1 | <!--
|
---|
2 | Licensed to the Apache Software Foundation (ASF) under one or more
|
---|
3 | contributor license agreements. See the NOTICE file distributed with
|
---|
4 | this work for additional information regarding copyright ownership.
|
---|
5 | The ASF licenses this file to You under the Apache License, Version 2.0
|
---|
6 | (the "License"); you may not use this file except in compliance with
|
---|
7 | the License. You may obtain a copy of the License at
|
---|
8 |
|
---|
9 | http://www.apache.org/licenses/LICENSE-2.0
|
---|
10 |
|
---|
11 | Unless required by applicable law or agreed to in writing, software
|
---|
12 | distributed under the License is distributed on an "AS IS" BASIS,
|
---|
13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
---|
14 | See the License for the specific language governing permissions and
|
---|
15 | limitations under the License.
|
---|
16 | -->
|
---|
17 | <html>
|
---|
18 |
|
---|
19 | <head>
|
---|
20 | <meta http-equiv="Content-Language" content="en-us">
|
---|
21 | <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
|
---|
22 | <title>Writing Your Own Task</title>
|
---|
23 | </head>
|
---|
24 |
|
---|
25 | <body>
|
---|
26 | <h1>Developing with Ant</h1>
|
---|
27 |
|
---|
28 | <h2><a name="writingowntask">Writing Your Own Task</a></h2>
|
---|
29 | <p>It is very easy to write your own task:</p>
|
---|
30 | <ol>
|
---|
31 | <li>Create a Java class that extends <code>org.apache.tools.ant.Task</code>
|
---|
32 | or <a href="base_task_classes.html">another class</a> that was designed to be extended.</li>
|
---|
33 | <li>For each attribute, write a <i>setter</i> method. The setter method must be a
|
---|
34 | <code>public void</code> method that takes a single argument. The
|
---|
35 | name of the method must begin with <code>set</code>, followed by the
|
---|
36 | attribute name, with the first character of the name in uppercase, and the rest in
|
---|
37 |
|
---|
38 | lowercase<a href="#footnote-1"><sup>*</sup></a>. That is, to support an attribute named
|
---|
39 | <code>file</code> you create a method <code>setFile</code>.
|
---|
40 | Depending on the type of the argument, Ant will perform some
|
---|
41 | conversions for you, see <a href="#set-magic">below</a>.</li>
|
---|
42 |
|
---|
43 | <li>If your task shall contain other tasks as nested elements (like
|
---|
44 | <a href="CoreTasks/parallel.html"><code>parallel</code></a>), your
|
---|
45 | class must implement the interface
|
---|
46 | <code>org.apache.tools.ant.TaskContainer</code>. If you do so, your
|
---|
47 | task can not support any other nested elements. See
|
---|
48 | <a href="#taskcontainer">below</a>.</li>
|
---|
49 |
|
---|
50 | <li>If the task should support character data (text nested between the
|
---|
51 | start end end tags), write a <code>public void addText(String)</code>
|
---|
52 | method. Note that Ant does <strong>not</strong> expand properties on
|
---|
53 | the text it passes to the task.</li>
|
---|
54 |
|
---|
55 | <li>For each nested element, write a <i>create</i>, <i>add</i> or
|
---|
56 | <i>addConfigured</i> method. A create method must be a
|
---|
57 | <code>public</code> method that takes no arguments and returns an
|
---|
58 | <code>Object</code> type. The name of the create method must begin
|
---|
59 | with <code>create</code>, followed by the element name. An add (or
|
---|
60 | addConfigured) method must be a <code>public void</code> method that
|
---|
61 | takes a single argument of an <code>Object</code> type with a
|
---|
62 | no-argument constructor. The name of the add (addConfigured) method
|
---|
63 | must begin with <code>add</code> (<code>addConfigured</code>),
|
---|
64 | followed by the element name. For a more complete discussion see
|
---|
65 | <a href="#nested-elements">below</a>.</li>
|
---|
66 |
|
---|
67 | <li>Write a <code>public void execute</code> method, with no arguments, that
|
---|
68 | throws a <code>BuildException</code>. This method implements the task
|
---|
69 | itself.</li>
|
---|
70 | </ol>
|
---|
71 |
|
---|
72 | <hr>
|
---|
73 | <p><a name="footnote-1">*</a> Actually the case of the letters after
|
---|
74 | the first one doesn't really matter to Ant, using all lower case is a
|
---|
75 | good convention, though.</p>
|
---|
76 |
|
---|
77 | <h3>The Life-cycle of a Task</h3>
|
---|
78 | <ol>
|
---|
79 | <li>The task gets instantiated using a no-argument constructor, at parser
|
---|
80 | time. This means even tasks that are never executed get
|
---|
81 | instantiated.</li>
|
---|
82 |
|
---|
83 | <li>The task gets references to its project and location inside the
|
---|
84 | buildfile via its inherited <code>project</code> and
|
---|
85 | <code>location</code> variables.</li>
|
---|
86 |
|
---|
87 | <li>If the user specified an <code>id</code> attribute to this task,
|
---|
88 | the project
|
---|
89 | registers a reference to this newly created task, at parser
|
---|
90 | time.</li>
|
---|
91 |
|
---|
92 | <li>The task gets a reference to the target it belongs to via its
|
---|
93 | inherited <code>target</code> variable.</li>
|
---|
94 |
|
---|
95 | <li><code>init()</code> is called at parser time.</li>
|
---|
96 |
|
---|
97 | <li>All child elements of the XML element corresponding to this task
|
---|
98 | are created via this task's <code>createXXX()</code> methods or
|
---|
99 | instantiated and added to this task via its <code>addXXX()</code>
|
---|
100 | methods, at parser time.</li>
|
---|
101 |
|
---|
102 | <li>All attributes of this task get set via their corresponding
|
---|
103 | <code>setXXX</code> methods, at runtime.</li>
|
---|
104 |
|
---|
105 | <li>The content character data sections inside the XML element
|
---|
106 | corresponding to this task is added to the task via its
|
---|
107 | <code>addText</code> method, at runtime.</li>
|
---|
108 |
|
---|
109 | <li>All attributes of all child elements get set via their corresponding
|
---|
110 | <code>setXXX</code> methods, at runtime.</li>
|
---|
111 |
|
---|
112 | <li><a name="execute"><code>execute()</code></a> is called at runtime. While the above initialization
|
---|
113 | steps only occur once, the execute() method may be
|
---|
114 | called more than once, if the task is invoked more than once. For example,
|
---|
115 | if <code>target1</code> and <code>target2</code> both depend
|
---|
116 | on <code>target3</code>, then running
|
---|
117 | <code>'ant target1 target2'</code> will run all tasks in
|
---|
118 | <code>target3</code> twice.</li>
|
---|
119 | </ol>
|
---|
120 |
|
---|
121 | <h3><a name="set-magic">Conversions Ant will perform for attributes</a></h3>
|
---|
122 |
|
---|
123 | <p>Ant will always expand properties before it passes the value of an
|
---|
124 | attribute to the corresponding setter method.</p>
|
---|
125 |
|
---|
126 | <p>The most common way to write an attribute setter is to use a
|
---|
127 | <code>java.lang.String</code> argument. In this case Ant will pass
|
---|
128 | the literal value (after property expansion) to your task. But there
|
---|
129 | is more! If the argument of you setter method is</p>
|
---|
130 |
|
---|
131 | <ul>
|
---|
132 |
|
---|
133 | <li><code>boolean</code>, your method will be passed the value
|
---|
134 | <i>true</i> if the value specified in the build file is one of
|
---|
135 | <code>true</code>, <code>yes</code>, or <code>on</code> and
|
---|
136 | <i>false</i> otherwise.</li>
|
---|
137 |
|
---|
138 | <li><code>char</code> or <code>java.lang.Character</code>, your
|
---|
139 | method will be passed the first character of the value specified in
|
---|
140 | the build file.</li>
|
---|
141 |
|
---|
142 | <li>any other primitive type (<code>int</code>, <code>short</code>
|
---|
143 | and so on), Ant will convert the value of the attribute into this
|
---|
144 | type, thus making sure that you'll never receive input that is not a
|
---|
145 | number for that attribute.</li>
|
---|
146 |
|
---|
147 | <li><code>java.io.File</code>, Ant will first determine whether the
|
---|
148 | value given in the build file represents an absolute path name. If
|
---|
149 | not, Ant will interpret the value as a path name relative to the
|
---|
150 | project's basedir.</li>
|
---|
151 |
|
---|
152 | <li><code>org.apache.tools.ant.types.Path</code>, Ant will tokenize
|
---|
153 | the value specified in the build file, accepting <code>:</code> and
|
---|
154 | <code>;</code> as path separators. Relative path names will be
|
---|
155 | interpreted as relative to the project's basedir.</li>
|
---|
156 |
|
---|
157 | <li><code>java.lang.Class</code>, Ant will interpret the value
|
---|
158 | given in the build file as a Java class name and load the named
|
---|
159 | class from the system class loader.</li>
|
---|
160 |
|
---|
161 | <li>any other type that has a constructor with a single
|
---|
162 | <code>String</code> argument, Ant will use this constructor to
|
---|
163 | create a new instance from the value given in the build file.</li>
|
---|
164 |
|
---|
165 | <li>A subclass of
|
---|
166 | <code>org.apache.tools.ant.types.EnumeratedAttribute</code>, Ant
|
---|
167 | will invoke this classes <code>setValue</code> method. Use this if
|
---|
168 | your task should support enumerated attributes (attributes with
|
---|
169 | values that must be part of a predefined set of values). See
|
---|
170 | <code>org/apache/tools/ant/taskdefs/FixCRLF.java</code> and the
|
---|
171 | inner <code>AddAsisRemove</code> class used in <code>setCr</code>
|
---|
172 | for an example.</li>
|
---|
173 |
|
---|
174 | <li>A (Java 5) enumeration. Ant will call the setter with the enum constant
|
---|
175 | matching the value given in the build file. This is easier than using
|
---|
176 | <code>EnumeratedAttribute</code> and can result in cleaner code, but of course
|
---|
177 | your task will not run on JDK 1.4 or earlier. Note that any override of
|
---|
178 | <code>toString()</code> in the enumeration is ignored; the build file must use
|
---|
179 | the declared name (see <code>Enum.getName()</code>). You may wish to use lowercase
|
---|
180 | enum constant names, in contrast to usual Java style, to look better in build files.
|
---|
181 | <em>As of Ant 1.7.0.</em></li>
|
---|
182 |
|
---|
183 | </ul>
|
---|
184 |
|
---|
185 | <p>What happens if more than one setter method is present for a given
|
---|
186 | attribute? A method taking a <code>String</code> argument will always
|
---|
187 | lose against the more specific methods. If there are still more
|
---|
188 | setters Ant could chose from, only one of them will be called, but we
|
---|
189 | don't know which, this depends on the implementation of your Java
|
---|
190 | virtual machine.</p>
|
---|
191 |
|
---|
192 | <h3><a name="nested-elements">Supporting nested elements</a></h3>
|
---|
193 |
|
---|
194 | <p>Let's assume your task shall support nested elements with the name
|
---|
195 | <code>inner</code>. First of all, you need a class that represents
|
---|
196 | this nested element. Often you simply want to use one of Ant's
|
---|
197 | classes like <code>org.apache.tools.ant.types.FileSet</code> to
|
---|
198 | support nested <code>fileset</code> elements.</p>
|
---|
199 |
|
---|
200 | <p>Attributes of the nested elements or nested child elements of them
|
---|
201 | will be handled using the same mechanism used for tasks (i.e. setter
|
---|
202 | methods for attributes, addText for nested text and
|
---|
203 | create/add/addConfigured methods for child elements).</p>
|
---|
204 |
|
---|
205 | <p>Now you have a class <code>NestedElement</code> that is supposed to
|
---|
206 | be used for your nested <code><inner></code> elements, you have
|
---|
207 | three options:</p>
|
---|
208 |
|
---|
209 | <ol>
|
---|
210 | <li><code>public NestedElement createInner()</code></li>
|
---|
211 | <li><code>public void addInner(NestedElement anInner)</code></li>
|
---|
212 | <li><code>public void addConfiguredInner(NestedElement anInner)</code></li>
|
---|
213 | </ol>
|
---|
214 |
|
---|
215 | <p>What is the difference?</p>
|
---|
216 |
|
---|
217 | <p>Option 1 makes the task create the instance of
|
---|
218 | <code>NestedElement</code>, there are no restrictions on the type.
|
---|
219 | For the options 2 and 3, Ant has to create an instance of
|
---|
220 | <code>NestedInner</code> before it can pass it to the task, this
|
---|
221 | means, <code>NestedInner</code> must have a <code>public</code> no-arg
|
---|
222 | constructor or a <code>public</code> one-arg constructor
|
---|
223 | taking a Project class as a parameter.
|
---|
224 | This is the only difference between options 1 and 2.</p>
|
---|
225 |
|
---|
226 | <p>The difference between 2 and 3 is what Ant has done to the object
|
---|
227 | before it passes it to the method. <code>addInner</code> will receive
|
---|
228 | an object directly after the constructor has been called, while
|
---|
229 | <code>addConfiguredInner</code> gets the object <em>after</em> the
|
---|
230 | attributes and nested children for this new object have been
|
---|
231 | handled.</p>
|
---|
232 |
|
---|
233 | <p>What happens if you use more than one of the options? Only one of
|
---|
234 | the methods will be called, but we don't know which, this depends on
|
---|
235 | the implementation of your Java virtual machine.</p>
|
---|
236 |
|
---|
237 | <h3><a name="nestedtype">Nested Types</a></h3>
|
---|
238 | If your task needs to nest an arbitary type that has been defined
|
---|
239 | using <code><typedef></code> you have two options.
|
---|
240 | <ol>
|
---|
241 | <li><code>public void add(Type type)</code></li>
|
---|
242 | <li><code>public void addConfigured(Type type)</code></li>
|
---|
243 | </ol>
|
---|
244 | The difference between 1 and 2 is the same as between 2 and 3 in the
|
---|
245 | previous section.
|
---|
246 | <p>
|
---|
247 | For example suppose one wanted to handle objects object of type
|
---|
248 | org.apache.tools.ant.taskdefs.condition.Condition, one may
|
---|
249 | have a class:
|
---|
250 | </p>
|
---|
251 | <blockquote>
|
---|
252 | <pre>
|
---|
253 | public class MyTask extends Task {
|
---|
254 | private List conditions = new ArrayList();
|
---|
255 | public void add(Condition c) {
|
---|
256 | conditions.add(c);
|
---|
257 | }
|
---|
258 | public void execute() {
|
---|
259 | // iterator over the conditions
|
---|
260 | }
|
---|
261 | }
|
---|
262 | </pre>
|
---|
263 | </blockquote>
|
---|
264 | <p>
|
---|
265 | One may define and use this class like this:
|
---|
266 | </p>
|
---|
267 | <blockquote>
|
---|
268 | <pre>
|
---|
269 | <taskdef name="mytask" classname="MyTask" classpath="classes"/>
|
---|
270 | <typedef name="condition.equals"
|
---|
271 | classname="org.apache.tools.ant.taskdefs.conditions.Equals"/>
|
---|
272 | <mytask>
|
---|
273 | <condition.equals arg1="${debug}" arg2="true"/>
|
---|
274 | </mytask>
|
---|
275 | </pre>
|
---|
276 | </blockquote>
|
---|
277 | <p>
|
---|
278 | A more complicated example follows:
|
---|
279 | </p>
|
---|
280 | <blockquote>
|
---|
281 | <pre>
|
---|
282 | public class Sample {
|
---|
283 | public static class MyFileSelector implements FileSelector {
|
---|
284 | public void setAttrA(int a) {}
|
---|
285 | public void setAttrB(int b) {}
|
---|
286 | public void add(Path path) {}
|
---|
287 | public boolean isSelected(File basedir, String filename, File file) {
|
---|
288 | return true;
|
---|
289 | }
|
---|
290 | }
|
---|
291 |
|
---|
292 | interface MyInterface {
|
---|
293 | void setVerbose(boolean val);
|
---|
294 | }
|
---|
295 |
|
---|
296 | public static class BuildPath extends Path {
|
---|
297 | public BuildPath(Project project) {
|
---|
298 | super(project);
|
---|
299 | }
|
---|
300 |
|
---|
301 | public void add(MyInterface inter) {}
|
---|
302 | public void setUrl(String url) {}
|
---|
303 | }
|
---|
304 |
|
---|
305 | public static class XInterface implements MyInterface {
|
---|
306 | public void setVerbose(boolean x) {}
|
---|
307 | public void setCount(int c) {}
|
---|
308 | }
|
---|
309 | }
|
---|
310 | </pre>
|
---|
311 | </blockquote>
|
---|
312 | <p>
|
---|
313 | This class defines a number of static classes that implement/extend
|
---|
314 | Path, MyFileSelector and MyInterface. These may be defined and used
|
---|
315 | as follows:
|
---|
316 | </p>
|
---|
317 | <pre>
|
---|
318 | <blockquote>
|
---|
319 | <typedef name="myfileselector" classname="Sample$MyFileSelector"
|
---|
320 | classpath="classes" loaderref="classes"/>
|
---|
321 | <typedef name="buildpath" classname="Sample$BuildPath"
|
---|
322 | classpath="classes" loaderref="classes"/>
|
---|
323 | <typedef name="xinterface" classname="Sample$XInterface"
|
---|
324 | classpath="classes" loaderref="classes"/>
|
---|
325 |
|
---|
326 | <copy todir="copy-classes">
|
---|
327 | <fileset dir="classes">
|
---|
328 | <myfileselector attra="10" attrB="-10">
|
---|
329 | <buildpath path="." url="abc">
|
---|
330 | <xinterface count="4"/>
|
---|
331 | </buildpath>
|
---|
332 | </myfileselector>
|
---|
333 | </fileset>
|
---|
334 | </copy>
|
---|
335 | </blockquote>
|
---|
336 | </pre>
|
---|
337 | <h3><a name="taskcontainer">TaskContainer</a></h3>
|
---|
338 |
|
---|
339 | <p>The <code>TaskContainer</code> consists of a single method,
|
---|
340 | <code>addTask</code> that basically is the same as an <a
|
---|
341 | href="#nested-elements">add method</a> for nested elements. The task
|
---|
342 | instances will be configured (their attributes and nested elements
|
---|
343 | have been handled) when your task's <code>execute</code> method gets
|
---|
344 | invoked, but not before that.</p>
|
---|
345 |
|
---|
346 | <p>When we <a href="#execute">said</a> <code>execute</code> would be
|
---|
347 | called, we lied ;-). In fact, Ant will call the <code>perform</code>
|
---|
348 | method in <code>org.apache.tools.ant.Task</code>, which in turn calls
|
---|
349 | <code>execute</code>. This method makes sure that <a
|
---|
350 | href="#buildevents">Build Events</a> will be triggered. If you
|
---|
351 | execute the task instances nested into your task, you should also
|
---|
352 | invoke <code>perform</code> on these instances instead of
|
---|
353 | <code>execute</code>.</p>
|
---|
354 |
|
---|
355 | <h3>Example</h3>
|
---|
356 | <p>Let's write our own task, which prints a message on the
|
---|
357 | <code>System.out</code> stream.
|
---|
358 | The
|
---|
359 | task has one attribute, called <code>message</code>.</p>
|
---|
360 | <blockquote>
|
---|
361 | <pre>
|
---|
362 | package com.mydomain;
|
---|
363 |
|
---|
364 | import org.apache.tools.ant.BuildException;
|
---|
365 | import org.apache.tools.ant.Task;
|
---|
366 |
|
---|
367 | public class MyVeryOwnTask extends Task {
|
---|
368 | private String msg;
|
---|
369 |
|
---|
370 | // The method executing the task
|
---|
371 | public void execute() throws BuildException {
|
---|
372 | System.out.println(msg);
|
---|
373 | }
|
---|
374 |
|
---|
375 | // The setter for the "message" attribute
|
---|
376 | public void setMessage(String msg) {
|
---|
377 | this.msg = msg;
|
---|
378 | }
|
---|
379 | }
|
---|
380 | </pre>
|
---|
381 | </blockquote>
|
---|
382 | <p>It's really this simple ;-)</p>
|
---|
383 | <p>Adding your task to the system is rather simple too:</p>
|
---|
384 | <ol>
|
---|
385 | <li>Make sure the class that implements your task is in the classpath when
|
---|
386 | starting Ant.</li>
|
---|
387 | <li>Add a <code><taskdef></code> element to your project.
|
---|
388 | This actually adds your task to the system.</li>
|
---|
389 | <li>Use your task in the rest of the buildfile.</li>
|
---|
390 | </ol>
|
---|
391 |
|
---|
392 | <h3>Example</h3>
|
---|
393 | <blockquote>
|
---|
394 | <pre>
|
---|
395 | <?xml version="1.0"?>
|
---|
396 |
|
---|
397 | <project name="OwnTaskExample" default="main" basedir=".">
|
---|
398 | <taskdef name="mytask" classname="com.mydomain.MyVeryOwnTask"/>
|
---|
399 |
|
---|
400 | <target name="main">
|
---|
401 | <mytask message="Hello World! MyVeryOwnTask works!"/>
|
---|
402 | </target>
|
---|
403 | </project>
|
---|
404 | </pre>
|
---|
405 | </blockquote>
|
---|
406 | <h3>Example 2</h3>
|
---|
407 | To use a task directly from the buildfile which created it, place the
|
---|
408 | <code><taskdef></code> declaration inside a target
|
---|
409 | <i>after the compilation</i>. Use the <code>classpath</code> attribute of
|
---|
410 | <code><taskdef></code> to point to where the code has just been
|
---|
411 | compiled.
|
---|
412 | <blockquote>
|
---|
413 | <pre>
|
---|
414 | <?xml version="1.0"?>
|
---|
415 |
|
---|
416 | <project name="OwnTaskExample2" default="main" basedir=".">
|
---|
417 |
|
---|
418 | <target name="build" >
|
---|
419 | <mkdir dir="build"/>
|
---|
420 | <javac srcdir="source" destdir="build"/>
|
---|
421 | </target>
|
---|
422 |
|
---|
423 | <target name="declare" depends="build">
|
---|
424 | <taskdef name="mytask"
|
---|
425 | classname="com.mydomain.MyVeryOwnTask"
|
---|
426 | classpath="build"/>
|
---|
427 | </target>
|
---|
428 |
|
---|
429 | <target name="main" depends="declare">
|
---|
430 | <mytask message="Hello World! MyVeryOwnTask works!"/>
|
---|
431 | </target>
|
---|
432 | </project>
|
---|
433 | </pre>
|
---|
434 | </blockquote>
|
---|
435 |
|
---|
436 | <p>Another way to add a task (more permanently), is to add the task name and
|
---|
437 | implementing class name to the <code>default.properties</code> file in the
|
---|
438 | <code>org.apache.tools.ant.taskdefs</code>
|
---|
439 | package. Then you can use it as if it were a built-in task.</p>
|
---|
440 |
|
---|
441 | <hr>
|
---|
442 | <h2><a name="buildevents">Build Events</a></h2>
|
---|
443 | <P>Ant is capable of generating build events as it performs the tasks necessary to build a project.
|
---|
444 | Listeners can be attached to Ant to receive these events. This capability could be used, for example,
|
---|
445 | to connect Ant to a GUI or to integrate Ant with an IDE.
|
---|
446 | </P>
|
---|
447 | <p>To use build events you need to create an ant <code>Project</code> object. You can then call the
|
---|
448 | <code>addBuildListener</code> method to add your listener to the project. Your listener must implement
|
---|
449 | the <code>org.apache.tools.antBuildListener</code> interface. The listener will receive BuildEvents
|
---|
450 | for the following events</P>
|
---|
451 | <ul>
|
---|
452 | <li>Build started</li>
|
---|
453 | <li>Build finished</li>
|
---|
454 | <li>Target started</li>
|
---|
455 | <li>Target finished</li>
|
---|
456 | <li>Task started</li>
|
---|
457 | <li>Task finished</li>
|
---|
458 | <li>Message logged</li>
|
---|
459 | </ul>
|
---|
460 |
|
---|
461 | <p>If the build file invokes another build file via <a
|
---|
462 | href="CoreTasks/ant.html"><code><ant></code></a> or <a
|
---|
463 | href="CoreTasks/subant.html"><code><subant></code></a> or uses <a
|
---|
464 | href="CoreTasks/antcall.html"><code><antcall></code></a>, you are creating a
|
---|
465 | new Ant "project" that will send target and task level events of its
|
---|
466 | own but never sends build started/finished events. Ant 1.6.2
|
---|
467 | introduces an extension of the BuildListener interface named
|
---|
468 | SubBuildListener that will receive two new events for</p>
|
---|
469 | <ul>
|
---|
470 | <li>SubBuild started</li>
|
---|
471 | <li>SubBuild finished</li>
|
---|
472 | </ul>
|
---|
473 | <p>If you are interested in those events, all you need to do is to
|
---|
474 | implement the new interface instead of BuildListener (and register the
|
---|
475 | listener, of course).</p>
|
---|
476 |
|
---|
477 | <p>
|
---|
478 | If you wish to attach a listener from the command line you may use the
|
---|
479 | <code>-listener</code> option. For example:</p>
|
---|
480 | <blockquote>
|
---|
481 | <pre>ant -listener org.apache.tools.ant.XmlLogger</pre>
|
---|
482 | </blockquote>
|
---|
483 | <p>will run Ant with a listener that generates an XML representation of the build progress. This
|
---|
484 | listener is included with Ant, as is the default listener, which generates the logging to standard output.</p>
|
---|
485 |
|
---|
486 | <p><b>Note: </b>A listener must not access System.out and System.err directly since ouput on
|
---|
487 | these streams is redirected by Ant's core to the build event system. Accessing these
|
---|
488 | streams can cause an infinite loop in Ant. Depending on the version of Ant, this will
|
---|
489 | either cause the build to terminate or the Java VM to run out of Stack space. A logger, also, may
|
---|
490 | not access System.out and System.err directly. It must use the streams with which it has
|
---|
491 | been configured.
|
---|
492 | </p>
|
---|
493 |
|
---|
494 | <hr>
|
---|
495 | <h2><a name="integration">Source code integration</a></h2>
|
---|
496 |
|
---|
497 | The other way to extend Ant through Java is to make changes to existing tasks, which is positively encouraged.
|
---|
498 | Both changes to the existing source and new tasks can be incorporated back into the Ant codebase, which
|
---|
499 | benefits all users and spreads the maintenance load around.
|
---|
500 | <p>
|
---|
501 |
|
---|
502 | Please consult the
|
---|
503 | <a href="http://jakarta.apache.org/site/getinvolved.html">Getting Involved</a> pages on the Jakarta web site
|
---|
504 | for details on how to fetch the latest source and how to submit changes for reincorporation into the
|
---|
505 | source tree.
|
---|
506 | <p>
|
---|
507 | Ant also has some
|
---|
508 | <a href="http://ant.apache.org/ant_task_guidelines.html">task guidelines</a>
|
---|
509 | which provides some advice to people developing and testing tasks. Even if you intend to
|
---|
510 | keep your tasks to yourself, you should still read this as it should be informative.
|
---|
511 |
|
---|
512 | </body>
|
---|
513 | </html>
|
---|
514 |
|
---|