This commit was manufactured by cvs2svn to create branch 'mono-1-0'.
[mono.git] / mcs / nant / src / Task.cs
1 // NAnt - A .NET build tool\r
2 // Copyright (C) 2001 Gerry Shaw\r
3 //\r
4 // This program is free software; you can redistribute it and/or modify\r
5 // it under the terms of the GNU General Public License as published by\r
6 // the Free Software Foundation; either version 2 of the License, or\r
7 // (at your option) any later version.\r
8 //\r
9 // This program is distributed in the hope that it will be useful,\r
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
12 // GNU General Public License for more details.\r
13 //\r
14 // You should have received a copy of the GNU General Public License\r
15 // along with this program; if not, write to the Free Software\r
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
17 //\r
18 // Gerry Shaw (gerry_shaw@yahoo.com)\r
19 // Mike Krueger (mike@icsharpcode.net)\r
20 // Ian MacLean (ian_maclean@another.com)\r
21 \r
22 namespace SourceForge.NAnt {\r
23 \r
24     using System;\r
25     using System.Reflection;\r
26     using System.Xml;\r
27 \r
28     public abstract class Task {\r
29 \r
30         /// <summary>Gets and sets how much spacing log prefix names will be padded.</summary>\r
31         /// <remarks>\r
32         /// Includes characters for a space after the name and the [ ] brackets. Default is 12.\r
33         /// </remarks>\r
34         public static int LogPrefixPadding = Log.IndentSize;\r
35 \r
36         Location _location = Location.UnknownLocation;\r
37         Target _target = null;\r
38         Project _project = null;\r
39 \r
40         /// <summary>\r
41         /// Location in build file where task is defined.\r
42         /// </summary>\r
43         protected Location Location {\r
44             get { return _location; }\r
45             set { _location = value; }\r
46         }\r
47 \r
48         public string Name {\r
49             get {\r
50                 string name = null;\r
51                 TaskNameAttribute taskName = (TaskNameAttribute) Attribute.GetCustomAttribute(GetType(), typeof(TaskNameAttribute));\r
52                 if (taskName != null) {\r
53                     name = taskName.Name;\r
54                 }\r
55                 return name;\r
56             }\r
57         }\r
58 \r
59         public string LogPrefix {\r
60             get {\r
61                 string prefix = "[" + Name + "] ";\r
62                 return prefix.PadLeft(LogPrefixPadding);\r
63             }\r
64         }\r
65 \r
66         public Target Target {\r
67             get { return _target; }\r
68             set { _target = value; }\r
69         }\r
70 \r
71         public Project Project {\r
72             get { return _project; }\r
73             set { _project = value; }\r
74         }\r
75 \r
76         protected void AutoInitializeAttributes(XmlNode taskNode) {\r
77 \r
78             // TODO: BooleanValidatorAttribute and Int32ValidatorAttribute implementation in Task\r
79 \r
80             // Go down the inheritance tree to find the private fields in the object.\r
81             // We are looking for task attributes to initialize.\r
82             Type currentType = GetType();\r
83             while (currentType != typeof(object)) {\r
84                 FieldInfo[] fieldInfoArray = currentType.GetFields(BindingFlags.NonPublic|BindingFlags.Instance);\r
85                 foreach (FieldInfo fieldInfo in fieldInfoArray) {\r
86 \r
87                     // process TaskAttribute attributes\r
88                     TaskAttributeAttribute taskAttribute = (TaskAttributeAttribute) Attribute.GetCustomAttribute(fieldInfo, typeof(TaskAttributeAttribute));\r
89                     if (taskAttribute != null) {\r
90 \r
91                         // get value from xml file\r
92                         XmlNode node = taskNode.SelectSingleNode("@" + taskAttribute.Name);\r
93 \r
94                         // check if its required\r
95                         if (node == null && taskAttribute.Required) {\r
96                             // TODO: add Location to exception\r
97                             throw new BuildException(String.Format("{0} is a required attribute.", taskAttribute.Name), Location);\r
98                         }\r
99 \r
100                         if (node != null) {\r
101                             fieldInfo.SetValue(this, Convert.ChangeType(node.Value, fieldInfo.FieldType));\r
102                         }\r
103                     }\r
104 \r
105                     // process TaskFileSet attributes\r
106                     TaskFileSetAttribute fileSetAttribute = (TaskFileSetAttribute) Attribute.GetCustomAttribute(fieldInfo, typeof(TaskFileSetAttribute));\r
107                     if (fileSetAttribute != null) {\r
108                         // have file set initialize itself\r
109                         FileSet fileSet = (FileSet) fieldInfo.GetValue(this);\r
110 \r
111                         // set task fileset belongs to\r
112                         fileSet.Task = this;\r
113 \r
114                         // load values from build file\r
115                         XmlNode fileSetNode = taskNode.SelectSingleNode(fileSetAttribute.Name);\r
116                         if (fileSetNode != null) {\r
117 \r
118                             XmlNode baseDirectoryNode = fileSetNode.SelectSingleNode("@basedir");\r
119                             if (baseDirectoryNode != null) {\r
120                                 fileSet.BaseDirectory = baseDirectoryNode.Value;\r
121                             }\r
122 \r
123                             foreach (XmlNode node in fileSetNode.SelectNodes("includes")) {\r
124                                 string pathname = node.SelectSingleNode("@name").Value;\r
125                                 fileSet.Includes.Add(pathname);\r
126                             }\r
127 \r
128                             foreach (XmlNode node in fileSetNode.SelectNodes("excludes")) {\r
129                                 fileSet.Excludes.Add(node.SelectSingleNode("@name").Value);\r
130                             }\r
131                         }\r
132                     }\r
133                 }\r
134                 currentType = currentType.BaseType;\r
135             }\r
136         }\r
137 \r
138         protected void AutoExpandAttributes() {\r
139 \r
140             // Go down the inheritance tree to find the private fields in the object.\r
141             // We are looking for task attributes to initialize.\r
142             Type currentType = GetType();\r
143             while (currentType != typeof(object)) {\r
144                 FieldInfo[] fieldInfoArray = currentType.GetFields(BindingFlags.NonPublic|BindingFlags.Instance);\r
145                 foreach (FieldInfo fieldInfo in fieldInfoArray) {\r
146 \r
147                     // proces string parameters\r
148                     TaskAttributeAttribute taskAttribute = (TaskAttributeAttribute) Attribute.GetCustomAttribute(fieldInfo, typeof(TaskAttributeAttribute));\r
149                     if (taskAttribute != null) {\r
150                         if (taskAttribute.ExpandText) {\r
151                             string value = (string) fieldInfo.GetValue(this);\r
152                             value = Project.ExpandText(value);\r
153                             fieldInfo.SetValue(this, value);\r
154                         }\r
155 \r
156                         // if a field also has a validator attribute then ensure that value is correct\r
157                         ValidatorAttribute[] validators = (ValidatorAttribute[]) Attribute.GetCustomAttributes(fieldInfo, typeof(ValidatorAttribute));\r
158                         foreach (ValidatorAttribute validator in validators) {\r
159                             string errorMessage = validator.Validate(fieldInfo.GetValue(this));\r
160                             if (errorMessage != null) {\r
161                                 throw new BuildException(String.Format("Error processing '{0}' attribute in <{1}> task: {2}", taskAttribute.Name, Name, errorMessage), Location);\r
162                             }\r
163                         }\r
164                     }\r
165                 }\r
166                 currentType = currentType.BaseType;\r
167             }\r
168         }\r
169 \r
170         public void Initialize(XmlNode taskNode) {\r
171             Initialize(taskNode, null);\r
172         }\r
173 \r
174         public void Initialize(XmlNode taskNode, Location location) {\r
175             if (location != null) {\r
176                 _location = location;\r
177             }\r
178             AutoInitializeAttributes(taskNode);\r
179             InitializeTask(taskNode);\r
180         }\r
181 \r
182         public void Execute() {\r
183             AutoExpandAttributes();\r
184             ExecuteTask();\r
185         }\r
186 \r
187         protected virtual void InitializeTask(XmlNode taskNode) {\r
188         }\r
189 \r
190         protected abstract void ExecuteTask();\r
191     }\r
192 }\r