1 // NAnt - A .NET build tool
\r
2 // Copyright (C) 2001 Gerry Shaw
\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
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
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
18 // Gerry Shaw (gerry_shaw@yahoo.com)
\r
19 // Mike Krueger (mike@icsharpcode.net)
\r
20 // Ian MacLean (ian_maclean@another.com)
\r
22 namespace SourceForge.NAnt {
\r
25 using System.Reflection;
\r
28 public abstract class Task {
\r
30 /// <summary>Gets and sets how much spacing log prefix names will be padded.</summary>
\r
32 /// Includes characters for a space after the name and the [ ] brackets. Default is 12.
\r
34 public static int LogPrefixPadding = Log.IndentSize;
\r
36 Location _location = Location.UnknownLocation;
\r
37 Target _target = null;
\r
38 Project _project = null;
\r
41 /// Location in build file where task is defined.
\r
43 protected Location Location {
\r
44 get { return _location; }
\r
45 set { _location = value; }
\r
48 public string Name {
\r
51 TaskNameAttribute taskName = (TaskNameAttribute) Attribute.GetCustomAttribute(GetType(), typeof(TaskNameAttribute));
\r
52 if (taskName != null) {
\r
53 name = taskName.Name;
\r
59 public string LogPrefix {
\r
61 string prefix = "[" + Name + "] ";
\r
62 return prefix.PadLeft(LogPrefixPadding);
\r
66 public Target Target {
\r
67 get { return _target; }
\r
68 set { _target = value; }
\r
71 public Project Project {
\r
72 get { return _project; }
\r
73 set { _project = value; }
\r
76 protected void AutoInitializeAttributes(XmlNode taskNode) {
\r
78 // TODO: BooleanValidatorAttribute and Int32ValidatorAttribute implementation in Task
\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
87 // process TaskAttribute attributes
\r
88 TaskAttributeAttribute taskAttribute = (TaskAttributeAttribute) Attribute.GetCustomAttribute(fieldInfo, typeof(TaskAttributeAttribute));
\r
89 if (taskAttribute != null) {
\r
91 // get value from xml file
\r
92 XmlNode node = taskNode.SelectSingleNode("@" + taskAttribute.Name);
\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
100 if (node != null) {
\r
101 fieldInfo.SetValue(this, Convert.ChangeType(node.Value, fieldInfo.FieldType));
\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
111 // set task fileset belongs to
\r
112 fileSet.Task = this;
\r
114 // load values from build file
\r
115 XmlNode fileSetNode = taskNode.SelectSingleNode(fileSetAttribute.Name);
\r
116 if (fileSetNode != null) {
\r
118 XmlNode baseDirectoryNode = fileSetNode.SelectSingleNode("@basedir");
\r
119 if (baseDirectoryNode != null) {
\r
120 fileSet.BaseDirectory = baseDirectoryNode.Value;
\r
123 foreach (XmlNode node in fileSetNode.SelectNodes("includes")) {
\r
124 string pathname = node.SelectSingleNode("@name").Value;
\r
125 fileSet.Includes.Add(pathname);
\r
128 foreach (XmlNode node in fileSetNode.SelectNodes("excludes")) {
\r
129 fileSet.Excludes.Add(node.SelectSingleNode("@name").Value);
\r
134 currentType = currentType.BaseType;
\r
138 protected void AutoExpandAttributes() {
\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
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
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
166 currentType = currentType.BaseType;
\r
170 public void Initialize(XmlNode taskNode) {
\r
171 Initialize(taskNode, null);
\r
174 public void Initialize(XmlNode taskNode, Location location) {
\r
175 if (location != null) {
\r
176 _location = location;
\r
178 AutoInitializeAttributes(taskNode);
\r
179 InitializeTask(taskNode);
\r
182 public void Execute() {
\r
183 AutoExpandAttributes();
\r
187 protected virtual void InitializeTask(XmlNode taskNode) {
\r
190 protected abstract void ExecuteTask();
\r