2 // TaskElement.cs: Represents XML element that is a 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 // FIXME: remove this class
40 /*public class TaskElement {
42 XmlAttribute condition;
43 XmlAttribute continueOnError;
44 XmlElement taskElement;
50 static Type requiredAttribute;
51 static Type outputAttribute;
55 this.isImported = false;
60 requiredAttribute = typeof (Microsoft.Build.Framework.RequiredAttribute);
61 outputAttribute = typeof (Microsoft.Build.Framework.OutputAttribute);
64 public bool Execute ()
68 string[] parameterNames;
69 PropertyInfo[] properties;
70 PropertyInfo currentProperty;
71 Hashtable values = new Hashtable ();
77 task = (Task)Activator.CreateInstance (Type);
78 task.BuildEngine = new BuildEngine (parentTarget.Project.ParentEngine, 0, 0,
79 ContinueOnError, parentTarget.Project.FullFileName);
80 parameterNames = GetParameterNames ();
81 foreach (string parameter in parameterNames) {
82 currentProperty = GetType ().GetProperty (parameter);
83 if (currentProperty == null)
84 throw new InvalidProjectFileException (String.Format ("Task does not have property \"{0}\" defined",
86 rawParameter = GetParameterValue (parameter);
87 value = GetObjectFromString (rawParameter, currentProperty.PropertyType);
88 values.Add (parameter, value);
91 properties = GetType().GetProperties ();
92 foreach (PropertyInfo pi in properties) {
93 if (pi.IsDefined (requiredAttribute, false) && values.ContainsKey (pi.Name) == false) {
94 throw new InvalidProjectFileException ("Required property not set.");
96 if (values.ContainsKey (pi.Name)) {
97 pi.SetValue (task, values [pi.Name], null);
101 result = task.Execute ();
105 foreach (XmlNode xn in taskElement.ChildNodes) {
106 if (xn is XmlElement) {
107 XmlElement xe = (XmlElement) xn;
109 string property, parameter, item;
113 if (xe.Name != "Output")
114 throw new InvalidProjectFileException ("Only Output elements can be Task's child nodes.");
115 if (xe.GetAttribute ("ItemName") != "" && xe.GetAttribute ("PropertyName") != "")
116 throw new InvalidProjectFileException ("Only one of ItemName and ProperytyName attributes can be specified.");
117 if (xe.GetAttribute ("TaskParameter") == "")
118 throw new InvalidProjectFileException ("TaskParameter attribute must be specified.");
120 property = xe.GetAttribute ("PropertyName");
121 parameter = xe.GetAttribute ("TaskParameter");
122 item = xe.GetAttribute ("ItemName");
123 p = parentTarget.Project;
125 pi = GetType ().GetProperty (parameter);
127 throw new Exception ("Could not get property info.");
128 if (pi.IsDefined (outputAttribute, false) == false)
129 throw new Exception ("This is not output property.");
131 o = pi.GetValue (task, null);
134 if (xe.GetAttribute ("ItemName") != "") {
135 BuildItemGroup newItems = HandleItemGroup (pi, o, item);
136 if (p.EvaluatedItemsByName.Contains (item)) {
137 BuildItemGroup big = (BuildItemGroup) p.EvaluatedItemsByName [item];
139 p.EvaluatedItemsByName.Remove (item);
140 p.EvaluatedItemsByName.Add (item, newItems);
142 p.EvaluatedItemsByName.Add (item, newItems);
145 BuildProperty bp = HandleProperty (pi, o, property);
146 p.EvaluatedProperties.AddFromExistingProperty (bp);
153 LogTaskFinished (result);
158 private BuildProperty HandleProperty (PropertyInfo propertyInfo, object o, string name)
160 string output = null;
163 if (propertyInfo == null)
164 throw new ArgumentNullException ("propertyInfo");
166 throw new ArgumentNullException ("o");
168 throw new ArgumentNullException ("name");
170 if (propertyInfo.PropertyType == typeof (ITaskItem)) {
171 ITaskItem item = (ITaskItem) o;
172 bp = ChangeType.TransformToBuildProperty (name, item);
173 } else if (propertyInfo.PropertyType == typeof (ITaskItem[])) {
174 ITaskItem[] items = (ITaskItem[]) o;
175 bp = ChangeType.TransformToBuildProperty (name, items);
177 if (propertyInfo.PropertyType.IsArray == true) {
178 output = ChangeType.TransformToString ((object[])o, propertyInfo.PropertyType);
180 output = ChangeType.TransformToString (o, propertyInfo.PropertyType);
182 bp = ChangeType.TransformToBuildProperty (name, output);
187 private BuildItemGroup HandleItemGroup (PropertyInfo propertyInfo, object o, string name)
192 if (propertyInfo == null)
193 throw new ArgumentNullException ("propertyInfo");
195 throw new ArgumentNullException ("o");
197 throw new ArgumentNullException ("name");
199 if (propertyInfo.PropertyType == typeof (ITaskItem)) {
200 ITaskItem item = (ITaskItem) o;
201 big = ChangeType.TransformToBuildItemGroup (name, item);
202 } else if (propertyInfo.PropertyType == typeof (ITaskItem[])) {
203 ITaskItem[] items = (ITaskItem[]) o;
204 big = ChangeType.TransformToBuildItemGroup (name, items);
206 if (propertyInfo.PropertyType.IsArray == true) {
207 temp = ChangeType.TransformToString ((object[]) o, propertyInfo.PropertyType);
209 temp = ChangeType.TransformToString (o, propertyInfo.PropertyType);
211 big = ChangeType.TransformToBuildItemGroup (name, temp);
216 public string[] GetParameterNames ()
218 int attributesCount = 0;
219 ArrayList tempNames = new ArrayList ();
222 foreach (XmlAttribute xmlAttribute in taskElement.Attributes) {
223 if (xmlAttribute.Name == "Condition")
225 if (xmlAttribute.Name == "ContinueOnError")
227 tempNames.Add (xmlAttribute.Name);
229 names = new string [tempNames.Count];
230 foreach (string name in tempNames)
231 names [attributesCount++] = name;
235 public string GetParameterValue (string attributeName)
237 return taskElement.GetAttribute (attributeName);
240 private object GetObjectFromString (string raw, Type type)
245 e = new Expression (parentTarget.Project, raw);
247 if (type == typeof (ITaskItem)) {
248 result = (object) e.ToITaskItem ();
249 } else if (type == typeof (ITaskItem[])) {
250 result = (object) e.ToITaskItemArray ();
253 result = e.ToArray (type);
255 result = e.ToNonArray (type);
262 public void SetParameterValue (string parameterName,
263 string parameterValue)
265 taskElement.SetAttribute (parameterName, parameterValue);
268 internal void BindToXml (XmlElement taskElement,
271 if (taskElement == null)
272 throw new ArgumentNullException ("taskElement");
273 if (parentTarget == null)
274 throw new ArgumentNullException ("parentTarget");
275 this.taskElement = taskElement;
276 this.parentTarget = parentTarget;
277 this.condition = taskElement.GetAttributeNode ("Condition");
278 this.continueOnError = taskElement.GetAttributeNode ("ContinueOnError");
279 this.name = taskElement.Name;
282 private void LogTaskStarted ()
284 TaskStartedEventArgs tsea = new TaskStartedEventArgs ("Task started.", null, parentTarget.Project.FullFileName,
285 parentTarget.Project.FullFileName, taskElement.Name);
286 parentTarget.Project.ParentEngine.EventSource.FireTaskStarted (this, tsea);
289 private void LogTaskFinished (bool succeeded)
291 TaskFinishedEventArgs tfea = new TaskFinishedEventArgs ("Task finished.", null, parentTarget.Project.FullFileName,
292 parentTarget.Project.FullFileName, taskElement.Name, succeeded);
293 parentTarget.Project.ParentEngine.EventSource.FireTaskFinished (this, tfea);
296 public string Condition {
297 get { return condition.Value; }
298 set { condition.Value = value; }
301 public bool ContinueOnError {
303 // FIXME: insert here text parsing
304 if (continueOnError == null)
307 return Boolean.Parse (continueOnError.Value);
310 continueOnError.Value = value.ToString ();
314 public object HostObject {
331 return parentTarget.Project.TaskDatabase.GetTypeFromClassName (name);