You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

develop.html 15 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. <html>
  2. <head>
  3. <meta http-equiv="Content-Language" content="en-us">
  4. <title>Writing Your Own Task</title>
  5. </head>
  6. <body>
  7. <h1>Developing with Ant</h1>
  8. <h2><a name="writingowntask">Writing Your Own Task</a></h2>
  9. <p>It is very easy to write your own task:</p>
  10. <ol>
  11. <li>Create a Java class that extends <code>org.apache.tools.ant.Task</code>
  12. or <a href="base_task_classes.html">another class</a> that was desgined to be extended.</li>
  13. <li>For each attribute, write a <i>setter</i> method. The setter method must be a
  14. <code>public void</code> method that takes a single argument. The
  15. name of the method must begin with <code>set</code>, followed by the
  16. attribute name, with the first character of the name in uppercase, and the rest in
  17. lowercase. That is, to support an attribute named
  18. <code>file</code> you create a method <code>setFile</code>.
  19. Depending on the type of the argument, Ant will perform some
  20. conversions for you, see <a href="#set-magic">below</a>.</li>
  21. <li>If your task shall contain other tasks as nested elements (like
  22. <a href="CoreTasks/parallel.html"><code>parallel</code></a>), your
  23. class must implement the interface
  24. <code>org.apache.tools.ant.TaskContainer</code>. If you do so, your
  25. task can not support any other nested elements. See
  26. <a href="#taskcontainer">below</a>.</li>
  27. <li>If the task should support character data (text nested between the
  28. start end end tags), write a <code>public void addText(String)</code>
  29. method. Note that Ant does <strong>not</strong> expand properties on
  30. the text it passes to the task.</li>
  31. <li>For each nested element, write a <i>create</i>, <i>add</i> or
  32. <i>addConfigured</i> method. A create method must be a
  33. <code>public</code> method that takes no arguments and returns an
  34. <code>Object</code> type. The name of the create method must begin
  35. with <code>create</code>, followed by the element name. An add (or
  36. addConfigured) method must be a <code>public void</code> method that
  37. takes a single argument of an <code>Object</code> type with a
  38. no-argument constructor. The name of the add (addConfigured) method
  39. must begin with <code>add</code> (<code>addConfigured</code>),
  40. followed by the element name. For a more complete discussion see
  41. <a href="#nested-elements">below</a>.</li>
  42. <li>Write a <code>public void execute</code> method, with no arguments, that
  43. throws a <code>BuildException</code>. This method implements the task
  44. itself.</li>
  45. </ol>
  46. <h3>The Life-cycle of a Task</h3>
  47. <ol>
  48. <li>The task gets instantiated using a no-argument constructor, at parser
  49. time. This means even tasks that are never executed get
  50. instantiated.</li>
  51. <li>The task gets references to its project and location inside the
  52. buildfile via its inherited <code>project</code> and
  53. <code>location</code> variables.</li>
  54. <li>If the user specified an <code>id</code> attribute to this task,
  55. the project
  56. registers a reference to this newly created task, at parser
  57. time.</li>
  58. <li>The task gets a reference to the target it belongs to via its
  59. inherited <code>target</code> variable.</li>
  60. <li><code>init()</code> is called at parser time.</li>
  61. <li>All child elements of the XML element corresponding to this task
  62. are created via this task's <code>createXXX()</code> methods or
  63. instantiated and added to this task via its <code>addXXX()</code>
  64. methods, at parser time.</li>
  65. <li>All attributes of this task get set via their corresponding
  66. <code>setXXX</code> methods, at runtime.</li>
  67. <li>The content character data sections inside the XML element
  68. corresponding to this task is added to the task via its
  69. <code>addText</code> method, at runtime.</li>
  70. <li>All attributes of all child elements get set via their corresponding
  71. <code>setXXX</code> methods, at runtime.</li>
  72. <li><a name="execute"><code>execute()</code></a> is called at runtime. While the above initialization
  73. steps only occur once, the execute() method may be
  74. called more than once, if the task is invoked more than once. For example,
  75. if <code>target1</code> and <code>target2</code> both depend
  76. on <code>target3</code>, then running
  77. <code>'ant target1 target2'</code> will run all tasks in
  78. <code>target3</code> twice.</li>
  79. </ol>
  80. <h3><a name="set-magic">Conversions Ant will perform for attributes</a></h3>
  81. <p>Ant will always expand properties before it passes the value of an
  82. attribute to the corresponding setter method.</p>
  83. <p>The most common way to write an attribute setter is to use a
  84. <code>java.lang.String</code> argument. In this case Ant will pass
  85. the literal value (after property expansion) to your task. But there
  86. is more! If the argument of you setter method is</p>
  87. <ul>
  88. <li><code>boolean</code>, your method will be passed the value
  89. <i>true</i> if the value specified in the build file is one of
  90. <code>true</code>, <code>yes</code>, or <code>on</code> and
  91. <i>false</i> otherwise.</li>
  92. <li><code>char</code> or <code>java.lang.Character</code>, your
  93. method will be passed the first character of the value specified in
  94. the build file.</li>
  95. <li>any other primitive type (<code>int</code>, <code>short</code>
  96. and so on), Ant will convert the value of the attribute into this
  97. type, thus making sure that you'll never receive input that is not a
  98. number for that attribute.</li>
  99. <li><code>java.io.File</code>, Ant will first determine whether the
  100. value given in the build file represents an absolute path name. If
  101. not, Ant will interpret the value as a path name relative to the
  102. project's basedir.</li>
  103. <li><code>org.apache.tools.ant.types.Path</code>, Ant will tokenize
  104. the value specified in the build file, accepting <code>:</code> and
  105. <code>;</code> as path separators. Relative path names will be
  106. interpreted as relative to the project's basedir.</li>
  107. <li><code>java.lang.Class</code>, Ant will interpret the value
  108. given in the build file as a Java class name and load the named
  109. class from the system class loader.</li>
  110. <li>any other type that has a constructor with a single
  111. <code>String</code> argument, Ant will use this constructor to
  112. create a new instance from the value given in the build file.</li>
  113. <li>A subclass of
  114. <code>org.apache.tools.ant.types.EnumeratedAttribute</code>, Ant
  115. will invoke this classes <code>setValue</code> method. Use this if
  116. your task should support enumerated attributes (attributes with
  117. values that must be part of a predefined set of values). See
  118. <code>org/apache/tools/ant/taskdefs/FixCRLF.java</code> and the
  119. inner <code>AddAsisRemove</code> class used in <code>setCr</code>
  120. for an example.</li>
  121. </ul>
  122. <p>What happens if more than one setter method is present for a given
  123. attribute? A method taking a <code>String</code> argument will always
  124. lose against the more specific methods. If there are still more
  125. setters Ant could chose from, only one of them will be called, but we
  126. don't know which, this depends on the implementation of your Java
  127. virtual machine.</p>
  128. <h3><a name="nested-elements">Supporting nested elements</a></h3>
  129. <p>Let's assume your task shall support nested elements with the name
  130. <code>inner</code>. First of all, you need a class that represents
  131. this nested element. Often you simply want to use one of Ant's
  132. classes like <code>org.apache.tools.ant.types.FileSet</code> to
  133. support nested <code>fileset</code> elements.</p>
  134. <p>Attributes of the nested elements or nested child elements of them
  135. will be handled using the same mechanism used for tasks (i.e. setter
  136. methods for attributes, addText for nested text and
  137. create/add/addConfigured methods for child elements).</p>
  138. <p>Now you have a class <code>NestedElement</code> that is supposed to
  139. be used for your nested <code>&lt;inner&gt;</code> elements, you have
  140. three options:</p>
  141. <ol>
  142. <li><code>public NestedElement createInner()</code></li>
  143. <li><code>public void addInner(NestedElement anInner)</code></li>
  144. <li><code>public void addConfiguredInner(NestedElement anInner)</code></li>
  145. </ol>
  146. <p>What is the difference?</p>
  147. <p>Option 1 makes the task create the instance of
  148. <code>NestedElement</code>, there are no restrictions on the type.
  149. For the options 2 and 3, Ant has to create an instance of
  150. <code>NestedInner</code> before it can pass it to the task, this
  151. means, <code>NestedInner</code> must have a <code>public</code> no-arg
  152. constructor. This is the only difference between options 1 and 2.</p>
  153. <p>The difference between 2 and 3 is what Ant has done to the object
  154. before it passes it to the method. <code>addInner</code> will receive
  155. an object directly after the constructor has been called, while
  156. <code>addConfiguredInner</code> gets the object <em>after</em> the
  157. attributes and nested children for this new object have been
  158. handled.</p>
  159. <p>What happens if you use more than one of the options? Only one of
  160. the methods will be called, but we don't know which, this depends on
  161. the implementation of your Java virtual machine.</p>
  162. <h3><a name="taskcontainer">TaskContainer</a></h3>
  163. <p>The <code>TaskContainer</code> consists of a single method,
  164. <code>addTask</code> that basically is the same as an <a
  165. href="#nested-elements">add method</a> for nested elements. The task
  166. instances will be configured (their attributes and nested elements
  167. have been handled) when your task's <code>execute</code> method gets
  168. invoked, but not before that.</p>
  169. <p>When we <a href="#execute">said</a> <code>execute</code> would be
  170. called, we lied ;-). In fact, Ant will call the <code>perform</code>
  171. method in <code>org.apache.tools.ant.Task</code>, which in turn calls
  172. <code>execute</code>. This method makes sure that <a
  173. href="#buildevents">Build Events</a> will be triggered. If you
  174. execute the task instances nested into your task, you should also
  175. invoke <code>perform</code> on these instances instead of
  176. <code>execute</code>.</p>
  177. <h3>Example</h3>
  178. <p>Let's write our own task, which prints a message on the
  179. <code>System.out</code> stream.
  180. The
  181. task has one attribute, called <code>message</code>.</p>
  182. <blockquote>
  183. <pre>
  184. package com.mydomain;
  185. import org.apache.tools.ant.BuildException;
  186. import org.apache.tools.ant.Task;
  187. public class MyVeryOwnTask extends Task {
  188. private String msg;
  189. // The method executing the task
  190. public void execute() throws BuildException {
  191. System.out.println(msg);
  192. }
  193. // The setter for the &quot;message&quot; attribute
  194. public void setMessage(String msg) {
  195. this.msg = msg;
  196. }
  197. }
  198. </pre>
  199. </blockquote>
  200. <p>It's really this simple ;-)</p>
  201. <p>Adding your task to the system is rather simple too:</p>
  202. <ol>
  203. <li>Make sure the class that implements your task is in the classpath when
  204. starting Ant.</li>
  205. <li>Add a <code>&lt;taskdef&gt;</code> element to your project.
  206. This actually adds your task to the system.</li>
  207. <li>Use your task in the rest of the buildfile.</li>
  208. </ol>
  209. <h3>Example</h3>
  210. <blockquote>
  211. <pre>
  212. &lt;?xml version=&quot;1.0&quot;?&gt;
  213. &lt;project name=&quot;OwnTaskExample&quot; default=&quot;main&quot; basedir=&quot;.&quot;&gt;
  214. &lt;taskdef name=&quot;mytask&quot; classname=&quot;com.mydomain.MyVeryOwnTask&quot;/&gt;
  215. &lt;target name=&quot;main&quot;&gt;
  216. &lt;mytask message=&quot;Hello World! MyVeryOwnTask works!&quot;/&gt;
  217. &lt;/target&gt;
  218. &lt;/project&gt;
  219. </pre>
  220. </blockquote>
  221. <h3>Example 2</h3>
  222. To use a task directly from the buildfile which created it, place the
  223. <code>&lt;taskdef&gt;</code> declaration inside a target
  224. <i>after the compilation</i>. Use the <code>classpath</code> attribute of
  225. <code>&lt;taskdef&gt;</code> to point to where the code has just been
  226. compiled.
  227. <blockquote>
  228. <pre>
  229. &lt;?xml version=&quot;1.0&quot;?&gt;
  230. &lt;project name=&quot;OwnTaskExample2&quot; default=&quot;main&quot; basedir=&quot;.&quot;&gt;
  231. &lt;target name=&quot;build&quot; &gt;
  232. &lt;mkdir dir=&quot;build&quot;/&gt;
  233. &lt;javac srcdir=&quot;source&quot; destdir=&quot;build&quot;/&gt;
  234. &lt;/target&gt;
  235. &lt;target name=&quot;declare&quot; depends=&quot;build&quot;&gt;
  236. &lt;taskdef name=&quot;mytask&quot;
  237. classname=&quot;com.mydomain.MyVeryOwnTask&quot;
  238. classpath=&quot;build&quot;/&gt;
  239. &lt;/target&gt;
  240. &lt;target name=&quot;main&quot; depends=&quot;declare&quot;&gt;
  241. &lt;mytask message=&quot;Hello World! MyVeryOwnTask works!&quot;/&gt;
  242. &lt;/target&gt;
  243. &lt;/project&gt;
  244. </pre>
  245. </blockquote>
  246. <p>Another way to add a task (more permanently), is to add the task name and
  247. implementing class name to the <code>default.properties</code> file in the
  248. <code>org.apache.tools.ant.taskdefs</code>
  249. package. Then you can use it as if it were a built-in task.</p>
  250. <hr>
  251. <h2><a name="buildevents">Build Events</a></h2>
  252. <P>Ant is capable of generating build events as it performs the tasks necessary to build a project.
  253. Listeners can be attached to Ant to receive these events. This capability could be used, for example,
  254. to connect Ant to a GUI or to integrate Ant with an IDE.
  255. </P>
  256. <p>To use build events you need to create an ant <code>Project</code> object. You can then call the
  257. <code>addBuildListener</code> method to add your listener to the project. Your listener must implement
  258. the <code>org.apache.tools.antBuildListener</code> interface. The listener will receive BuildEvents
  259. for the following events</P>
  260. <ul>
  261. <li>Build started</li>
  262. <li>Build finished</li>
  263. <li>Target started</li>
  264. <li>Target finished</li>
  265. <li>Task started</li>
  266. <li>Task finished</li>
  267. <li>Message logged</li>
  268. </ul>
  269. <p>
  270. If you wish to attach a listener from the command line you may use the
  271. <code>-listener</code> option. For example:</p>
  272. <blockquote>
  273. <pre>ant -listener org.apache.tools.ant.XmlLogger</pre>
  274. </blockquote>
  275. <p>will run Ant with a listener that generates an XML representation of the build progress. This
  276. listener is included with Ant, as is the default listener, which generates the logging to standard output.</p>
  277. <hr>
  278. <h2><a name="integration">Source code integration</a></h2>
  279. The other way to extend Ant through Java is to make changes to existing tasks, which is positively encouraged.
  280. Both changes to the existing source and new tasks can be incorporated back into the Ant codebase, which
  281. benefits all users and spreads the maintenance load around.
  282. <p>
  283. Please consult the
  284. <a href="http://jakarta.apache.org/site/getinvolved.html">Getting Involved</a> pages on the Jakarta web site
  285. for details on how to fetch the latest source and how to submit changes for reincorporation into the
  286. source tree.
  287. <p>
  288. Ant also has some
  289. <a href="http://ant.apache.org/ant_task_guidelines.html">task guidelines</a>
  290. which provides some advice to people developing and testing tasks. Even if you intend to
  291. keep your tasks to yourself, you should still read this as it should be informative.
  292. <hr>
  293. <p align="center">Copyright &copy; 2000-2003 Apache Software Foundation. All rights
  294. Reserved.</p>
  295. </body>
  296. </html>