Using Commons Logging from Ant
April 23rd, 2008 by Alexander Ananiev
Here is a common problem with custom Ant tasks. A typical task is implemented using multiple classes, so classes that don't extend org.apache.tools.ant.Task class don't necessarily have to have a dependency on Ant APIs. For example, it is pretty easy to pass Ant properties in a hashtable instead of passing the entire project object. This makes the custom task's code more generic and reusable.
One little issue that still remains is logging. Ant users are accustomed to running Ant with -verbose option which tells Ant tasks to print more detailed information. Oftentimes, -verbose is the only way to debug a build.
Unfortunately, using Ant logging requires access to Project or Task objects. As a result, the dependency on Ant APIs permeates the code that otherwise could have remained generic.
My solution for this is to use a simple class that implements org.apache.commons.logging.Log interface so that we can use jakarta commons logging (JCL) APIs instead of using Ant logging directly.
The class is called AntCommonsLogger.
To initialize AntCommonsLogger, users can either invoke "antCommonsLoggerInit" task in the beginning of a project or call AntCommonsLogger.init( getProject()) somewhere in their custom task class. After that, AntCommonsLogger becomes the default logger so that any class can use the the familiar commons logging pattern without any changes:
private static Log logger = LogFactory.getLog(CustomTask.class.getName());
...
logger.info("message");
logger.debug("message");
logger.trace("message");
"info" messages (i.e. calls to logger.info()) display during normal Ant execution, "debug" messages display if "-verbose" was specified and "trace" messages display if "-debug" was specified. This is a bit counterintuitive but this is the best we could do given that Ant's "verbose" does not have a direct counterpart in JCL.
To begin using AntCommonsLogger, download myarch-antuil and add antCommonsLoggerInit task definition to your project, e.g.:
<taskdef resource="com/myarch/antutil/tasks.properties">
<classpath>
<pathelement path="${basedir}/myarch-antutil.jar"/>
<!-- lib.dir must contain commons-logging -->
<fileset dir="${lib.dir}" />
</classpath>
</taskdef>
You also need to add myarch-util.jar and commons-logging.jar to the classpath of your custom tasks.
Note that calling antCommonsLoggerInit makes AntCommonsLogger the default logger for this JVM instance. This means that all Java classes invoked by this Ant script (e.g., using "java" task) that use JCL, will use AntCommonsLogger instead of java.util logging or log4j. If this is not what you want, call AntCommonsLogger.init(getProject()) at the begging of your custom task and AntCommonsLogger.restorePreviousDefault() at the end.
Download myarch-antuil with AntCommonsLogger