2006-12-16 Marek Sieradzki <marek.sieradzki@gmail.com>
[mono.git] / mcs / class / Microsoft.Build.Engine / Microsoft.Build.BuildEngine / BatchingImpl.cs
1 //
2 // BatchingImpl.cs: Class that implements BatchingAlgorithm from the wiki.
3 //
4 // Author:
5 //   Marek Sieradzki (marek.sieradzki@gmail.com)
6 // 
7 // (C) 2005 Marek Sieradzki
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28 #if NET_2_0
29
30 using System;
31 using System.IO;
32 using System.Xml;
33
34 namespace Microsoft.Build.BuildEngine {
35         internal class BatchingImpl {
36         
37                 string          inputs;
38                 string          outputs;
39                 Project         project;
40         
41                 public BatchingImpl (Project project, XmlElement targetElement)
42                 {
43                         if (targetElement == null)
44                                 throw new ArgumentNullException ("targetElement");
45                         if (project == null)
46                                 throw new ArgumentNullException ("project");
47                 
48                         this.project = project;
49                         
50                         inputs = targetElement.GetAttribute ("Inputs");
51                         outputs = targetElement.GetAttribute ("Outputs");
52                 }
53                 
54                 public bool BuildNeeded ()
55                 {
56                         // FIXME: change this to ITaskItem instead of string
57                 
58                         Expression inputExpr, outputExpr;
59                         string[] inputFiles, outputFiles;
60                         DateTime oldestInput, youngestOutput;
61                 
62                         if (inputs == String.Empty) {
63                                 return true;
64                         }
65                         if (outputs == String.Empty) {
66                                 return true;
67                         }
68                         
69                         inputExpr = new Expression ();
70                         inputExpr.Parse (inputs);
71                         outputExpr = new Expression ();
72                         outputExpr.Parse (outputs);
73                         
74                         inputFiles = (string[]) inputExpr.ConvertTo (project, typeof (string[]));
75                         outputFiles = (string[]) outputExpr.ConvertTo (project, typeof (string[]));
76                         
77                         if (inputFiles == null) {
78                                 return true;
79                         }
80                         if (outputFiles == null) {
81                                 return true;
82                         }
83                         if (inputFiles.Length == 0) {
84                                 return true;
85                         }
86                         if (outputFiles.Length == 0) {
87                                 return true;
88                         }
89                         
90                         if (File.Exists (inputFiles [0])) {
91                                 oldestInput = File.GetLastWriteTime (inputFiles [0]);
92                         } else {
93                                 return true;
94                         }
95                         if (File.Exists (outputFiles [0])) {
96                                 youngestOutput = File.GetLastWriteTime (outputFiles [0]);
97                         } else {
98                                 return true;
99                         }
100                                 
101                         foreach (string file in inputFiles) {
102                                 if (file.Trim () == String.Empty)
103                                         continue;
104                         
105                                 if (File.Exists (file.Trim ())) {
106                                         if (File.GetLastWriteTime (file.Trim ()) > oldestInput)
107                                                 oldestInput = File.GetLastWriteTime (file.Trim ());
108                                 } else {
109                                         return true;
110                                 }
111                         }
112                         foreach (string file in outputFiles) {
113                                 if (file.Trim () == String.Empty)
114                                         continue;
115                         
116                                 if (File.Exists (file.Trim ())) {
117                                         if (File.GetLastWriteTime (file.Trim ()) < youngestOutput)
118                                                 youngestOutput = File.GetLastWriteTime (file.Trim ());
119                                 } else {
120                                         return true;
121                                 }
122                         }
123                         
124                         if (oldestInput > youngestOutput) {
125                                 return true;
126                         }
127                         else {
128                                 return false;
129                         }
130                 }
131                 
132                 // FIXME: should do everything from task batching specification, not just run task once
133                 public bool BatchBuildTask (BuildTask buildTask)
134                 {
135                         if (buildTask.Condition == String.Empty)
136                                 return buildTask.Execute ();
137                         
138                         ConditionExpression ce = ConditionParser.ParseCondition (buildTask.Condition);
139                         
140                         if (ce.BoolEvaluate (project))
141                                 return buildTask.Execute ();
142                         else
143                         // FIXME: skipped, it should be logged
144                                 return true;
145                         
146                 }
147         }
148 }
149
150 #endif