Previous Section
Table of Contents
Next Section


User-Defined Tasks

You can create user-defined tasks to extend the functioning of Ant. The user-defined tasks acquire the same interface as that of the built-in tasks. The main advantages of user-defined tasks are:

Components of a Task

The various components of a task are:

  • Superclasses: Contain a number of task classes. The Ant engine operates only on Task classes and not on the additions made to the child elements of the Task class. For example, if the task has to use file sets and patterns, you need to extend the org.apache.tools.ant.main.taskdef.MatchingTask class because this class employs a large number of file sets and pattern operations.

  • Attributes: Specify the type-value pairs that describe a specific XML tag. In most cases, attribute values are boolean values that act as process flags for the tasks. For example, the failonerror attribute in the <javac> task is boolean. When the flag is set to on, javac halts the build process if compilation is not successful. Alternately, javac allows the compilation to occur in the presence of an error.

  • Nested elements: Act as substitutes for the attributes. Nested elements can be data types or tasks. The difference between nested elements and attributes is that the corresponding class of the nested elements contains the data and the functions. For example, the <delete> task contains the dir attribute and the <fileset> nested element. Ant passes the directory object to the task class to set the attribute value. There are different ways to pass the fileset object to the task class. In all the cases, Ant sets the fileset nested element using the same life cycle as the task, which is a recursive process. This shows that Ant's process for managing nested elements is more complex than that for managing attributes.

Communication between Ant and Tasks

The Ant build engine uses different mechanisms to communicate with tasks. The three communication methods that the Ant build engine uses to communicate with Ant tasks are:

  • The Project class: Exists in every task as a public instance variable. It represents the complete build file and all the components of the build file that allow you to access all the tasks, properties, targets, and other parts of the build file. The Project class describes system-wide constants and global methods for all tasks. The constants are for system-call parameters, such as logging. The global methods offer functions, such as translating paths to a native form and providing a boolean translator for task attributes with boolean values. The method calls and constants available through the Project class are:

    • project.getGlobalFilterSet(): Returns a global FilterSet object relating to the build file. You can describe a global filter set by excluding or including a set of files for every task that constitutes a file or directory operation.

    • project.getBaseDir(): Returns the value of the basedir attribute in the <project> element.

    • project.translatePath(): Translates a generic path to the native format of the operating system you are using.

    • project.toBoolean: Verifies a boolean value. Tasks with boolean attributes can take the yes|no, true|false, or on|off values.


  • Build exceptions: Specify a method for Ant tasks to signal error conditions to the Ant build engine. You can implement build exceptions using the BuildException class. When you throw a BuildException from any point inside a task, the task stops immediately.

  • The Logging system: Provides methods to the task to show the progress report to the end user, such as the log() method. You can access this system using the Project class. The logging system provides messages displayed at different message levels. The message levels indicate to Ant at which state a message should show. For example, all error, warning, and info level messages are shown in the log. The message levels are error, warning, info, verbose, and debug.

The Task Life Cycle

The two primary phases of the life cycle of an Ant task are:

  • The parse-time phase: Specifies the phase in which Ant interprets the task from XML by processing nested elements.

  • The run time phase: Specifies the phase when the Ant task enters the action state. This phase starts when the parse-time phase ends successfully. Other targets and tasks may have already run successfully by the time a task enters the run time phase.

The Parse-Time Phase

In the parse-time phase, Ant processes nested elements rather than processing attributes. In this phase, Ant calls the createXXX(), addXXX(), or addConfiguredXXX() functions on the task, where XXX is the type of the nested element. This depends on the way you use the nested elements and the nature of the object corresponding to the nested element. You can use the createXXX() function if the object does not contain default constructor or if the task instantiates the element object. You can use the addXXX() function if you need to refer an instantiated object to the task. You can use the addConfiguredXXX() function to make Ant completely process the nested element before it passes the reference. Ant uses the Document Object Model (DOM) XML parser to parse the task.

The following actions are performed in a sequence on a task during the parse-time phase:

  1. Instantiating the task using a constructor, which accepts no arguments. The attributes are not set at this step.

  2. Building the references of the task to its project and the parent target objects. The task engine provides specific objects to the tasks using which the tasks can communicate with the task engine.

  3. Adding the ID attribute to register a reference to the new task. It is helpful for the tasks and data types that execute parallel processing.

  4. Calling the init() function present in the task object.

  5. Building all the nested elements of the XML element corresponding to the task using the createXXX() function and processing the elements using the addXXX() and addConfiguredXXX() functions.

The Run Time Phase

The run time phase starts at the end of the parse-time phase. During the run time phase, Ant processes the attributes of the task.

The following actions are performed in a sequence on a task during the run time phase:

  1. Setting all the attributes of the task with the help of corresponding setXXX() functions. If the set function is missing, it causes the failure of the build and the task.

  2. Adding content, which is in the form of character data present inside the XML element, to the task using the addText() function, as shown:

<taskname>
<! [CDATA[Sample text]]>
</taskname>

The above code shows a CDATA section. When Ant reads a CDATA section, it calls addtext("Sample text") on your task. If the task does not include the addtext() function and you add a CDATA element, the build fails.

  1. Setting all the attributes of nested elements using the corresponding setXXX() functions.

  2. Calling the execute() function to run the task so that it can perform its actions.

Ant Task Guidelines

You need to create Ant tasks in a standard format to easily integrate them with Ant. To create the Ant tasks in a standard format, the guidelines are:

  • Use Ant's built-in helper classes. This eases workload by minimizing the development, maintenance, and writing of the code.

  • Use the Execute task. This assists in invoking other programs. The Execute task detaches all the separate programs dealing with the Java and platform issues. The programs are present under various volumes of platforms supported by Ant.

  • Use the Java and ExecuteJava classes. This assists in spawning Java programs in a separate VM or in the same VM, with or without a different classholder.

  • Use project and related classes that contain functions that help delete, copy, or touch the file. Classes, such as Project, FileUtils, and JavaEnvUtils, help use the functions to avoid writing the code.



Previous Section
Table of Contents
Next Section