Using Apache Ant™ Tasks Outside of Ant

Rationale

Apache Ant provides a rich set of tasks for buildfile creators and administrators. But what about programmers? Can the functionality provided by Ant tasks be used in java programs?

Yes, and its quite easy. Before getting into the details, however, we should mention the pros and cons of this approach:

Pros

Robust Ant tasks are very robust. They have been banged on by many people. Ant tasks have been used in many different contexts, and have therefore been instrumented to take care of a great many boundary conditions and potentially obscure errors.
Cross Platform Ant tasks are cross platform. They have been tested on all of the volume platforms, and several rather unusual ones (Netware and OS/390, to name a few).
Community Support Using Ant tasks means you have less of your own code to support. Ant code is supported by the entire Apache Ant community.

Cons

Dependency on Ant Libraries Obviously, if you use an Ant task in your code, you will have to add "ant.jar" to your path. Of course, you could use a code optimizer to remove the unnecessary classes, but you will still probably require a chunk of the Ant core.
Loss of Flexibility At some point, if you find yourself having to modify the Ant code, it probably makes more sense to "roll your own." Of course, you can still steal some code snippets and good ideas. This is the beauty of open source!

Example

Let's say you want to unzip a zip file programmatically from java into a certain directory. Of course you could write your own routine to do this, but why not use the Ant task that has already been written?

In my example, I wanted to be able to unzip a file from within an XSLT Transformation. XSLT Transformers can be extended by plugging in static methods in java. I therefore need a function something like this:

/**
 * Unzip a zip file into a given directory.
 *
 * @param zipFilepath A pathname representing a local zip file
 * @param destinationDir where to unzip the archive to
 */
 static public void unzip(String zipFilepath, String destinationDir)

The Ant task to perform this function is org.apache.tools.ant.taskdefs.Expand. All we have to do is create a dummy Ant Project and Target, set the Task parameters that would normally be set in a buildfile, and call execute().

First, let's make sure we have the proper includes:

import org.apache.tools.ant.Project;
import org.apache.tools.ant.Target;
import org.apache.tools.ant.taskdefs.Expand;
import java.io.File;

The function call is actually quite simple:

static public void unzip(String zipFilepath, String destinationDir) {

    final class Expander extends Expand {
        public Expander() {
 	    project = new Project();
	    project.init();
	    taskType = "unzip";
	    taskName = "unzip";
	    target = new Target();
	}	
    }
    Expander expander = new Expander();
    expander.setSrc(new File(zipfile));
    expander.setDest(new File(destdir));
    expander.execute();

In actual practice, you will probably want to add your own error handling code and you may not want to use a local inner class. However, the point of the example is to show how an Ant task can be called programmatically in relatively few lines of code.

The question you are probably asking yourself at this point is: How would I know which classes and methods have to be called in order to set up a dummy Project and Target? The answer is: you don't. Ultimately, you have to be willing to get your feet wet and read the source code. The above example is merely designed to whet your appetite and get you started. Go for it!