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;
68 this.taskElement = taskElement;
69 this.taskType = taskType;
70 values = new Dictionary <string, object> ();
72 foreach (KeyValuePair <string, string> de in parameters) {
73 currentProperty = taskType.GetProperty (de.Key);
74 if (currentProperty == null)
75 throw new InvalidProjectFileException (String.Format ("Task does not have property \"{0}\" defined",
77 values.Add (de.Key, GetObjectFromString (de.Value, currentProperty.PropertyType));
80 properties = taskType.GetProperties ();
81 foreach (PropertyInfo pi in properties) {
82 if (pi.IsDefined (requiredAttribute, false) && values.ContainsKey (pi.Name) == false)
83 throw new InvalidProjectFileException ("Required property not set.");
85 if (values.ContainsKey (pi.Name))
86 InitializeParameter (pi, values [pi.Name]);
90 public bool Execute ()
92 return task.Execute ();
95 public void PublishOutput ()
97 XmlElement xmlElement;
98 PropertyInfo propertyInfo;
100 string taskParameter;
104 foreach (XmlNode xmlNode in taskElement.ChildNodes) {
105 if (xmlNode is XmlElement) {
106 xmlElement = (XmlElement) xmlNode;
108 if (xmlElement.Name != "Output")
109 throw new InvalidProjectFileException ("Only Output elements can be Task's child nodes.");
110 if (xmlElement.GetAttribute ("ItemName") != "" && xmlElement.GetAttribute ("PropertyName") != "")
111 throw new InvalidProjectFileException ("Only one of ItemName and ProperytyName attributes can be specified.");
112 if (xmlElement.GetAttribute ("TaskParameter") == "")
113 throw new InvalidProjectFileException ("TaskParameter attribute must be specified.");
115 taskParameter = xmlElement.GetAttribute ("TaskParameter");
116 itemName = xmlElement.GetAttribute ("ItemName");
117 propertyName = xmlElement.GetAttribute ("PropertyName");
119 propertyInfo = taskType.GetProperty (taskParameter);
120 if (propertyInfo == null)
121 throw new Exception ("Could not get property info.");
122 if (propertyInfo.IsDefined (outputAttribute, false) == false)
123 throw new Exception ("This is not output property.");
125 o = propertyInfo.GetValue (task, null);
129 if (itemName != String.Empty) {
130 PublishItemGroup (propertyInfo, o, itemName);
132 PublishProperty (propertyInfo, o, propertyName);
138 private void InitializeParameter (PropertyInfo propertyInfo, object value)
140 propertyInfo.SetValue (task, value, null);
143 private void PublishItemGroup (PropertyInfo propertyInfo,
147 BuildItemGroup newItems = CollectItemGroup (propertyInfo, o, itemName);
148 if (parentProject.EvaluatedItemsByName.Contains (itemName)) {
149 BuildItemGroup big = (BuildItemGroup) parentProject.EvaluatedItemsByName [itemName];
151 parentProject.EvaluatedItemsByName.Remove (itemName);
152 parentProject.EvaluatedItemsByName.Add (itemName, newItems);
154 parentProject.EvaluatedItemsByName.Add (itemName, newItems);
158 private void PublishProperty (PropertyInfo propertyInfo,
162 BuildProperty bp = CollectProperty (propertyInfo, o, propertyName);
163 parentProject.EvaluatedProperties.AddProperty (bp);
166 private BuildProperty CollectProperty (PropertyInfo propertyInfo, object o, string name)
168 string output = null;
171 if (propertyInfo == null)
172 throw new ArgumentNullException ("propertyInfo");
174 throw new ArgumentNullException ("o");
176 throw new ArgumentNullException ("name");
178 if (propertyInfo.PropertyType == typeof (ITaskItem)) {
179 ITaskItem item = (ITaskItem) o;
180 bp = ChangeType.TransformToBuildProperty (name, item);
181 } else if (propertyInfo.PropertyType == typeof (ITaskItem[])) {
182 ITaskItem[] items = (ITaskItem[]) o;
183 bp = ChangeType.TransformToBuildProperty (name, items);
185 if (propertyInfo.PropertyType.IsArray == true) {
186 output = ChangeType.TransformToString ((object[])o, propertyInfo.PropertyType);
188 output = ChangeType.TransformToString (o, propertyInfo.PropertyType);
190 bp = ChangeType.TransformToBuildProperty (name, output);
195 private BuildItemGroup CollectItemGroup (PropertyInfo propertyInfo, object o, string name)
200 if (propertyInfo == null)
201 throw new ArgumentNullException ("propertyInfo");
203 throw new ArgumentNullException ("o");
205 throw new ArgumentNullException ("name");
207 if (propertyInfo.PropertyType == typeof (ITaskItem)) {
208 ITaskItem item = (ITaskItem) o;
209 big = ChangeType.TransformToBuildItemGroup (name, item);
210 } else if (propertyInfo.PropertyType == typeof (ITaskItem[])) {
211 ITaskItem[] items = (ITaskItem[]) o;
212 big = ChangeType.TransformToBuildItemGroup (name, items);
214 if (propertyInfo.PropertyType.IsArray == true) {
215 temp = ChangeType.TransformToString ((object[]) o, propertyInfo.PropertyType);
217 temp = ChangeType.TransformToString (o, propertyInfo.PropertyType);
219 big = ChangeType.TransformToBuildItemGroup (name, temp);
224 private object GetObjectFromString (string raw, Type type)
229 e = new OldExpression (parentProject);
232 if (type == typeof (ITaskItem)) {
233 result = e.ConvertTo (typeof (ITaskItem));
234 } else if (type == typeof (ITaskItem[])) {
235 result = e.ConvertTo (typeof (ITaskItem[]));
237 result = e.ConvertTo (type);