How to include ant-contrib.jar dynamically in Ant

Thomas Pujolle picture Thomas Pujolle · Oct 15, 2012 · Viewed 13.5k times · Source

I'm looking for a way to include a .jar from within an Ant file so I can use it straight away and call its methods in my targets. In my case it's ant-contrib-1.0b3.jar.

Answer

David W. picture David W. · Oct 15, 2012

The best way is to put the Ant-Contrib jarfile inside you project. For example, let's say the build.xml is in the root of your project. Create a directory called ant.lib\ant-contrib inside your project, then put the ant-contrib*.jar in this folder. You can use this method for other optional Ant tasks that you might need (for example, Ivy, Findbugs, Cobrrtura, etc).

Then, in your build.xml file, you can do this:

<taskdef resource="net/sf/antcontrib/antlib.xml">
     <classpath>
         <fileset dir="${basedir}/ant.lib/ant-contrib"/>
     </classpath>
</taskdef>

I like doing it this way because the optional jars with the tasks are included with the project. If you check everything into your version control system, someone can checkout your code, and do the build without downloading Ant-Contrib and installing it themselves.

You can define an XML namespaces. This gives your Ant-Contrib tasks a prefix in order to avoid task name collisions in case you use other optional ant tasks that have the same task name. Plus, it alerts users that this is not a standard Ant task.

If you use an XML namespace, you need to put a XMLNS declaration in your <project> heading. This will contain a URI that will connect your Ant Contrib tasks to your XML namespace. For example, the ac: namespace is for all Ant Contrib tasks:

<project name="my.project" default="package" basedir="."
    xmlns:ac="http://ant-contrib.sourceforge.net">

 <taskdef resource="net/sf/antcontrib/antlib.xml"
      uri="http://ant-contrib.sourceforge.net">
     <classpath>
         <fileset dir="${basedir}/ant.lib/ant-contrib"/>
     </classpath>
</taskdef>

What this does is match the XML namespace (xmlns) of ac with the URI http://ant-contrib.sourceforge.net. The URI could be anything. For example:

<project name="my.project" default="package" basedir="."
    xmlns:ac="hamburger:with-fries">

 <taskdef resource="net/sf/antcontrib/antlib.xml"
      uri="hamburger:with-fries">
     <classpath>
         <fileset dir="${basedir}/ant.lib/ant-contrib"/>
     </classpath>
</taskdef>

The standard is to use something like antlib:net.sf.antcontrib:

<project name="my.project" default="package" basedir="."
    xmlns:ac="antlib:net.sf.antcontrib">

 <taskdef resource="net/sf/antcontrib/antlib.xml"
      uri="antlib:net.sf.antcontrib">
     <classpath>
         <fileset dir="${basedir}/ant.lib/ant-contrib"/>
     </classpath>
</taskdef>

However, I like using the URL of the project. That way, if someone wants documentation on Ant-Contrib tasks, they know the URL where the Ant-Contrib project lives.

In all three cases above, I've defined the XML namespace with ac. Thus, you have to prefix all Ant-Contrib task names with ac:. You could use antcontrib or whatever you like. With the ac: namespace, your Ant-contrib tasks will look like this:

<ac:if>
   <istrue value="${include.debug.code}"/>
   <ac:then>
        [...]
   </ac:then>
   <ac:else>
        [...]
   </ac:else>
<ac:if>

If you skip the whole namespace thing, you can simply use the Ant-Contrib tasks as documented:

<if>
   <istrue value="${include.debug.code}"/>
   <then>
        [...]
   </then>
   <else>
        [...]
   </else>