About
How to develop a Task for Ant
Model / Requirements
Minimum Class Definition
public class HelloWorld {
public void execute() {
System.out.println("Hello World");
}
}
- A class is registered as an AnT task if it's provide a method with the signature “public void execute()”.
- The class doesn't need to extends no superclass and implements no interface
- The class may throws a BuildException.
This class is wrapped by Ant's TaskAdapter and uses reflection for:
- setting a reference to the project
- and calling the execute() method.
Subclass
The class may extend Task or another class that was designed to be extended.
Class | Description |
---|---|
AbstractCvsTask | Another task can extend this with some customized output processing |
JDBCTask | Handles JDBC configuration needed by SQL type tasks. |
MatchingTask | This is an abstract task that should be used by all those tasks that require to include or exclude files based on pattern matching. |
Pack | Abstract Base class for pack tasks. |
Unpack | Abstract Base class for unpack tasks. |
DispatchTask | Abstract Base class for tasks that may have multiple actions. |
Attribute/Parameter
To define an attribute, a public setter method must be provided such as:
public void set<attributename>(<type> newValue)
and Ant will do the rest via reflection.
The name of the method must:
- begin with set,
- followed by the attribute name,
- with the first character of the name in uppercase,
- and the rest in lowercase
Ant supports any of these datatypes as arguments of the set-method:
- elementary data type like int, long, …
- its wrapper classes like java.lang.Integer, java.lang.Long, …
- java.lang.String
- some more classes (e.g. java.io.File)
- Any Java Object parsed from Ant 1.8's Property Helper
Before calling the set-method all properties are resolved. So a ${msg} would not set the string to “${msg}” if there is a property “msg” with a set value.
Depending on the setter datatype argument, Ant will perform some DataType Conversions logic
- from the build file parameters (character)
- to the datatype of the setter method
Project
The Project object gives some abilities:
- access to Ant's logging facilities getting
- setting properties
- and much more.
The Project object is:
- not available from a custom task constructor (the return value will be null)
- available when node attributes or text are set, or when the method execute() is called.
Hello World with the use of the project class
package ant.mytask;
import org.apache.tools.ant.Project;
public class HelloWorld {
private Project project;
public void setProject(Project proj) {
project = proj;
}
public void execute() {
String message = project.getProperty("ant.project.name");
project.log("Here is project '" + message + "'.", Project.MSG_INFO);
}
}
Two useful methods from class Project:
- String getProperty(String propertyName)
- String replaceProperties(String value)
Container
If the task shall contain other tasks as nested elements (like parallel), your class must implement the interface TaskContainer. If you do so, your task can not support any other nested elements.
Execution Ant will call the perform method in Task, which in turn calls execute. This method makes sure that Build Events will be triggered. If you execute the task instances nested into your task, you should also invoke perform on these instances instead of execute.
Nested Element
A class must be create that will represent a nested element. Example: FileSet support nested fileset elements.
Attributes of the nested elements or nested child elements of them are handled using the same mechanism used for bar tasks. i.e.:
- setter methods for attributes,
- addText for nested text
- create/add/addConfigured methods for child elements. (See below for the first child ;)
To support nested element, the class need to add one of the below method:
- a create method
- or a add method
- or a addConfigured method.
Create
- A create method must be a public method that takes no arguments and returns an Object type.
- The name of the create method must begin with create, followed by the element name.
Example with an <inner> nested element:
public NestedElement createInner()
Add
The add (or addConfigured) method must be:
- a public void method that takes a single argument of an Object type with a no-argument constructor.
- named with the add (or addConfigured) prefix followed by the element name.
The Nested element class must have:
- a public no-arg constructor
- or a public one-arg constructor taking a project class as a parameter.
Example with an <inner> nested element:
public void addInner(NestedElement anInner)
public void addConfiguredInner(NestedElement anInner)
User/Application Input
When a task wants to prompt a user for input. See InputHandler
Build Event
Adding the task to the system
Taskdef
When using the task
- The class that implements your task is in the classpath when starting Ant.
- Add a <taskdef> element to your project. This actually adds your task to the system.
- Use your task in the rest of the buildfile.
When developing a task
To use a task directly from the buildfile which created it, place the <taskdef> declaration inside a target after the compilation. Use the classpath attribute of <taskdef> to point to where the code has just been compiled.
<?xml version="1.0"?>
<project name="OwnTaskExample2" default="main" basedir=".">
<!-- Compilation -->
<target name="build" >
<mkdir dir="build"/>
<javac srcdir="source" destdir="build"/>
</target>
<!-- Declare the task after compilation -->
<target name="declare" depends="build">
<taskdef name="mytask"
classname="com.mydomain.MyVeryOwnTask"
classpath="build"/>
</target>
<!-- Use the task after declaration -->
<target name="main" depends="declare">
<mytask message="Hello World! MyVeryOwnTask works!"/>
</target>
</project>
Taskdefs package property file
To add the task more permanently, you can add to the default.properties file in the org.apache.tools.ant.taskdefs package:
- the task name
- and the implementing class name