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;
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;
43 Project parentProject;
45 static Type requiredAttribute;
46 static Type outputAttribute;
50 requiredAttribute = typeof (Microsoft.Build.Framework.RequiredAttribute);
51 outputAttribute = typeof (Microsoft.Build.Framework.OutputAttribute);
58 public void Prepare (ITask task, XmlElement taskElement,
59 IDictionary parameters, Type taskType)
62 PropertyInfo currentProperty;
63 PropertyInfo[] properties;
66 this.taskElement = taskElement;
67 values = new Hashtable ();
69 foreach (DictionaryEntry de in parameters) {
70 currentProperty = taskType.GetProperty ((string) de.Key);
71 if (currentProperty == null)
72 throw new InvalidProjectFileException (String.Format ("Task does not have property \"{0}\" defined",
74 values.Add ((string) de.Key, GetObjectFromString ((string) de.Value, currentProperty.PropertyType));
77 properties = taskType.GetProperties ();
78 foreach (PropertyInfo pi in properties) {
79 if (pi.IsDefined (requiredAttribute, false) && values.ContainsKey (pi.Name) == false)
80 throw new InvalidProjectFileException ("Required property not set.");
82 if (values.ContainsKey (pi.Name))
83 InitializeParameter (pi, values [pi.Name]);
87 public bool Execute ()
91 result = task.Execute ();
96 public void PublishOutput ()
98 XmlElement xmlElement;
99 PropertyInfo propertyInfo;
101 string taskParameter;
105 foreach (XmlNode xmlNode in taskElement.ChildNodes) {
106 if (xmlNode is XmlElement) {
107 xmlElement = (XmlElement) xmlNode;
109 if (xmlElement.Name != "Output")
110 throw new InvalidProjectFileException ("Only Output elements can be Task's child nodes.");
111 if (xmlElement.GetAttribute ("ItemName") != "" && xmlElement.GetAttribute ("PropertyName") != "")
112 throw new InvalidProjectFileException ("Only one of ItemName and ProperytyName attributes can be specified.");
113 if (xmlElement.GetAttribute ("TaskParameter") == "")
114 throw new InvalidProjectFileException ("TaskParameter attribute must be specified.");
116 taskParameter = xmlElement.GetAttribute ("TaskParameter");
117 itemName = xmlElement.GetAttribute ("ItemName");
118 propertyName = xmlElement.GetAttribute ("PropertyName");
120 propertyInfo = GetType ().GetProperty (taskParameter);
121 if (propertyInfo == null)
122 throw new Exception ("Could not get property info.");
123 if (propertyInfo.IsDefined (outputAttribute, false) == false)
124 throw new Exception ("This is not output property.");
126 o = propertyInfo.GetValue (task, null);
130 if (itemName != String.Empty) {
131 PublishItemGroup (propertyInfo, o, itemName);
133 PublishProperty (propertyInfo, o, propertyName);
139 private void InitializeParameter (PropertyInfo propertyInfo, object value)
141 propertyInfo.SetValue (task, value, null);
144 private void PublishItemGroup (PropertyInfo propertyInfo,
148 BuildItemGroup newItems = CollectItemGroup (propertyInfo, o, itemName);
149 if (parentProject.EvaluatedItemsByName.Contains (itemName)) {
150 BuildItemGroup big = (BuildItemGroup) parentProject.EvaluatedItemsByName [itemName];
152 parentProject.EvaluatedItemsByName.Remove (itemName);
153 parentProject.EvaluatedItemsByName.Add (itemName, newItems);
155 parentProject.EvaluatedItemsByName.Add (itemName, newItems);
159 private void PublishProperty (PropertyInfo propertyInfo,
163 BuildProperty bp = CollectProperty (propertyInfo, o, propertyName);
164 parentProject.EvaluatedProperties.AddFromExistingProperty (bp);
167 private BuildProperty CollectProperty (PropertyInfo propertyInfo, object o, string name)
169 string output = null;
172 if (propertyInfo == null)
173 throw new ArgumentNullException ("propertyInfo");
175 throw new ArgumentNullException ("o");
177 throw new ArgumentNullException ("name");
179 if (propertyInfo.PropertyType == typeof (ITaskItem)) {
180 ITaskItem item = (ITaskItem) o;
181 bp = ChangeType.TransformToBuildProperty (name, item);
182 } else if (propertyInfo.PropertyType == typeof (ITaskItem[])) {
183 ITaskItem[] items = (ITaskItem[]) o;
184 bp = ChangeType.TransformToBuildProperty (name, items);
186 if (propertyInfo.PropertyType.IsArray == true) {
187 output = ChangeType.TransformToString ((object[])o, propertyInfo.PropertyType);
189 output = ChangeType.TransformToString (o, propertyInfo.PropertyType);
191 bp = ChangeType.TransformToBuildProperty (name, output);
196 private BuildItemGroup CollectItemGroup (PropertyInfo propertyInfo, object o, string name)
201 if (propertyInfo == null)
202 throw new ArgumentNullException ("propertyInfo");
204 throw new ArgumentNullException ("o");
206 throw new ArgumentNullException ("name");
208 if (propertyInfo.PropertyType == typeof (ITaskItem)) {
209 ITaskItem item = (ITaskItem) o;
210 big = ChangeType.TransformToBuildItemGroup (name, item);
211 } else if (propertyInfo.PropertyType == typeof (ITaskItem[])) {
212 ITaskItem[] items = (ITaskItem[]) o;
213 big = ChangeType.TransformToBuildItemGroup (name, items);
215 if (propertyInfo.PropertyType.IsArray == true) {
216 temp = ChangeType.TransformToString ((object[]) o, propertyInfo.PropertyType);
218 temp = ChangeType.TransformToString (o, propertyInfo.PropertyType);
220 big = ChangeType.TransformToBuildItemGroup (name, temp);
225 private object GetObjectFromString (string raw, Type type)
230 e = new Expression (parentProject, raw);
232 if (type == typeof (ITaskItem)) {
233 result = (object) e.ToITaskItem ();
234 } else if (type == typeof (ITaskItem[])) {
235 result = (object) e.ToITaskItemArray ();
238 result = e.ToArray (type);
240 result = e.ToNonArray (type);