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) {
111 xmlElement = (XmlElement) xmlNode;
113 if (xmlElement.Name != "Output")
114 throw new InvalidProjectFileException ("Only Output elements can be Task's child nodes.");
115 if (xmlElement.GetAttribute ("ItemName") != String.Empty && xmlElement.GetAttribute ("PropertyName") != String.Empty)
116 throw new InvalidProjectFileException ("Only one of ItemName and ProperytyName attributes can be specified.");
117 if (xmlElement.GetAttribute ("TaskParameter") == String.Empty)
118 throw new InvalidProjectFileException ("TaskParameter attribute must be specified.");
120 taskParameter = xmlElement.GetAttribute ("TaskParameter");
121 itemName = xmlElement.GetAttribute ("ItemName");
122 propertyName = xmlElement.GetAttribute ("PropertyName");
124 propertyInfo = taskType.GetProperty (taskParameter);
125 if (propertyInfo == null)
126 throw new Exception ("Could not get property info.");
127 if (propertyInfo.IsDefined (outputAttribute, false) == false)
128 throw new Exception ("This is not output property.");
130 o = propertyInfo.GetValue (task, null);
134 if (itemName != String.Empty) {
135 PublishItemGroup (propertyInfo, o, itemName);
137 PublishProperty (propertyInfo, o, propertyName);
143 private void InitializeParameter (PropertyInfo propertyInfo, object value)
145 propertyInfo.SetValue (task, value, null);
148 private void PublishItemGroup (PropertyInfo propertyInfo,
152 BuildItemGroup newItems = CollectItemGroup (propertyInfo, o, itemName);
153 if (parentProject.EvaluatedItemsByName.Contains (itemName)) {
154 BuildItemGroup big = (BuildItemGroup) parentProject.EvaluatedItemsByName [itemName];
156 parentProject.EvaluatedItemsByName.Remove (itemName);
157 parentProject.EvaluatedItemsByName.Add (itemName, newItems);
159 parentProject.EvaluatedItemsByName.Add (itemName, newItems);
163 private void PublishProperty (PropertyInfo propertyInfo,
167 BuildProperty bp = CollectProperty (propertyInfo, o, propertyName);
168 parentProject.EvaluatedProperties.AddProperty (bp);
171 private BuildProperty CollectProperty (PropertyInfo propertyInfo, object o, string name)
173 string output = null;
176 if (propertyInfo == null)
177 throw new ArgumentNullException ("propertyInfo");
179 throw new ArgumentNullException ("o");
181 throw new ArgumentNullException ("name");
183 if (propertyInfo.PropertyType == typeof (ITaskItem)) {
184 ITaskItem item = (ITaskItem) o;
185 bp = ChangeType.TransformToBuildProperty (name, item);
186 } else if (propertyInfo.PropertyType == typeof (ITaskItem[])) {
187 ITaskItem[] items = (ITaskItem[]) o;
188 bp = ChangeType.TransformToBuildProperty (name, items);
190 if (propertyInfo.PropertyType.IsArray == true) {
191 output = ChangeType.TransformToString ((object[])o, propertyInfo.PropertyType);
193 output = ChangeType.TransformToString (o, propertyInfo.PropertyType);
195 bp = ChangeType.TransformToBuildProperty (name, output);
200 private BuildItemGroup CollectItemGroup (PropertyInfo propertyInfo, object o, string name)
205 if (propertyInfo == null)
206 throw new ArgumentNullException ("propertyInfo");
208 throw new ArgumentNullException ("o");
210 throw new ArgumentNullException ("name");
212 if (propertyInfo.PropertyType == typeof (ITaskItem)) {
213 ITaskItem item = (ITaskItem) o;
214 big = ChangeType.TransformToBuildItemGroup (name, item);
215 } else if (propertyInfo.PropertyType == typeof (ITaskItem[])) {
216 ITaskItem[] items = (ITaskItem[]) o;
217 big = ChangeType.TransformToBuildItemGroup (name, items);
219 if (propertyInfo.PropertyType.IsArray == true) {
220 temp = ChangeType.TransformToString ((object[]) o, propertyInfo.PropertyType);
222 temp = ChangeType.TransformToString (o, propertyInfo.PropertyType);
224 big = ChangeType.TransformToBuildItemGroup (name, temp);
229 private object GetObjectFromString (string raw, Type type)
234 e = new OldExpression (parentProject);
237 if ((string) e.ConvertTo (typeof (string)) == String.Empty)
240 result = e.ConvertTo (type);