2006-09-11 04:19:00 +00:00
|
|
|
<!--
|
|
|
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
|
|
|
contributor license agreements. See the NOTICE file distributed with
|
|
|
|
this work for additional information regarding copyright ownership.
|
|
|
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
|
|
|
(the "License"); you may not use this file except in compliance with
|
|
|
|
the License. You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
-->
|
2001-02-13 12:32:01 +00:00
|
|
|
<html>
|
|
|
|
|
|
|
|
<head>
|
|
|
|
<meta http-equiv="Content-Language" content="en-us">
|
2005-04-29 18:58:16 +00:00
|
|
|
<link rel="stylesheet" type="text/css" href="stylesheets/style.css">
|
2002-02-04 20:57:49 +00:00
|
|
|
<title>Writing Your Own Task</title>
|
2001-02-13 12:32:01 +00:00
|
|
|
</head>
|
|
|
|
|
|
|
|
<body>
|
2010-11-11 17:04:16 +00:00
|
|
|
<h1>Developing with Apache Ant</h1>
|
2001-02-13 12:32:01 +00:00
|
|
|
|
2018-02-08 22:52:33 +01:00
|
|
|
<h2 id="writingowntask">Writing Your Own Task</h2>
|
2001-02-13 12:32:01 +00:00
|
|
|
<p>It is very easy to write your own task:</p>
|
|
|
|
<ol>
|
2018-03-10 20:17:33 +01:00
|
|
|
<li>Create a Java class that extends <code class="code">org.apache.tools.ant.Task</code>
|
2018-03-03 21:26:50 +01:00
|
|
|
or <a href="base_task_classes.html">another class</a> that was designed to be extended.</li>
|
|
|
|
|
|
|
|
<li id="footnote-1-back">For each attribute, write a <em>setter</em> method. The setter method
|
|
|
|
must be a <code>public void</code> method that takes a single argument. The name of the method
|
|
|
|
must begin with <code>set</code>, followed by the attribute name, with the first character of
|
2018-03-18 11:15:39 +01:00
|
|
|
the name in uppercase, and the rest in lowercase<a href="#footnote-1">*</a>. That is, to
|
|
|
|
support an attribute named <var>file</var> you create a
|
2018-03-10 20:17:33 +01:00
|
|
|
method <code class="code">setFile</code>. Depending on the type of the argument, Ant will
|
|
|
|
perform some conversions for you, see <a href="#set-magic">below</a>.</li>
|
2018-03-03 21:26:50 +01:00
|
|
|
|
|
|
|
<li>If your task shall contain other tasks as nested elements
|
|
|
|
(like <a href="Tasks/parallel.html"><code>parallel</code></a>), your class must implement the
|
2018-03-10 20:17:33 +01:00
|
|
|
interface <code class="code">org.apache.tools.ant.TaskContainer</code>. If you do so, your task
|
|
|
|
can not support any other nested elements. See <a href="#taskcontainer">below</a>.</li>
|
2018-03-03 21:26:50 +01:00
|
|
|
|
|
|
|
<li>If the task should support character data (text nested between the start and end tags), write
|
2018-03-10 20:17:33 +01:00
|
|
|
a <code class="code">public void addText(String)</code> method. Note that Ant
|
|
|
|
does <strong>not</strong> expand properties on the text it passes to the task.</li>
|
2018-03-03 21:26:50 +01:00
|
|
|
|
|
|
|
<li>For each nested element, write a <em>create</em>, <em>add</em> or <em>addConfigured</em>
|
2018-03-18 11:15:39 +01:00
|
|
|
method. A create method must be a <code>public</code> method that takes no arguments and
|
|
|
|
returns an <code>Object</code> type. The name of the create method must begin
|
|
|
|
with <code>create</code>, followed by the element name. An add (or addConfigured) method must be
|
|
|
|
a <code>public void</code> method that takes a single argument of an <code>Object</code> type
|
|
|
|
with a no-argument constructor. The name of the add (addConfigured) method must begin
|
|
|
|
with <code>add</code> (<code>addConfigured</code>), followed by the element name. For a more
|
|
|
|
complete discussion see <a href="#nested-elements">below</a>.</li>
|
2018-03-03 21:26:50 +01:00
|
|
|
|
2018-03-10 20:17:33 +01:00
|
|
|
<li>Write a <code class="code">public void execute()</code> method, with no arguments, that throws
|
2018-03-03 21:26:50 +01:00
|
|
|
a <code>BuildException</code>. This method implements the task itself.</li>
|
2001-02-13 12:32:01 +00:00
|
|
|
</ol>
|
|
|
|
|
2018-03-04 10:36:45 +01:00
|
|
|
<hr/>
|
2018-03-03 21:26:50 +01:00
|
|
|
<p id="footnote-1"><a href="#footnote-1-back">*</a> Actually the case of the letters after the first
|
|
|
|
one doesn't really matter to Ant, using all lower case is a good convention, though.</p>
|
2003-10-14 08:29:15 +00:00
|
|
|
|
2001-02-13 12:32:01 +00:00
|
|
|
<h3>The Life-cycle of a Task</h3>
|
|
|
|
<ol>
|
2018-03-03 21:26:50 +01:00
|
|
|
<li>The xml element that contains the tag corresponding to the task gets converted to
|
2018-03-10 20:17:33 +01:00
|
|
|
an <code class="code">UnknownElement</code> at parse time.
|
|
|
|
This <code class="code">UnknownElement</code> gets placed in a list within a target object, or
|
|
|
|
recursively within another <code class="code">UnknownElement</code>.
|
2007-08-23 08:23:05 +00:00
|
|
|
</li>
|
2018-03-03 21:26:50 +01:00
|
|
|
|
2018-03-10 20:17:33 +01:00
|
|
|
<li>When the target is executed, each <code class="code">UnknownElement</code> is invoked using
|
|
|
|
an <code class="code">perform()</code> method. This instantiates the task. This means that tasks
|
|
|
|
only gets instantiated at run time.
|
2007-08-23 08:23:05 +00:00
|
|
|
</li>
|
2001-02-13 12:32:01 +00:00
|
|
|
|
2018-03-03 21:26:50 +01:00
|
|
|
<li>The task gets references to its project and location inside the buildfile via its
|
|
|
|
inherited <code>project</code> and <code>location</code> variables.</li>
|
2001-02-13 12:32:01 +00:00
|
|
|
|
2018-03-03 21:26:50 +01:00
|
|
|
<li>If the user specified an <var>id</var> attribute to this task, the project registers a
|
|
|
|
reference to this newly created task, at run time.</li>
|
2001-02-13 12:32:01 +00:00
|
|
|
|
2018-03-03 21:26:50 +01:00
|
|
|
<li>The task gets a reference to the target it belongs to via its inherited <code>target</code>
|
|
|
|
variable.</li>
|
2001-02-13 12:32:01 +00:00
|
|
|
|
2018-03-10 20:17:33 +01:00
|
|
|
<li><code class="code">init()</code> is called at run time.</li>
|
2001-02-13 12:32:01 +00:00
|
|
|
|
2018-03-03 21:26:50 +01:00
|
|
|
<li>All child elements of the XML element corresponding to this task are created via this
|
2018-03-10 20:17:33 +01:00
|
|
|
task's <code class="code">createXXX()</code> methods or instantiated and added to this task via
|
|
|
|
its <code class="code">addXXX()</code> methods, at run time. Child elements corresponding
|
|
|
|
to <code class="code">addConfiguredXXX()</code> are created at this point but the
|
|
|
|
actual <em>addConfigured</em> method is not called.</li>
|
2001-02-13 12:32:01 +00:00
|
|
|
|
2018-03-10 20:17:33 +01:00
|
|
|
<li>All attributes of this task get set via their corresponding <code class="code">setXXX()</code>
|
2018-03-18 07:55:29 +01:00
|
|
|
methods, at run time.</li>
|
2001-02-13 12:32:01 +00:00
|
|
|
|
2018-03-03 21:26:50 +01:00
|
|
|
<li>The content character data sections inside the XML element corresponding to this task is added
|
2018-03-18 07:55:29 +01:00
|
|
|
to the task via its <code class="code">addText()</code> method, at run time.</li>
|
2001-02-13 12:32:01 +00:00
|
|
|
|
2018-03-10 20:17:33 +01:00
|
|
|
<li>All attributes of all child elements get set via their
|
2018-03-18 07:55:29 +01:00
|
|
|
corresponding <code class="code">setXXX()</code> methods, at run time.</li>
|
2001-02-13 12:32:01 +00:00
|
|
|
|
2018-03-03 21:26:50 +01:00
|
|
|
<li>If child elements of the XML element corresponding to this task have been created
|
2018-03-10 20:17:33 +01:00
|
|
|
for <code class="code">addConfiguredXXX()</code> methods, those methods get invoked now.</li>
|
2010-02-15 16:04:24 +00:00
|
|
|
|
2018-03-18 07:55:29 +01:00
|
|
|
<li id="execute"><code class="code">execute()</code> is called at run time. If <q>target1</q>
|
2018-03-10 20:17:33 +01:00
|
|
|
and <q>target2</q> both depend on <q>target3</q>, then running <kbd>ant target1 target2</kbd>
|
|
|
|
will run all tasks in <q>target3</q> twice.</li>
|
2001-02-13 12:32:01 +00:00
|
|
|
</ol>
|
|
|
|
|
2018-02-08 22:52:33 +01:00
|
|
|
<h3 id="set-magic">Conversions Ant will perform for attributes</h3>
|
2002-03-27 16:32:49 +00:00
|
|
|
|
2018-03-03 21:26:50 +01:00
|
|
|
<p>Ant will always expand properties before it passes the value of an attribute to the corresponding
|
|
|
|
setter method. <em>Since Ant 1.8</em>, it is possible to <a href="Tasks/propertyhelper.html">extend
|
|
|
|
Ant's property handling</a> such that a non-string Object may be the result of the evaluation of a
|
|
|
|
string containing a single property reference. These will be assigned directly via setter methods of
|
|
|
|
matching type. Since it requires some beyond-the-basics intervention to enable this behavior, it may
|
|
|
|
be a good idea to flag attributes intended to permit this usage paradigm.</p>
|
2008-07-16 17:18:02 +00:00
|
|
|
|
2018-03-10 20:17:33 +01:00
|
|
|
<p>The most common way to write an attribute setter is to use
|
|
|
|
a <code class="code">java.lang.String</code> argument. In this case Ant will pass the literal value
|
|
|
|
(after property expansion) to your task. But there is more! If the argument of you setter method
|
|
|
|
is</p>
|
2006-12-01 18:10:20 +00:00
|
|
|
|
2018-03-03 21:26:50 +01:00
|
|
|
<ul>
|
2018-03-10 20:17:33 +01:00
|
|
|
<li><code>boolean</code>, your method will be passed the value <q>true</q> if the value specified
|
|
|
|
in the build file is one of <q>true</q>, <q>yes</q>, or <q>on</q> and <q>false</q>
|
|
|
|
otherwise.</li>
|
2018-03-03 21:26:50 +01:00
|
|
|
|
2018-03-10 20:17:33 +01:00
|
|
|
<li><code>char</code> or <code class="code">java.lang.Character</code>, your method will be passed
|
|
|
|
the first character of the value specified in the build file.</li>
|
2018-03-03 21:26:50 +01:00
|
|
|
|
2018-03-10 20:17:33 +01:00
|
|
|
<li>any other primitive type (<code class="code">int</code>, <code class="code">short</code> and
|
|
|
|
so on), Ant will convert the value of the attribute into this type, thus making sure that you'll
|
|
|
|
never receive input that is not a number for that attribute.</li>
|
2018-03-03 21:26:50 +01:00
|
|
|
|
2018-03-10 20:17:33 +01:00
|
|
|
<li><code class="code">java.io.File</code>, Ant will first determine whether the value given in
|
|
|
|
the build file represents an absolute path name. If not, Ant will interpret the value as a path
|
|
|
|
name relative to the project's <var>basedir</var>.</li>
|
2018-03-03 21:26:50 +01:00
|
|
|
|
2018-03-10 20:17:33 +01:00
|
|
|
<li><code class="code">org.apache.tools.ant.types.Resource</code>, Ant will resolve the string as
|
|
|
|
a <code class="code">java.io.File</code> as above, then pass in as
|
|
|
|
a <code class="code">org.apache.tools.ant.types.resources.FileResource</code>. <em>Since Ant
|
|
|
|
1.8</em></li>
|
2018-03-03 21:26:50 +01:00
|
|
|
|
2018-03-10 20:17:33 +01:00
|
|
|
<li><code class="code">org.apache.tools.ant.types.Path</code>, Ant will tokenize the value
|
|
|
|
specified in the build file, accepting <q>:</q> and <q>;</q> as path separators. Relative path
|
|
|
|
names will be interpreted as relative to the project's <var>basedir</var>.</li>
|
2018-03-03 21:26:50 +01:00
|
|
|
|
2018-03-10 20:17:33 +01:00
|
|
|
<li><code class="code">java.lang.Class</code>, Ant will interpret the value given in the build
|
|
|
|
file as a Java class name and load the named class from the system class loader.</li>
|
2018-03-03 21:26:50 +01:00
|
|
|
|
2018-03-10 20:17:33 +01:00
|
|
|
<li>any other type that has a constructor with a single <code class="code">String</code> argument,
|
|
|
|
Ant will use this constructor to create a new instance from the value given in the build
|
|
|
|
file.</li>
|
2018-03-03 21:26:50 +01:00
|
|
|
|
2018-03-10 20:17:33 +01:00
|
|
|
<li>A subclass of <code class="code">org.apache.tools.ant.types.EnumeratedAttribute</code>, Ant
|
|
|
|
will invoke this class's <code class="code">setValue</code> method. Use this if your task
|
|
|
|
should support enumerated attributes (attributes with values that must be part of a predefined
|
|
|
|
set of values). See <code>org/apache/tools/ant/taskdefs/FixCRLF.java</code> and the
|
|
|
|
inner <code class="code">AddAsisRemove</code> class used in <code class="code">setCr</code> for
|
|
|
|
an example.</li>
|
2018-03-03 21:26:50 +01:00
|
|
|
|
|
|
|
<li>A (Java 5) enumeration, Ant will call the setter with the enum constant matching the value
|
2018-03-10 20:17:33 +01:00
|
|
|
given in the build file. This is easier than using <code class="code">EnumeratedAttribute</code>
|
|
|
|
and can result in cleaner code, but of course your task will not run on JDK 1.4 or earlier. Note
|
|
|
|
that any override of <code class="code">toString()</code> in the enumeration is ignored; the
|
|
|
|
build file must use the declared name (see <code>Enum.getName()</code>). You may wish to use
|
|
|
|
lowercase enum constant names, in contrast to usual Java style, to look better in build
|
|
|
|
files. <em>Since Ant 1.7.0</em></li>
|
2002-03-27 16:32:49 +00:00
|
|
|
</ul>
|
|
|
|
|
2018-03-03 21:26:50 +01:00
|
|
|
<p>What happens if more than one setter method is present for a given attribute? A method taking
|
2018-03-10 20:17:33 +01:00
|
|
|
a <code class="code">String</code> argument will always lose against the more specific methods. If
|
|
|
|
there are still more setters Ant could chose from, only one of them will be called, but we don't
|
|
|
|
know which, this depends on the implementation of your Java virtual machine.</p>
|
2002-03-27 16:32:49 +00:00
|
|
|
|
2018-02-08 22:52:33 +01:00
|
|
|
<h3 id="nested-elements">Supporting nested elements</h3>
|
2002-03-27 16:32:49 +00:00
|
|
|
|
2018-03-03 21:26:50 +01:00
|
|
|
<p>Let's assume your task shall support nested elements with the name <code>inner</code>. First of
|
|
|
|
all, you need a class that represents this nested element. Often you simply want to use one of
|
2018-03-10 20:17:33 +01:00
|
|
|
Ant's classes like <code class="code">org.apache.tools.ant.types.FileSet</code> to support
|
2018-03-03 21:26:50 +01:00
|
|
|
nested <code>fileset</code> elements.</p>
|
2002-03-27 16:32:49 +00:00
|
|
|
|
2018-03-03 21:26:50 +01:00
|
|
|
<p>Attributes of the nested elements or nested child elements of them will be handled using the same
|
2018-03-10 20:17:33 +01:00
|
|
|
mechanism used for tasks (i.e. <em>setter</em> methods for
|
|
|
|
attributes, <code class="code">addText()</code> for nested text
|
|
|
|
and <em>create</em>/<em>add</em>/<em>addConfigured</em> methods for child elements).</p>
|
2002-03-27 16:32:49 +00:00
|
|
|
|
2018-03-10 20:17:33 +01:00
|
|
|
<p>Now you have a class <code class="code">NestedElement</code> that is supposed to be used for your
|
2018-03-03 21:26:50 +01:00
|
|
|
nested <code><inner></code> elements, you have three options:</p>
|
2002-03-27 16:32:49 +00:00
|
|
|
|
|
|
|
<ol>
|
2018-03-10 20:17:33 +01:00
|
|
|
<li><code class="code">public NestedElement createInner()</code></li>
|
|
|
|
<li><code class="code">public void addInner(NestedElement anInner)</code></li>
|
|
|
|
<li><code class="code">public void addConfiguredInner(NestedElement anInner)</code></li>
|
2002-03-27 16:32:49 +00:00
|
|
|
</ol>
|
|
|
|
|
|
|
|
<p>What is the difference?</p>
|
|
|
|
|
2018-03-10 20:17:33 +01:00
|
|
|
<p>Option 1 makes the task create the instance of <code class="code">NestedElement</code>, there are
|
|
|
|
no restrictions on the type. For the options 2 and 3, Ant has to create an instance
|
|
|
|
of <code class="code">NestedInner</code> before it can pass it to the task, this
|
|
|
|
means, <code class="code">NestedInner</code> must have a <code>public</code> no-arg constructor or
|
|
|
|
a <code>public</code> one-arg constructor taking a <code class="code">Project</code> class as a
|
|
|
|
parameter. This is the only difference between options 1 and 2.</p>
|
2018-03-03 21:26:50 +01:00
|
|
|
|
|
|
|
<p>The difference between 2 and 3 is what Ant has done to the object before it passes it to the
|
2018-03-10 20:17:33 +01:00
|
|
|
method. <code class="code">addInner()</code> will receive an object directly after the constructor
|
|
|
|
has been called, while <code class="code">addConfiguredInner()</code> gets the object <em>after</em>
|
|
|
|
the attributes and nested children for this new object have been handled.</p>
|
2018-03-03 21:26:50 +01:00
|
|
|
|
|
|
|
<p>What happens if you use more than one of the options? Only one of the methods will be called,
|
|
|
|
but we don't know which, this depends on the implementation of your JVM.</p>
|
2002-03-27 16:32:49 +00:00
|
|
|
|
2018-02-08 22:52:33 +01:00
|
|
|
<h3 id="nestedtype">Nested Types</h3>
|
2018-03-03 21:26:50 +01:00
|
|
|
<p>If your task needs to nest an arbitrary type that has been defined
|
|
|
|
using <code><typedef></code> you have two options.</p>
|
|
|
|
<ol>
|
2018-03-10 20:17:33 +01:00
|
|
|
<li><code class="code">public void add(Type type)</code></li>
|
|
|
|
<li><code class="code">public void addConfigured(Type type)</code></li>
|
2018-03-03 21:26:50 +01:00
|
|
|
</ol>
|
|
|
|
<p>The difference between 1 and 2 is the same as between 2 and 3 in the previous section.</p>
|
|
|
|
<p>For example suppose one wanted to handle objects object of
|
2018-03-10 20:17:33 +01:00
|
|
|
type <code class="code">org.apache.tools.ant.taskdefs.condition.Condition</code>, one may have a
|
|
|
|
class:</p>
|
2018-03-03 21:26:50 +01:00
|
|
|
<pre>
|
2003-10-08 13:29:55 +00:00
|
|
|
public class MyTask extends Task {
|
|
|
|
private List conditions = new ArrayList();
|
|
|
|
public void add(Condition c) {
|
|
|
|
conditions.add(c);
|
|
|
|
}
|
|
|
|
public void execute() {
|
|
|
|
// iterator over the conditions
|
|
|
|
}
|
2018-02-28 07:58:59 +01:00
|
|
|
}</pre>
|
2018-03-03 21:26:50 +01:00
|
|
|
<p>One may define and use this class like this:</p>
|
2018-02-09 06:54:03 +01:00
|
|
|
<pre>
|
2003-10-08 13:29:55 +00:00
|
|
|
<taskdef name="mytask" classname="MyTask" classpath="classes"/>
|
|
|
|
<typedef name="condition.equals"
|
|
|
|
classname="org.apache.tools.ant.taskdefs.conditions.Equals"/>
|
|
|
|
<mytask>
|
|
|
|
<condition.equals arg1="${debug}" arg2="true"/>
|
2018-02-28 07:58:59 +01:00
|
|
|
</mytask></pre>
|
2018-03-03 21:26:50 +01:00
|
|
|
<p>A more complicated example follows:</p>
|
2018-02-09 06:54:03 +01:00
|
|
|
<pre>
|
2003-10-08 13:29:55 +00:00
|
|
|
public class Sample {
|
|
|
|
public static class MyFileSelector implements FileSelector {
|
|
|
|
public void setAttrA(int a) {}
|
|
|
|
public void setAttrB(int b) {}
|
|
|
|
public void add(Path path) {}
|
|
|
|
public boolean isSelected(File basedir, String filename, File file) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
interface MyInterface {
|
|
|
|
void setVerbose(boolean val);
|
2018-02-08 22:52:33 +01:00
|
|
|
}
|
2003-10-08 13:29:55 +00:00
|
|
|
|
|
|
|
public static class BuildPath extends Path {
|
|
|
|
public BuildPath(Project project) {
|
|
|
|
super(project);
|
|
|
|
}
|
2018-02-08 22:52:33 +01:00
|
|
|
|
2003-10-08 13:29:55 +00:00
|
|
|
public void add(MyInterface inter) {}
|
|
|
|
public void setUrl(String url) {}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static class XInterface implements MyInterface {
|
|
|
|
public void setVerbose(boolean x) {}
|
|
|
|
public void setCount(int c) {}
|
|
|
|
}
|
2018-02-28 07:58:59 +01:00
|
|
|
}</pre>
|
2018-03-03 21:26:50 +01:00
|
|
|
<p>This class defines a number of static classes that
|
2018-03-10 20:17:33 +01:00
|
|
|
implement/extend <code class="code">Path</code>, <code class="code">MyFileSelector</code>
|
|
|
|
and <code class="code">MyInterface</code>. These may be defined and used as follows:</p>
|
2018-02-09 06:54:03 +01:00
|
|
|
<pre>
|
2003-10-08 13:29:55 +00:00
|
|
|
<typedef name="myfileselector" classname="Sample$MyFileSelector"
|
|
|
|
classpath="classes" loaderref="classes"/>
|
|
|
|
<typedef name="buildpath" classname="Sample$BuildPath"
|
|
|
|
classpath="classes" loaderref="classes"/>
|
|
|
|
<typedef name="xinterface" classname="Sample$XInterface"
|
|
|
|
classpath="classes" loaderref="classes"/>
|
|
|
|
|
|
|
|
<copy todir="copy-classes">
|
|
|
|
<fileset dir="classes">
|
|
|
|
<myfileselector attra="10" attrB="-10">
|
|
|
|
<buildpath path="." url="abc">
|
|
|
|
<xinterface count="4"/>
|
|
|
|
</buildpath>
|
|
|
|
</myfileselector>
|
|
|
|
</fileset>
|
2018-02-28 07:58:59 +01:00
|
|
|
</copy></pre>
|
2015-05-28 08:25:47 +02:00
|
|
|
|
2018-02-08 22:52:33 +01:00
|
|
|
<h3 id="taskcontainer">TaskContainer</h3>
|
2002-03-27 16:32:49 +00:00
|
|
|
|
2018-03-10 20:17:33 +01:00
|
|
|
<p>The <code class="code">TaskContainer</code> consists of a single
|
|
|
|
method, <code class="code">addTask</code> that basically is the same as
|
|
|
|
an <a href="#nested-elements">add method</a> for nested elements. The task instances will be
|
|
|
|
configured (their attributes and nested elements have been handled) when your
|
|
|
|
task's <code class="code">execute</code> method gets invoked, but not before that.</p>
|
2018-03-03 21:26:50 +01:00
|
|
|
|
2018-03-10 20:17:33 +01:00
|
|
|
<p>When we <a href="#execute">said</a> <code class="code">execute</code> would be called, we lied
|
|
|
|
;-). In fact, Ant will call the <code class="code">perform</code> method
|
|
|
|
in <code class="code">org.apache.tools.ant.Task</code>, which in turn
|
|
|
|
calls <code class="code">execute</code>. This method makes sure that <a href="#buildevents">Build
|
2018-03-03 21:26:50 +01:00
|
|
|
Events</a> will be triggered. If you execute the task instances nested into your task, you should
|
2018-03-10 20:17:33 +01:00
|
|
|
also invoke <code class="code">perform</code> on these instances instead
|
|
|
|
of <code class="code">execute</code>.</p>
|
2002-03-27 16:32:49 +00:00
|
|
|
|
2001-02-13 12:32:01 +00:00
|
|
|
<h3>Example</h3>
|
2018-03-03 21:26:50 +01:00
|
|
|
<p>Let's write our own task, which prints a message on the <code>System.out</code> stream. The task
|
|
|
|
has one attribute, called <code>message</code>.</p>
|
2018-02-09 06:54:03 +01:00
|
|
|
|
2001-02-13 12:32:01 +00:00
|
|
|
<pre>
|
|
|
|
package com.mydomain;
|
|
|
|
|
|
|
|
import org.apache.tools.ant.BuildException;
|
|
|
|
import org.apache.tools.ant.Task;
|
|
|
|
|
|
|
|
public class MyVeryOwnTask extends Task {
|
2002-03-27 16:32:49 +00:00
|
|
|
private String msg;
|
2001-02-13 12:32:01 +00:00
|
|
|
|
2002-03-27 16:32:49 +00:00
|
|
|
// The method executing the task
|
|
|
|
public void execute() throws BuildException {
|
|
|
|
System.out.println(msg);
|
|
|
|
}
|
2001-02-13 12:32:01 +00:00
|
|
|
|
2002-03-27 16:32:49 +00:00
|
|
|
// The setter for the "message" attribute
|
|
|
|
public void setMessage(String msg) {
|
|
|
|
this.msg = msg;
|
|
|
|
}
|
2018-02-28 07:58:59 +01:00
|
|
|
}</pre>
|
2018-02-09 06:54:03 +01:00
|
|
|
|
2001-02-13 12:32:01 +00:00
|
|
|
<p>It's really this simple ;-)</p>
|
|
|
|
<p>Adding your task to the system is rather simple too:</p>
|
|
|
|
<ol>
|
2018-03-03 21:26:50 +01:00
|
|
|
<li>Make sure the class that implements your task is in the classpath when starting Ant.</li>
|
|
|
|
<li>Add a <code><taskdef></code> element to your project. This actually adds your task to
|
|
|
|
the system.</li>
|
2001-02-13 12:32:01 +00:00
|
|
|
<li>Use your task in the rest of the buildfile.</li>
|
|
|
|
</ol>
|
|
|
|
|
|
|
|
<h3>Example</h3>
|
2018-02-09 06:54:03 +01:00
|
|
|
|
2001-02-13 12:32:01 +00:00
|
|
|
<pre>
|
|
|
|
<?xml version="1.0"?>
|
|
|
|
|
|
|
|
<project name="OwnTaskExample" default="main" basedir=".">
|
|
|
|
<taskdef name="mytask" classname="com.mydomain.MyVeryOwnTask"/>
|
|
|
|
|
|
|
|
<target name="main">
|
|
|
|
<mytask message="Hello World! MyVeryOwnTask works!"/>
|
|
|
|
</target>
|
2018-02-28 07:58:59 +01:00
|
|
|
</project></pre>
|
2015-05-28 08:25:47 +02:00
|
|
|
|
2001-10-14 04:39:49 +00:00
|
|
|
<h3>Example 2</h3>
|
2018-03-03 21:26:50 +01:00
|
|
|
<p>To use a task directly from the buildfile which created it, place
|
|
|
|
the <code><taskdef></code> declaration inside a target <em>after the compilation</em>. Use
|
|
|
|
the <var>classpath</var> attribute of <code><taskdef></code> to point to where the code has
|
|
|
|
just been compiled.</p>
|
2018-02-09 06:54:03 +01:00
|
|
|
|
2001-10-14 04:39:49 +00:00
|
|
|
<pre>
|
|
|
|
<?xml version="1.0"?>
|
|
|
|
|
|
|
|
<project name="OwnTaskExample2" default="main" basedir=".">
|
|
|
|
|
|
|
|
<target name="build" >
|
|
|
|
<mkdir dir="build"/>
|
|
|
|
<javac srcdir="source" destdir="build"/>
|
|
|
|
</target>
|
2002-02-04 20:57:49 +00:00
|
|
|
|
2001-10-14 04:39:49 +00:00
|
|
|
<target name="declare" depends="build">
|
2002-02-04 20:57:49 +00:00
|
|
|
<taskdef name="mytask"
|
2001-10-14 04:39:49 +00:00
|
|
|
classname="com.mydomain.MyVeryOwnTask"
|
|
|
|
classpath="build"/>
|
|
|
|
</target>
|
|
|
|
|
|
|
|
<target name="main" depends="declare">
|
|
|
|
<mytask message="Hello World! MyVeryOwnTask works!"/>
|
|
|
|
</target>
|
2018-02-28 07:58:59 +01:00
|
|
|
</project></pre>
|
2001-10-14 04:39:49 +00:00
|
|
|
|
2018-03-03 21:26:50 +01:00
|
|
|
<p>Another way to add a task (more permanently) is to add the task name and implementing class name
|
2018-03-10 20:17:33 +01:00
|
|
|
to the <samp>default.properties</samp> file in
|
|
|
|
the <code class="code">org.apache.tools.ant.taskdefs</code> package. Then you can use it as if it
|
|
|
|
were a built-in task.</p>
|
2001-02-13 12:32:01 +00:00
|
|
|
|
2018-03-04 10:36:45 +01:00
|
|
|
<hr/>
|
2018-02-08 22:52:33 +01:00
|
|
|
<h2 id="buildevents">Build Events</h2>
|
2015-05-28 08:25:47 +02:00
|
|
|
<p>Ant is capable of generating build events as it performs the tasks necessary to build a project.
|
2018-03-03 21:26:50 +01:00
|
|
|
Listeners can be attached to Ant to receive these events. This capability could be used, for
|
|
|
|
example, to connect Ant to a GUI or to integrate Ant with an IDE.</p>
|
2018-03-10 20:17:33 +01:00
|
|
|
<p>To use build events you need to create an ant <code class="code">Project</code> object. You can
|
|
|
|
then call the <code class="code">addBuildListener</code> method to add your listener to the
|
|
|
|
project. Your listener must implement
|
|
|
|
the <code class="code">org.apache.tools.antBuildListener</code> interface. The listener will receive
|
2018-03-03 21:26:50 +01:00
|
|
|
BuildEvents for the following events</p>
|
2001-02-13 12:32:01 +00:00
|
|
|
<ul>
|
2015-05-28 08:25:47 +02:00
|
|
|
<li>Build started</li>
|
|
|
|
<li>Build finished</li>
|
|
|
|
<li>Target started</li>
|
|
|
|
<li>Target finished</li>
|
|
|
|
<li>Task started</li>
|
|
|
|
<li>Task finished</li>
|
|
|
|
<li>Message logged</li>
|
2001-02-13 12:32:01 +00:00
|
|
|
</ul>
|
|
|
|
|
2018-03-03 21:26:50 +01:00
|
|
|
<p>If the build file invokes another build file
|
|
|
|
via <a href="Tasks/ant.html"><code><ant></code></a>
|
|
|
|
or <a href="Tasks/subant.html"><code><subant></code></a> or
|
|
|
|
uses <a href="Tasks/antcall.html"><code><antcall></code></a>, you are creating a new Ant
|
|
|
|
"project" that will send target and task level events of its own but never sends build
|
2018-03-10 20:17:33 +01:00
|
|
|
started/finished events. <em>Since Ant 1.6.2</em>, <code class="code">BuildListener</code> interface
|
|
|
|
has an extension named <code class="code">SubBuildListener</code> that will receive two new events
|
|
|
|
for</p>
|
2004-06-25 07:59:46 +00:00
|
|
|
<ul>
|
2015-05-28 08:25:47 +02:00
|
|
|
<li>SubBuild started</li>
|
|
|
|
<li>SubBuild finished</li>
|
2004-06-25 07:59:46 +00:00
|
|
|
</ul>
|
2018-03-03 21:26:50 +01:00
|
|
|
<p>If you are interested in those events, all you need to do is to implement the new interface
|
2018-03-10 20:17:33 +01:00
|
|
|
instead of <code class="code">BuildListener</code> (and register the listener, of course).</p>
|
2004-06-25 07:59:46 +00:00
|
|
|
|
2018-03-10 20:17:33 +01:00
|
|
|
<p>If you wish to attach a listener from the command line you may use the <kbd>-listener</kbd>
|
2018-03-03 21:26:50 +01:00
|
|
|
option. For example:</p>
|
2018-02-09 06:54:03 +01:00
|
|
|
|
2018-03-10 20:17:33 +01:00
|
|
|
<pre class="input">ant -listener org.apache.tools.ant.XmlLogger</pre>
|
2018-02-09 06:54:03 +01:00
|
|
|
|
2002-02-04 20:57:49 +00:00
|
|
|
<p>will run Ant with a listener that generates an XML representation of the build progress. This
|
2018-03-03 21:26:50 +01:00
|
|
|
listener is included with Ant, as is the default listener, which generates the logging to standard
|
|
|
|
output.</p>
|
2001-02-13 12:32:01 +00:00
|
|
|
|
2018-03-10 20:17:33 +01:00
|
|
|
<p><strong>Note</strong>: A listener must not access <code class="code">System.out</code>
|
|
|
|
and <code class="code">System.err</code> directly since output on these streams is redirected by
|
|
|
|
Ant's core to the build event system. Accessing these streams can cause an infinite loop in
|
|
|
|
Ant. Depending on the version of Ant, this will either cause the build to terminate or the JVM to
|
|
|
|
run out of Stack space. A logger, also, may not access <code class="code">System.out</code>
|
|
|
|
and <code class="code">System.err</code> directly. It must use the streams with which it has been
|
|
|
|
configured.</p>
|
2003-02-17 14:12:10 +00:00
|
|
|
|
2018-03-10 20:17:33 +01:00
|
|
|
<p><strong>Note</strong>: All methods of a <code class="code">BuildListener</code> except for the
|
|
|
|
"Build Started" and "Build Finished" events may occur on several threads simultaneously—for
|
|
|
|
example while Ant is executing a <code><parallel></code> task.</p>
|
2008-06-19 12:20:12 +00:00
|
|
|
|
2018-01-22 14:54:08 +01:00
|
|
|
<h3>Example</h3>
|
2018-03-10 20:17:33 +01:00
|
|
|
<p>Writing an adapter to your favourite log library is very easy. Just implement
|
|
|
|
the <code class="code">BuildListener</code> interface, instantiate your logger and delegate the
|
|
|
|
message to that instance.</p>
|
2018-03-03 21:26:50 +01:00
|
|
|
<p>When starting your build provide your adapter class and the log library to the build classpath
|
2018-03-10 20:17:33 +01:00
|
|
|
and activate your logger via <kbd>-listener</kbd> option as described above.</p>
|
2018-01-22 14:54:08 +01:00
|
|
|
|
|
|
|
<pre>
|
|
|
|
public class MyLogAdapter implements BuildListener {
|
|
|
|
|
|
|
|
private MyLogger getLogger() {
|
|
|
|
final MyLogger log = MyLoggerFactory.getLogger(Project.class.getName());
|
|
|
|
return log;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void buildStarted(final BuildEvent event) {
|
|
|
|
final MyLogger log = getLogger();
|
|
|
|
log.info("Build started.");
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void buildFinished(final BuildEvent event) {
|
|
|
|
final MyLogger logger = getLogger();
|
|
|
|
MyLogLevelEnum loglevel = ... // map event.getPriority() to enum via Project.MSG_* constants
|
|
|
|
boolean allOK = event.getException() == null;
|
|
|
|
String logmessage = ... // create log message using data of the event and the message invoked
|
|
|
|
logger.log(loglevel, logmessage);
|
|
|
|
}
|
|
|
|
|
|
|
|
// implement all methods in that way
|
2018-02-28 07:58:59 +01:00
|
|
|
}</pre>
|
2018-01-22 14:54:08 +01:00
|
|
|
|
2018-03-04 10:36:45 +01:00
|
|
|
<hr/>
|
2018-02-08 22:52:33 +01:00
|
|
|
<h2 id="integration">Source code integration</h2>
|
2001-11-09 21:15:10 +00:00
|
|
|
|
2018-03-03 21:26:50 +01:00
|
|
|
<p>The other way to extend Ant through Java is to make changes to existing tasks, which is
|
|
|
|
positively encouraged. Both changes to the existing source and new tasks can be incorporated back
|
|
|
|
into the Ant codebase, which benefits all users and spreads the maintenance load around.</p>
|
2001-11-09 21:15:10 +00:00
|
|
|
|
2018-03-08 07:43:53 +01:00
|
|
|
<p>Please consult the <a href="https://www.apache.org/foundation/getinvolved.html"
|
|
|
|
target="_top">Getting Involved</a> pages on the Apache web site for details on how to fetch the
|
|
|
|
latest source and how to submit changes for reincorporation into the source tree.</p>
|
2015-05-28 08:25:47 +02:00
|
|
|
|
2018-03-08 07:43:53 +01:00
|
|
|
<p>Ant also has some <a href="https://ant.apache.org/ant_task_guidelines.html" target="_top">task
|
|
|
|
guidelines</a> which provides some advice to people developing and testing tasks. Even if you intend
|
|
|
|
to keep your tasks to yourself, you should still read this as it should be informative.</p>
|
2001-11-09 21:15:10 +00:00
|
|
|
|
2001-02-13 12:32:01 +00:00
|
|
|
</body>
|
|
|
|
</html>
|