1 // NAnt - A .NET build tool
2 // Copyright (C) 2001 Gerry Shaw
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 // Gerry Shaw (gerry_shaw@yahoo.com)
19 // Mike Krueger (mike@icsharpcode.net)
20 // Ian MacLean (ian_maclean@another.com)
22 namespace SourceForge
.NAnt
{
25 using System
.Reflection
;
28 public abstract class Task
{
30 /// <summary>Gets and sets how much spacing log prefix names will be padded.</summary>
32 /// Includes characters for a space after the name and the [ ] brackets. Default is 12.
34 public static int LogPrefixPadding
= Log
.IndentSize
;
36 Location _location
= Location
.UnknownLocation
;
37 Target _target
= null;
38 Project _project
= null;
41 /// Location in build file where task is defined.
43 protected Location Location
{
44 get { return _location; }
45 set { _location = value; }
51 TaskNameAttribute taskName
= (TaskNameAttribute
) Attribute
.GetCustomAttribute(GetType(), typeof(TaskNameAttribute
));
52 if (taskName
!= null) {
59 public string LogPrefix
{
61 string prefix
= "[" + Name
+ "] ";
62 return prefix
.PadLeft(LogPrefixPadding
);
66 public Target Target
{
67 get { return _target; }
68 set { _target = value; }
71 public Project Project
{
72 get { return _project; }
73 set { _project = value; }
76 protected void AutoInitializeAttributes(XmlNode taskNode
) {
78 // TODO: BooleanValidatorAttribute and Int32ValidatorAttribute implementation in Task
80 // Go down the inheritance tree to find the private fields in the object.
81 // We are looking for task attributes to initialize.
82 Type currentType
= GetType();
83 while (currentType
!= typeof(object)) {
84 FieldInfo
[] fieldInfoArray
= currentType
.GetFields(BindingFlags
.NonPublic
|BindingFlags
.Instance
);
85 foreach (FieldInfo fieldInfo
in fieldInfoArray
) {
87 // process TaskAttribute attributes
88 TaskAttributeAttribute taskAttribute
= (TaskAttributeAttribute
) Attribute
.GetCustomAttribute(fieldInfo
, typeof(TaskAttributeAttribute
));
89 if (taskAttribute
!= null) {
91 // get value from xml file
92 XmlNode node
= taskNode
.SelectSingleNode("@" + taskAttribute
.Name
);
94 // check if its required
95 if (node
== null && taskAttribute
.Required
) {
96 // TODO: add Location to exception
97 throw new BuildException(String
.Format("{0} is a required attribute.", taskAttribute
.Name
), Location
);
101 fieldInfo
.SetValue(this, Convert
.ChangeType(node
.Value
, fieldInfo
.FieldType
));
105 // process TaskFileSet attributes
106 TaskFileSetAttribute fileSetAttribute
= (TaskFileSetAttribute
) Attribute
.GetCustomAttribute(fieldInfo
, typeof(TaskFileSetAttribute
));
107 if (fileSetAttribute
!= null) {
108 // have file set initialize itself
109 FileSet fileSet
= (FileSet
) fieldInfo
.GetValue(this);
111 // set task fileset belongs to
114 // load values from build file
115 XmlNode fileSetNode
= taskNode
.SelectSingleNode(fileSetAttribute
.Name
);
116 if (fileSetNode
!= null) {
118 XmlNode baseDirectoryNode
= fileSetNode
.SelectSingleNode("@basedir");
119 if (baseDirectoryNode
!= null) {
120 fileSet
.BaseDirectory
= baseDirectoryNode
.Value
;
123 foreach (XmlNode node
in fileSetNode
.SelectNodes("includes")) {
124 string pathname
= node
.SelectSingleNode("@name").Value
;
125 fileSet
.Includes
.Add(pathname
);
128 foreach (XmlNode node
in fileSetNode
.SelectNodes("excludes")) {
129 fileSet
.Excludes
.Add(node
.SelectSingleNode("@name").Value
);
134 currentType
= currentType
.BaseType
;
138 protected void AutoExpandAttributes() {
140 // Go down the inheritance tree to find the private fields in the object.
141 // We are looking for task attributes to initialize.
142 Type currentType
= GetType();
143 while (currentType
!= typeof(object)) {
144 FieldInfo
[] fieldInfoArray
= currentType
.GetFields(BindingFlags
.NonPublic
|BindingFlags
.Instance
);
145 foreach (FieldInfo fieldInfo
in fieldInfoArray
) {
147 // proces string parameters
148 TaskAttributeAttribute taskAttribute
= (TaskAttributeAttribute
) Attribute
.GetCustomAttribute(fieldInfo
, typeof(TaskAttributeAttribute
));
149 if (taskAttribute
!= null) {
150 if (taskAttribute
.ExpandText
) {
151 string value = (string) fieldInfo
.GetValue(this);
152 value = Project
.ExpandText(value);
153 fieldInfo
.SetValue(this, value);
156 // if a field also has a validator attribute then ensure that value is correct
157 ValidatorAttribute
[] validators
= (ValidatorAttribute
[]) Attribute
.GetCustomAttributes(fieldInfo
, typeof(ValidatorAttribute
));
158 foreach (ValidatorAttribute validator
in validators
) {
159 string errorMessage
= validator
.Validate(fieldInfo
.GetValue(this));
160 if (errorMessage
!= null) {
161 throw new BuildException(String
.Format("Error processing '{0}' attribute in <{1}> task: {2}", taskAttribute
.Name
, Name
, errorMessage
), Location
);
166 currentType
= currentType
.BaseType
;
170 public void Initialize(XmlNode taskNode
) {
171 Initialize(taskNode
, null);
174 public void Initialize(XmlNode taskNode
, Location location
) {
175 if (location
!= null) {
176 _location
= location
;
178 AutoInitializeAttributes(taskNode
);
179 InitializeTask(taskNode
);
182 public void Execute() {
183 AutoExpandAttributes();
187 protected virtual void InitializeTask(XmlNode taskNode
) {
190 protected abstract void ExecuteTask();