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);
54 public TaskEngine (Project project)
56 parentProject = project;
59 public void Prepare (ITask task, XmlElement taskElement,
60 IDictionary parameters, Type taskType)
63 PropertyInfo currentProperty;
64 PropertyInfo[] properties;
67 this.taskElement = taskElement;
68 values = new Hashtable ();
70 foreach (DictionaryEntry de in parameters) {
71 currentProperty = taskType.GetProperty ((string) de.Key);
72 if (currentProperty == null)
73 throw new InvalidProjectFileException (String.Format ("Task does not have property \"{0}\" defined",
75 values.Add ((string) de.Key, GetObjectFromString ((string) de.Value, currentProperty.PropertyType));
78 properties = taskType.GetProperties ();
79 foreach (PropertyInfo pi in properties) {
80 if (pi.IsDefined (requiredAttribute, false) && values.ContainsKey (pi.Name) == false)
81 throw new InvalidProjectFileException ("Required property not set.");
83 if (values.ContainsKey (pi.Name))
84 InitializeParameter (pi, values [pi.Name]);
88 public bool Execute ()
90 return task.Execute ();
93 public void PublishOutput ()
95 XmlElement xmlElement;
96 PropertyInfo propertyInfo;
102 foreach (XmlNode xmlNode in taskElement.ChildNodes) {
103 if (xmlNode is XmlElement) {
104 xmlElement = (XmlElement) xmlNode;
106 if (xmlElement.Name != "Output")
107 throw new InvalidProjectFileException ("Only Output elements can be Task's child nodes.");
108 if (xmlElement.GetAttribute ("ItemName") != "" && xmlElement.GetAttribute ("PropertyName") != "")
109 throw new InvalidProjectFileException ("Only one of ItemName and ProperytyName attributes can be specified.");
110 if (xmlElement.GetAttribute ("TaskParameter") == "")
111 throw new InvalidProjectFileException ("TaskParameter attribute must be specified.");
113 taskParameter = xmlElement.GetAttribute ("TaskParameter");
114 itemName = xmlElement.GetAttribute ("ItemName");
115 propertyName = xmlElement.GetAttribute ("PropertyName");
117 propertyInfo = GetType ().GetProperty (taskParameter);
118 if (propertyInfo == null)
119 throw new Exception ("Could not get property info.");
120 if (propertyInfo.IsDefined (outputAttribute, false) == false)
121 throw new Exception ("This is not output property.");
123 o = propertyInfo.GetValue (task, null);
127 if (itemName != String.Empty) {
128 PublishItemGroup (propertyInfo, o, itemName);
130 PublishProperty (propertyInfo, o, propertyName);
136 private void InitializeParameter (PropertyInfo propertyInfo, object value)
138 propertyInfo.SetValue (task, value, null);
141 private void PublishItemGroup (PropertyInfo propertyInfo,
145 BuildItemGroup newItems = CollectItemGroup (propertyInfo, o, itemName);
146 if (parentProject.EvaluatedItemsByName.Contains (itemName)) {
147 BuildItemGroup big = (BuildItemGroup) parentProject.EvaluatedItemsByName [itemName];
149 parentProject.EvaluatedItemsByName.Remove (itemName);
150 parentProject.EvaluatedItemsByName.Add (itemName, newItems);
152 parentProject.EvaluatedItemsByName.Add (itemName, newItems);
156 private void PublishProperty (PropertyInfo propertyInfo,
160 BuildProperty bp = CollectProperty (propertyInfo, o, propertyName);
161 parentProject.EvaluatedProperties.AddFromExistingProperty (bp);
164 private BuildProperty CollectProperty (PropertyInfo propertyInfo, object o, string name)
166 string output = null;
169 if (propertyInfo == null)
170 throw new ArgumentNullException ("propertyInfo");
172 throw new ArgumentNullException ("o");
174 throw new ArgumentNullException ("name");
176 if (propertyInfo.PropertyType == typeof (ITaskItem)) {
177 ITaskItem item = (ITaskItem) o;
178 bp = ChangeType.TransformToBuildProperty (name, item);
179 } else if (propertyInfo.PropertyType == typeof (ITaskItem[])) {
180 ITaskItem[] items = (ITaskItem[]) o;
181 bp = ChangeType.TransformToBuildProperty (name, items);
183 if (propertyInfo.PropertyType.IsArray == true) {
184 output = ChangeType.TransformToString ((object[])o, propertyInfo.PropertyType);
186 output = ChangeType.TransformToString (o, propertyInfo.PropertyType);
188 bp = ChangeType.TransformToBuildProperty (name, output);
193 private BuildItemGroup CollectItemGroup (PropertyInfo propertyInfo, object o, string name)
198 if (propertyInfo == null)
199 throw new ArgumentNullException ("propertyInfo");
201 throw new ArgumentNullException ("o");
203 throw new ArgumentNullException ("name");
205 if (propertyInfo.PropertyType == typeof (ITaskItem)) {
206 ITaskItem item = (ITaskItem) o;
207 big = ChangeType.TransformToBuildItemGroup (name, item);
208 } else if (propertyInfo.PropertyType == typeof (ITaskItem[])) {
209 ITaskItem[] items = (ITaskItem[]) o;
210 big = ChangeType.TransformToBuildItemGroup (name, items);
212 if (propertyInfo.PropertyType.IsArray == true) {
213 temp = ChangeType.TransformToString ((object[]) o, propertyInfo.PropertyType);
215 temp = ChangeType.TransformToString (o, propertyInfo.PropertyType);
217 big = ChangeType.TransformToBuildItemGroup (name, temp);
222 private object GetObjectFromString (string raw, Type type)
227 e = new Expression (parentProject, raw);
229 if (type == typeof (ITaskItem)) {
230 result = (object) e.ToITaskItem ();
231 } else if (type == typeof (ITaskItem[])) {
232 result = (object) e.ToITaskItemArray ();
235 result = e.ToArray (type);
237 result = e.ToNonArray (type);