2 // TaskEngine.cs: Class that executes each task.
5 // Marek Sieradzki (marek.sieradzki@gmail.com)
7 // (C) 2005 Marek Sieradzki
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
31 using System.Collections.Generic;
32 using System.Collections.Specialized;
33 using System.Reflection;
35 using Microsoft.Build.Framework;
36 using Microsoft.Build.Utilities;
38 namespace Microsoft.Build.BuildEngine {
39 internal class TaskEngine {
42 XmlElement taskElement;
44 Project parentProject;
46 static Type requiredAttribute;
47 static Type outputAttribute;
51 requiredAttribute = typeof (Microsoft.Build.Framework.RequiredAttribute);
52 outputAttribute = typeof (Microsoft.Build.Framework.OutputAttribute);
55 public TaskEngine (Project project)
57 parentProject = project;
60 public void Prepare (ITask task, XmlElement taskElement,
61 IDictionary <string, string> parameters, Type taskType)
63 Dictionary <string, object> values;
64 PropertyInfo currentProperty;
65 PropertyInfo[] properties;
69 this.taskElement = taskElement;
70 this.taskType = taskType;
71 values = new Dictionary <string, object> ();
73 foreach (KeyValuePair <string, string> de in parameters) {
74 currentProperty = taskType.GetProperty (de.Key);
75 if (currentProperty == null)
76 throw new InvalidProjectFileException (String.Format ("Task does not have property \"{0}\" defined",
79 value = GetObjectFromString (de.Value, currentProperty.PropertyType);
82 values.Add (de.Key, value);
85 properties = taskType.GetProperties ();
86 foreach (PropertyInfo pi in properties) {
87 if (pi.IsDefined (requiredAttribute, false) && values.ContainsKey (pi.Name) == false)
88 throw new InvalidProjectFileException ("Required property not set.");
90 if (values.ContainsKey (pi.Name))
91 InitializeParameter (pi, values [pi.Name]);
95 public bool Execute ()
97 return task.Execute ();
100 public void PublishOutput ()
102 XmlElement xmlElement;
103 PropertyInfo propertyInfo;
105 string taskParameter;
109 foreach (XmlNode xmlNode in taskElement.ChildNodes) {
110 if (!(xmlNode is XmlElement))
113 xmlElement = (XmlElement) xmlNode;
115 if (xmlElement.Name != "Output")
116 throw new InvalidProjectFileException ("Only Output elements can be Task's child nodes.");
117 if (xmlElement.GetAttribute ("ItemName") != String.Empty && xmlElement.GetAttribute ("PropertyName") != String.Empty)
118 throw new InvalidProjectFileException ("Only one of ItemName and PropertyName attributes can be specified.");
119 if (xmlElement.GetAttribute ("TaskParameter") == String.Empty)
120 throw new InvalidProjectFileException ("TaskParameter attribute must be specified.");
122 taskParameter = xmlElement.GetAttribute ("TaskParameter");
123 itemName = xmlElement.GetAttribute ("ItemName");
124 propertyName = xmlElement.GetAttribute ("PropertyName");
126 propertyInfo = taskType.GetProperty (taskParameter);
127 if (propertyInfo == null)
128 throw new Exception ("Could not get property info.");
129 if (!propertyInfo.IsDefined (outputAttribute, false))
130 throw new Exception ("This is not output property.");
132 o = propertyInfo.GetValue (task, null);
136 if (itemName != String.Empty) {
137 PublishItemGroup (propertyInfo, o, itemName);
139 PublishProperty (propertyInfo, o, propertyName);
144 void InitializeParameter (PropertyInfo propertyInfo, object value)
146 propertyInfo.SetValue (task, value, null);
149 void PublishItemGroup (PropertyInfo propertyInfo,
153 BuildItemGroup newItems = CollectItemGroup (propertyInfo, o, itemName);
155 if (parentProject.EvaluatedItemsByName.ContainsKey (itemName)) {
156 BuildItemGroup big = parentProject.EvaluatedItemsByName [itemName];
158 parentProject.EvaluatedItemsByName.Remove (itemName);
159 parentProject.EvaluatedItemsByName.Add (itemName, newItems);
161 parentProject.EvaluatedItemsByName.Add (itemName, newItems);
163 foreach (BuildItem bi in newItems)
164 parentProject.EvaluatedItems.AddItem (bi);
167 void PublishProperty (PropertyInfo propertyInfo,
171 BuildProperty bp = CollectProperty (propertyInfo, o, propertyName);
172 parentProject.EvaluatedProperties.AddProperty (bp);
175 BuildProperty CollectProperty (PropertyInfo propertyInfo, object o, string name)
177 string output = null;
180 if (propertyInfo == null)
181 throw new ArgumentNullException ("propertyInfo");
183 throw new ArgumentNullException ("o");
185 throw new ArgumentNullException ("name");
187 if (propertyInfo.PropertyType == typeof (ITaskItem)) {
188 ITaskItem item = (ITaskItem) o;
189 bp = ChangeType.TransformToBuildProperty (name, item);
190 } else if (propertyInfo.PropertyType == typeof (ITaskItem[])) {
191 ITaskItem[] items = (ITaskItem[]) o;
192 bp = ChangeType.TransformToBuildProperty (name, items);
194 if (propertyInfo.PropertyType.IsArray == true) {
195 output = ChangeType.TransformToString ((object[])o, propertyInfo.PropertyType);
197 output = ChangeType.TransformToString (o, propertyInfo.PropertyType);
199 bp = ChangeType.TransformToBuildProperty (name, output);
204 BuildItemGroup CollectItemGroup (PropertyInfo propertyInfo, object o, string name)
209 if (propertyInfo == null)
210 throw new ArgumentNullException ("propertyInfo");
212 throw new ArgumentNullException ("o");
214 throw new ArgumentNullException ("name");
216 if (propertyInfo.PropertyType == typeof (ITaskItem)) {
217 ITaskItem item = (ITaskItem) o;
218 big = ChangeType.TransformToBuildItemGroup (name, item);
219 } else if (propertyInfo.PropertyType == typeof (ITaskItem[])) {
220 ITaskItem[] items = (ITaskItem[]) o;
221 big = ChangeType.TransformToBuildItemGroup (name, items);
223 if (propertyInfo.PropertyType.IsArray == true) {
224 temp = ChangeType.TransformToString ((object[]) o, propertyInfo.PropertyType);
226 temp = ChangeType.TransformToString (o, propertyInfo.PropertyType);
228 big = ChangeType.TransformToBuildItemGroup (name, temp);
233 object GetObjectFromString (string raw, Type type)
238 e = new Expression ();
241 if ((string) e.ConvertTo (parentProject, typeof (string)) == String.Empty)
244 result = e.ConvertTo (parentProject, type);