[19253] | 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 |
|
---|