We all know that Apache Ant is a popular Java build management system. But, in many cases Ant alone is not enough for extended build tasks and we have to install Ant extensions or plugins. For example, tasks like – “loop through all the files available in a directory”, can be done quite easily using Ant-Contrib extentions. For this, we have to download ant-contrib.jar to a directory, say /usr/share/ant-extensions/lib and create a task definition in the Ant project file.

<taskdef resource="net/sf/antcontrib/antlib.xml">
    <classpath>
        <pathelement location="/usr/share/ant-extensions/lib/ant-contrib.jar"/>
  </classpath>
</taskdef>

Complete Ant project file may look like:-

<project name="List files" default="list-files" basedir=".">
    <property name="ant-contrib-file" value="/usr/share/ant-extensions/lib/ant-contrib-1.0b3.jar"/>
    <property name="dir-to-list" value="/usr/share/libs"/>
 
    <target name="load-ant-contrib" description="Load ant-contrib Ant tasks">
        <taskdef resource="net/sf/antcontrib/antlib.xml">
            <classpath>
                <pathelement location="${ant-contrib-file}"/>
            </classpath>
        </taskdef>
        <property name="ant.contrib.loaded" value="true"/>
    </target>
 
    <target name="list-files" depends="load-ant-contrib" description="List jar files in a directory">
        <for param="file">
            <fileset dir="${dir-to-list}" includes="*.jar"/>
            <sequential>
                <echo message="@{file}"/>
            </sequential>
        </for>
    </target>
</project>

In the above example, we have to manually manage the dependencies and their versions. Well, there is a better solution using Apache Ivy dependency manager wherein Ivy can automatically download Ant dependencies from maven repository. We just have to specify the name of the dependency along with it’s version in the Ant project file.

Ivy module dependencies can be described in an xml file called ivy.xml. ivy.xml file contains the description of the dependencies of a module, its published artifacts and its configurations. Sample ivy.xml file with only ant-contrib dependency may look like:-

<ivy-module version="2.0">
    <info organisation="my-org" module="my-module1"/>
    <dependencies>
        <dependency org="ant-contrib" name="ant-contrib" rev="1.0b3"/>
  </dependencies>
</ivy-module>

We can also create this xml using echoxml Ant task:-

<echoxml file="ivy.xml">
    <ivy-module version="2.0">
        <info organisation="my-org" module="my-module1"/>
        <dependencies>
            <dependency org="ant-contrib" name="ant-contrib" rev="1.0b3"/>
        </dependencies>
    </ivy-module>
</echoxml>

We can specifiy multiple dependencies in ivy.xml and Ivy will make that dependencies available in the Ant task. The only jar file we have to include in the Ant task is ivy.jar, all other dependencies will be managed automatically by Ivy. We can also download ivy.jar dynamically using the Ant get Task:-

<get src="http://repo1.maven.org/maven2/org/apache/ivy/ivy/2.4.0/ivy-2.4.0.jar"
     dest="${user.home}/.ivy2/jars"
     usetimestamp="true"/>

At this point Ivy module dependencies has been configured. Ivy provides retrieve task, which then reads from ivy.xml and copies resolved dependencies in configurable file system location. Configure artifactproperty followed by retrieve task which then sets loaded dependency in Ant property, which will be required to load dependencies using taskdef Ant task. retrieve and artifactproperty task can be configured as:-

<ivy:retrieve/>
<ivy:artifactproperty name="[module].[artifact]" value="lib/[artifact]-[revision].[ext]"/>

The ant-contrib jar file will be loaded in Ant property ant-contrib.ant-contrib. Ivy not needed after this, now you can just load ant-contrib task using taskdef Ant task like this:-

<taskdef resource="net/sf/antcontrib/antlib.xml">
    <classpath>
        <pathelement location="${ant-contrib.ant-contrib}"/>
    </classpath>
</taskdef>

With all the above things tied in together, the complete Ant(v1.9.4) project file looks like:-

<project name="Ivy dependency example" default="list-files" basedir="." xmlns:ivy="antlib:org.apache.ivy.ant">
    <property name="ivy.install.version" value="2.4.0"/>
    <property name="ivy.jar.dir" location="${user.home}/.ivy2/jars"/>
    <property name="ivy.jar.file" location="${ivy.jar.dir}/ivy-${ivy.install.version}.jar"/>
    <property name="dir-to-list" value="/usr/share/libs"/>
 
    <target name="download-ivy" unless="ivy.downloaded" description="Download Ivy jar files">
        <mkdir dir="${ivy.jar.dir}"/>
        <get src="http://repo1.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar"
             dest="${ivy.jar.file}"
             usetimestamp="true"/>
    </target>
 
    <target name="check-ivy-downloaded" description="Check if Ivy is already downloaded">
        <condition property="ivy.downloaded">
            <and>
                <available file="${ivy.jar.file}"/>
            </and>
        </condition>
    </target>
 
    <target name="load-ivy" depends="check-ivy-downloaded,download-ivy" unless="ivy.loaded" description="Load Ivy Ant tasks">
        <path id="ivy.lib.path">
            <fileset dir="${ivy.jar.dir}" includes="*.jar"/>
        </path>
        <taskdef resource="org/apache/ivy/ant/antlib.xml" uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>
                <echoxml file="ivy.xml">
                        <ivy-module version="2.0">
                                <info organisation="my-org" module="my-module1"/>
                                <dependencies>
                                        <dependency org="ant-contrib" name="ant-contrib" rev="1.0b3" transitive="false"/>
                                </dependencies>
                        </ivy-module>
                </echoxml>
        <property name="ivy.loaded" value="true"/>
    </target>
 
    <target name="retrieve" depends="load-ivy" description="Retrieve dependencies">
        <ivy:retrieve/>
        <ivy:artifactproperty name="[module].[artifact]" value="lib/[artifact]-[revision].[ext]"/>
    </target>
 
    <target name="load-ant-contrib" depends="retrieve" unless="ant.contrib.loaded" description="Load ant-contrib Ant tasks">
        <taskdef resource="net/sf/antcontrib/antlib.xml">
            <classpath>
                <pathelement location="${ant-contrib.ant-contrib}"/>
            </classpath>
        </taskdef>
        <property name="ant.contrib.loaded" value="true"/>
    </target>
 
    <target name="list-files" depends="load-ant-contrib" description="List jar files in a directory">
        <for param="file">
            <fileset dir="${dir-to-list}" includes="*.jar"/>
            <sequential>
                <echo message="@{file}"/>
            </sequential>
        </for>
    </target>
</project>
No votes yet.
Please wait...