How to turn a list of jar files into an Ant classpath string

Summary: This tutorial shows how to use a list of jar files in a lib directory to create a dynamic classpath you can write to a manifest file using an Ant build script.

In this tutorial I'd like to demonstrate how to convert a list of jar files in a standard lib directory into a classpath string you can use to define a manifest file in an Ant build script. By converting this list of jar files into a classpath string, the build process for your jar file can depend on any number of external jar files, and you can create this classpath dynamically.

Jar files in my lib directory

In my case, the Java application I was building depended on the following jar files, which were in the lib directory of my project:

commons-collections.jar
commons-dbcp-1.1.jar
commons-pool-1.1.jar
log4j-1.2.8.jar

Ant tasks to build the dynamic classpath

My ant script contains several sections that deal with this classpath issue. The first thing I do is create a classpath variable named build.classpath that contains a list of all the *.jar files in my lib directory, like this:

<path id="build.classpath">
  <fileset dir="lib">
    <include name="**/*.jar" />
  </fileset>
</path>

Next, I convert that build.classpath list into a space-separated string (named mf.classpath) using an Ant task named pathconvert, and a mapper named flattenmapper. This is shown in the next section of my Ant build script:

<!-- convert classpath to a flat list/string for use in manifest task -->
<pathconvert property="mf.classpath" pathsep=" ">
    <path refid="build.class.path" />
    <flattenmapper />
</pathconvert>

The net effect of these two sections of code is turning this list of jar files in my lib directory

commons-collections.jar
commons-dbcp-1.1.jar
commons-pool-1.1.jar
log4j-1.2.8.jar

into a space-separated string like this

commons-collections.jar commons-dbcp-1.1.jar commons-pool-1.1.jar log4j-1.2.8.jar

Building the manifest and the jar

In the final two steps of the process I first build a manifest file (MANIFEST.MF), using the mf.classpath variable, like this:

<tstamp/><!-- needed for TODAY -->
<manifest file="MANIFEST.MF">
  <attribute name="Built-By" value="${manifest.built.by}"/>
  <attribute name="Created-By" value="${manifest.created.by}"/>
  <attribute name="Main-Class" value="${manifest.main.class}"/>
  <attribute name="Implementation-Version" value="${version.number}-b${build.number}"/>   
  <attribute name="Built-Date" value="${TODAY}"/>
  <attribute name="Class-Path" value="${mf.classpath}" />
</manifest>

And then I use that manifest file to build my jar file, like this:

<!-- create the jar file, including the manifest file we just created -->
<jar basedir="${dest.dir.classes}" 
     destfile="${package.file}"
     includes="**/*.*"
     excludes="**/*Test*"
     manifest="MANIFEST.MF" />

Hopefully all of this makes sense. It's fairly complicated, but I've tried to break it down here to just the essential steps of the build process.