BUY THIS BOOK
Add to Cart

Print Book $34.95


Add to Cart

Print+PDF $45.44

Add to Cart

PDF $27.99

Safari Books Online

What is this?

Add to UK Cart

Print Book £24.95

What is this?

Looking to Reprint or License this content?


Ant: The Definitive Guide
Ant: The Definitive Guide, Second Edition By Steve Holzner
April 2005
Pages: 334

Cover | Table of Contents | Colophon


Table of Contents

Chapter 1: Getting Started
Build tools are one of the most boring items developers must have available in their development cycle. They aren't sexy, they aren't going to impress your friends, and you'll hardly notice a build tool at all until it's time to redeploy that 1,000-class Java application you've been working on. Then, all the interesting code, killer IDEs, and amazing design patterns aren't worth nearly as much as typing ant and calmly watching your boring build tool handle complicated dependencies, deployment onto multiple servers via FTP and SSH, and log errors. It is here that build tools like Ant truly shine.
At its most basic, all a good build tool does is take source code, compile it, and create a working application. When you're writing a single-class application, this isn't a big deal; in fact, it can be annoying to manage a build system instead of typing javac. But it's a different story when you start working with multiple source files, with multiple dependencies, need to check code out of a central repository automatically, test the code, and deploy it to some remote destination. You can end up with dozens of tasks to complete each time you want to build your application, which is the last thing you want to spend time on when you're already brain-dead from an all-night debugging session. When new members join your team, you'll have to walk through this whole process again, showing them the ropes and hoping they don't break anything in the process. It's for all of these reasons that developers—and especially Java programmers—turn to Ant.
Though there are still powerful alternatives to Ant like make, Jam, Cons, gnumake, and nmake, nothing is as integrated into the Java programming language. Ant is pure Java; you'll find line after line of Java code and .java files if you obtain a source release of the tool. Further, some of the most popular projects in the Java universe are built using Ant; everything from Tomcat to JBoss to Turbine can go from source to binary by typing ant.
Ant was originally the brainchild of James Duncan Davidson, and the word Ant stands for "Another Neat Tool," a fact that relatively few developers realize. Ant 1.0 first appeared in March 2000. James' original inspiration was to create a build tool that used a simple XML-based format for build files, as opposed to the shell commands and involved formatting that
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Ant's Origins
Ant was originally the brainchild of James Duncan Davidson, and the word Ant stands for "Another Neat Tool," a fact that relatively few developers realize. Ant 1.0 first appeared in March 2000. James' original inspiration was to create a build tool that used a simple XML-based format for build files, as opposed to the shell commands and involved formatting that Makefiles used. Ant caught on rapidly, and newer versions followedAnt 1.1 (July 2000), 1.2 (October 2000), 1.3 (March 2001), 1.4 (September 2001), and 1.5 (July 2003). The version this book uses—version 1.6.1—appeared in February of 2004. Although James Davidson has moved on to work with other build tools, Ant continues to evolve on an almost daily basis.
Ant is an open source, Apache community project, and its home page is at http://ant.apache.org. Because it's an open source project, it's always developing. There are multiple authors, called committers, which can write to Ant's source code repositories. However, officially sanctioned Ant versions don't appear too rapidly, and when they do, they're usually backward compatible enough to make sure your build files aren't broken.
One notable exception to this practice is Ant 2.0, which may be out sometime in the next year or so. When it does come out, the Apache Ant team plans on releasing an automated migration tool that will translate 1.x build files to Ant 2.0.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Getting Ant
Ant comes in two editions: binary and source. The binary release is ready to use: just download, uncompress, and go. The source release allows you to see what makes Ant run and to make modifications of your own if you choose. To download either, go to http://ant.apache.org/ and click a link under the Download title (either Binary Distributions or Source Distributions).
Downloading a binary edition is easiest: Just click the Binary Distributions link and download the .tar.gz or .zip compressed file.
If you want bleeding-edge Ant, you can get the nightly builds from http://cvs.apache.org/builds/ant/nightly/.
To install the binary distribution of Ant, expand it. Here's the resulting directory layout (only the bin and lib directories are needed to run Ant):
  ant
   |___ bin  Ant launch scripts
   |
   |___ lib  Ant jars 
   |
   |___ docs Ant documentation
   |
   |___ etc  XSL for formatting Ant XML output
You need to perform the following steps to complete the setup process:
  1. Add the Ant bin directory to your path.
  2. Set the ANT_HOME environment variable to the directory where you installed Ant.
    On some operating systems, the Ant scripts can guess ANT_HOMEspecifically in Unix and Windows NT/2000but it's better not to rely on them doing so accurately.
  3. Set the JAVA_HOME environment variable to the directory where your JDK is installed.
If you've expanded Ant in c:\ant on Windows, you'll end up with a new directory, c:\ant\apache-ant-1.6.1. If you've installed the JDK in c:\jdk1.4 (and the Java bin directory is
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Ant at Work
Rather than go on and on about what Ant can do for you, an example can illustrate how easy Ant makes the build process. Assume that you have a Java file called Project.java, as shown in Example 1-1.
Example 1-1. A simple Java class
public class Project 
{
    public static void main(String args[]) 
    {
        System.out.println("No worries.");    
    }
}
Assume you want to compile this code and store the results, Project.class, in a JAR file, Project.jar. With Ant and a build file, this is a piece of cake. By default, Ant looks for a build file named build.xml. That file is a valid XML document; Example 1-2 shows the build file for this example.
Example 1-2. A simple Ant build file
<?xml version="1.0" ?>
<project default="main">

    <target name="main" depends="compile, compress">
        <echo>
            Building the .jar file.
        </echo>
    </target>
  
    <target name="compile">
        <javac srcdir="."/>
    </target>
  
  <target name="compress">
        <jar jarfile="Project.jar" basedir="." includes="*.class" />
  </target>

</project>
To run this Ant build file, make sure it's in the same directory as Project.java, and enter ant at the command-line prompt. Ant has been tested on many platforms, including Linux; Unix versions from Solaris to HP-UX; Windows 9x, NT, 2000, and XP; OS/2 Warp, Novell Netware 6, and MacOS X.
When you run Ant on this first build file, here's what you'd see in Unix (using the bash shell):
-bash-2.05b$ ant
Buildfile: build.xml

compile:
    [javac] Compiling 1 source file

compress:
      [jar] Building jar: /home/httpd/vhosts/builder/Project.jar

main:
     [echo] 
     [echo]             Building the .jar file.
     [echo]         

BUILD SUCCESSFUL
Total time: 2 seconds
You'll get the same results in any supported operating system. For example, here's what you'd see in Windowsverything except the build time is identical:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Anatomy of a Build File
Ant projects all revolve around one or more build files. By default, Ant looks for a build file named build.xml. Because Ant files are XML documents, they start with an XML declaration, as all valid XML documents must:
<?xml version="1.0" ?>
        .
        .
        .
For the complete XML 1.0 syntax, look at http://www.w3.org/TR/REC-xml/. XML 1.1 is out now as well, but Ant build files are based on XML 1.0, and the difference between these versions is small anyway, centering mostly on the manner in which certain Unicode characters are supported.
Every Ant build file contains exactly one project. You set up an Ant project in a build file with the project element, which is the document element—i.e., the element that contains all other elements:
<?xml version="1.0" ?>
<project>
        .
        .
        .
</project>
            
As Ant build files are just XML, you'll need to know which attributes are allowed on the top-level project element.
You'll also want to know about the elements that can be nested within project. Those are dealt with throughout the rest of this chapter and in Chapter 2.
The three allowed attributes for the project element are shown in Table 1-1.
Table 1-1: The project element's supported attributes
Attribute
Description
Required
name
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Running Ant
Running Ant from the command-line is simple:
%ant [options] [target [target2 [target3] ...]]
options are one or more of the command-line options that begin with a hyphen, listed in Table 1-14; target, target2, etc., are the specific targets you want to run in the event you don't want to defer to the project element's default target.
Entering ant -help on the command line generates a list of command-line options.
Table 1-14: Ant command-line options
Name
Description
-buildfile file, or -f file, or -file file
Runs the build file specified by file.
-Dproperty=value
                           
Sets a property called property with a value of value, and passes it to Ant.
-debug, -d
Prints debugging information.
-diagnostics
Prints diagnostics about Ant.
-emacs, -e
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 2: Using Properties and Types
In Chapter 1, you learned about properties and tasks in Ant. However, long tables with short descriptions do not an Ant expert make. In this chapter, you begin to get the details on using Ant's extensive feature set, which relies on two conerstones: properties and types. You received an introduction to them in the previous chapter, but here's where to get a real working knowledge.
In the examples from last chapter, building was a linear process: you compiled some files, you JARred them up, and then you were done. In the real world, things are almost never so straightforward. You need to be able to check for specific files and perform different tasks depending on the existence of those files. You need to respond to error conditions, and let the user know what has happened when errors do occur. You often need to deal with groups of files, copy them over en masse, and more. These kinds of tasks involve using properties and types.
Ant provides extensive support for controlling the build process; though Ant is not a programming language, it has a number of control structures, and those control structures rely on properties. As if and try/catch allow you to handle several logic paths in Java, Ant's control tasks allow you the same flexibility within the context of a build process.
The foundation to any type of control processing is some form of the if statement. This typically involves two steps:
  1. Check or determine if a certain condition is true.
  2. If the condition is true, perform one action; if it is false, perform another.
In Java, this all happens in a single line of code; in Ant, the condition must be set in one step, and the evaluation of that condition occurs in another step. First, you need to set a condition based on some criteria; not surprisingly,
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Using Properties to Control Tasks
Ant provides extensive support for controlling the build process; though Ant is not a programming language, it has a number of control structures, and those control structures rely on properties. As if and try/catch allow you to handle several logic paths in Java, Ant's control tasks allow you the same flexibility within the context of a build process.
The foundation to any type of control processing is some form of the if statement. This typically involves two steps:
  1. Check or determine if a certain condition is true.
  2. If the condition is true, perform one action; if it is false, perform another.
In Java, this all happens in a single line of code; in Ant, the condition must be set in one step, and the evaluation of that condition occurs in another step. First, you need to set a condition based on some criteria; not surprisingly, condition is the name of the task Ant provides. condition allows you to specify one or more true/false tests (sometimes called criteria). If all the criteria evaluate to true, a property, supplied to the condition task, is set to true; if one or more of the criteria evaluate to false, the property is assigned a false value. You can check that property's value later in the build file.
In this example, the build file checks to see if two files exist using the available task (covered later in the chapter) and sets the property all.set (to true) if the files are found:
  <condition property="all.set">
    <and>
      <available file="file1.java"/>
      <available file="file2.java"/>
    </and>
  </condition>
Here's another example where the build file checks to see if it's running on Mac OS but not Mac OS X, which Ant treats as part of the Unix family:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Using Property Files
In larger build files, you might be working with dozens of properties, and storing them in property files is common. Setting tens, or hundreds, of properties all within a build file is a bad habit to get into and almost impossible to maintain.
Using property files means that you can quickly tailor a build file to different sets of circumstances by swapping property files. And you can store property values; though we've been using mostly true/false properties to make conditional processing easier, they can hold all kinds of textual data, such as copyright notices and legal information, in a central repository everyone can share.
You can specify a property file to use on the command line with the -propertyfile option.
Take a look at Example 2-2, which uses a property file to hold a property named message. This example points to the property file with the property task's file attribute, which can hold the fully qualified name of the file. You can use the property task's url attribute to point to a property file.
Example 2-2. Using a property file (ch02/properties/build.xml)
<?xml version="1.0" ?>
<project default="main">

    <property file="build.properties" />
    <property name="src" location="source" />
    <property name="output" location="bin" />

    <target name="main" depends="init, compile, compress">
        <echo>
            ${message}
        </echo>
    </target>
  
    <target name="init">
        <mkdir dir="${output}" />
    </target>
  
    <target name="compile">
        <javac srcdir="${src}" destdir="${output}" />
    </target>
  
  <target name="compress">
        <jar destfile="${output}/Project.jar" basedir="${output}" includes="*.class" />
  </target>
</project>
Here are the entire contents of another sample file, build.properties, which uses a name =
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Handling Data Using Types
Ant supports a number of types, and the rest of this chapter is devoted to understanding them and how to work with them. These types work much like data types in programming languages, and as you're going to see, types and properties are intertwined. The data structures you create using types can be assigned to properties, and the data you use to set up those data structures is often stored in properties. Now that you've got properties under your belt, it's time to move on to types.
Much of what a build tool like Ant does is work with files in directory structures, so you might expect that many of the Ant types have to do with handling files and directories. You can see the available Ant core (that is, built-in) types in Table 2-7.
Table 2-7: Core Ant types
Type
Description
Assertions
Enables, or disables, Java 1.4 assertions
Description
Holds a description of the project that can be viewed if you use the Ant -projecthelp command
DirSet
Contains a group of directories
FileList
Contains a named list of files
FileSet
Contains a groups of files
File mappers
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 3: Building Java Code
Ant is the premiere build tool for Java developers, and this chapter focuses on the Java build process, from compiling Java code with the javac task through compressing and packaging the results with tasks such as jar and tar. Along the way, I'll discuss several central build issues, such as keeping track of the build number, storing that number in a JAR file's manifest file, getting input from the user and acting on that input, calling one Ant target from another, creating Javadoc with the javadoc task, and more.
The javac task compiles Java source code. You've seen javac at work many times in this book but haven't exhausted what this task has to offer by any means. You can get an idea how extensive a task it is by its huge number of attributes, shown in Table 3-1.
Table 3-1: The javac task's attributes
Attribute
Description
Required
Default
bootclasspath
Specifies where to find any bootstrap class files.
No
bootclasspathref
Specifies where to find any bootstrap class files, given as a reference.
No
classpath
Specifies the classpath you want to use.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Compiling Code
The javac task compiles Java source code. You've seen javac at work many times in this book but haven't exhausted what this task has to offer by any means. You can get an idea how extensive a task it is by its huge number of attributes, shown in Table 3-1.
Table 3-1: The javac task's attributes
Attribute
Description
Required
Default
bootclasspath
Specifies where to find any bootstrap class files.
No
bootclasspathref
Specifies where to find any bootstrap class files, given as a reference.
No
classpath
Specifies the classpath you want to use.
No
classpathref
Specifies the classpath you want to use, given as a reference to a path.
No
compiler
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Getting Input from the User
At some point in a build, you may need input from the user. For example, you might want to ask before deleting a directory with the delete task.
The delete task is covered in detail in Chapter 4.
To get input from the user, use the input task, which creates a new property based on user input.
Example 3-1 puts input to work. This build file asks whether it's OK to delete the bin directory, and if it's not, the build fails. It queries the user using the input task, and creates a new property, do.delete, based on the user's input.
Example 3-1. Using the input task (ch03/input/build.xml)
<?xml version="1.0" ?>
<project default="main">

    <property name="message" value="Building the .jar file." />
    <property name="src" location="source" />
    <property name="output" location="bin" />

    <target name="main" depends="init, compile, compress">
        <echo>
            ${message}
        </echo>
    </target>
  
    <target name="init">
        <input
            message="Deleting bin directory OK?"
            validargs="y,n"
            addproperty="do.delete"
        />
        <condition property="do.abort">
            <equals arg1="n" arg2="${do.delete}"/>
        </condition>
        <fail if="do.abort">Build aborted.</fail>
        <delete dir="${output}" />
        <mkdir dir="${output}" />
    </target>
  
    <target name="compile">
        <javac srcdir="${src}" destdir="${output}" />
    </target>
  
  <target name="compress">
        <jar destfile="${output}/Project.jar" basedir="${output}" includes="*.class" />
  </target>
</project>
Here's what you see when you run Ant using this build file:
%ant
Buildfile: build.xml

init:
    [input] Deleting bin directory OK?(y,n)
            y
    [delete] Deleting directory /home/steven/input/bin
    [mkdir] Created dir: /home/steven/input/bin

compile:
    [javac] Compiling 1 source file to /home/steven/input/bin

compress:
    [jar] Building jar: /home/steven/input/bin/Project.jar

main:
    [echo]
    [echo]             Building the .jar file.
    [echo]

BUILD SUCCESSFUL
Total time: 5 seconds
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Calling Other Ant Tasks
You've seen that you can branch using true/false properties. Ant provides other powerful mechanisms for branchingthe antcall task, which you can use to call one Ant task from another, and the ant task, which calls Ant tasks in other build files.
A better way to think of antcall is that you're starting a new instance of Ant and executing targets in it. When you call an Ant target with antcall, its dependent targets are executed in order, something that can be confusing if you think you're calling a single target. Generally, it's best to do things the standard way and let Ant sort out the dependencies as it's supposed to. However, Ant can make life easier, as when you have a build file that creates a distribution for many different servers, and when varying sets of tasks need to be executed for each. (Even in cases like that, however, you can still set things up easily enough with if and unless and true/false properties.)
When you use antcall, you can think of that call as creating a new project; all the properties of the current project are available in that new project by default. The attributes of the antcall task appear in Table 3-4.
Table 3-4: The antcall attributes
Attribute
Description
Required
Default
inheritAll
If true, means the task should pass all current properties to the new Ant project. Properties passed to the new project will override the properties that are set in the new project.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Importing Other Build Files
With ant, you can execute build files outside the current build file, and you can include other build files in the current file. The old way of doing this was to rely on XML and the Ant XML parser to do the work for you. For example, if you wanted to include the entire contents of a document named shared.xml at a specific point in a build file, you could start by declaring an XML entity named, say, shared in your build file:
<?xml version="1.0"?>

<!DOCTYPE project [
            <!ENTITY shared SYSTEM "file:shared.xml">
            ]>
        .
        .
        .
To insert the contents of the shared.xml build file into the current build file, you can use an XML entity reference, &shared;, like this:
<?xml version="1.0"?>

<!DOCTYPE project [
    <!ENTITY shared SYSTEM "file:shared.xml">
]>

<project default="main" basedir=".">

    &shared;

    <target name="init">
        .
        .
        .
    </target>
        .
        .
        .
</project>
Since Ant 1.6, however, there is a new import task that can be used to include build files. The referenced files have to be complete Ant build files, which are inserted whole (minus the XML declaration and <project> and </project> tags). Here's how the above example would work using the import task:
<?xml version="1.0"?>
<project default="main" basedir=".">

  <import file="shared.xml"/>

    <target name="init">
        .
        .
        .
    </target>
        .
        .
        .
</project>
The attributes of the import task appear in Table 3-8.
Table 3-8: The import task's attributes
Attribute
Description
Required
Default
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Documenting Code
Creating applications in a commercial environment frequently means creating documentation, and Ant is up for that with the javadoc task. This task creates documentation using the Java javadoc tool, a process that involves compilation, which merits including this task in this chapter. This is one of the largest tasks in Ant because of the enormous number of javadoc options.
Here's an example, stored in the javadoc folder in the code for this book. Suppose you add a documentation-type comment to the Project.java file:
            /** This application prints out "No worries." */
public class Project 
{
    public static void main(String args[]) 
    {
        System.out.println("No worries.");    
    }
}
You can create Javadoc for the project using the javadoc task in a new target I'll name doc, which will put the generated Javadoc in a doc directory, as you see in Example 3-3.
Note the XML <![CDATA[...]> sections, which the build file uses to pass data to the javadoc tool.
Example 3-3. Creating javadoc (ch03/javadoc/build.xml)
<?xml version="1.0" ?>
<project default="main">

    <property name="message" value="Building the .jar file." />
    <property name="src" location="source" />
    <property name="docs" location="docs" />
    <property name="output" location="bin" />

    <target name="main" depends="init, compile, doc, compress">
        <echo>
            ${message}
        </echo>
    </target>
  
    <target name="init">
        <mkdir dir="${output}" />
        <mkdir dir="${docs}" />
    </target>
  
    <target name="compile">
        <javac srcdir="${src}" destdir="${output}" />
    </target>

    <target name="doc">
        <javadoc 
            sourcefiles="${src}/Project.java"
            destdir="${docs}"
            author="true"
            version="true"
            use="true"
            windowtitle="Project API">
            <doctitle><![CDATA[<h1>Project API</h1>]]></doctitle>
            <bottom><![CDATA[<i>Copyright &#169; 2005</i>]]></bottom>
        </javadoc>
    </target>

    <target name="compress">
        <jar destfile="${output}/Project.jar" basedir="${output}" includes="*.class" />
    </target>

</project>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Creating JAR Files
The jar task JARs files for you. Example 3-4 is a fairly complex example, which creates a new JAR file with an included manifest, MANIFEST.MF, that contains several attributes.
Example 3-4. Using the jar task (ch03/jar/build.xml)
<?xml version="1.0" ?>
<project default="main">

    <property name="message" value="Building the .jar file." />
    <property name="src" location="source" />
    <property name="output" location="bin" />

    <target name="main" depends="init, compile, compress">
        <echo>
            ${message}
        </echo>
    </target>
  
    <target name="init">
        <mkdir dir="${output}" />
    </target>
  
    <target name="compile">
        <javac srcdir="${src}" destdir="${output}" />
    </target>
  
    <target name="compress">
        <jar destfile="${output}/Project.jar" basedir="${output}" 
            includes="*.class" >
            <manifest>
                <attribute name="Author" value="${user.name}"/>
                <section name="Shared">
                    <attribute name="Title" value="Example"/>
                    <attribute name="Vendor" value="MegaAntCo"/>
                </section>
                <section name="Copyright">
                    <attribute name="Copy" value="(C) MegaAntCo 2005"/>
                </section>
            </manifest>
        </jar>
    </target>
</project>
The created JAR file contains Project.class and MANIFEST.MF; this latter file contains these contents:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.6.1
Created-By: 1.4.2_03-b02 (Sun Microsystems Inc.)
Author: Steven Holzner

Name: Shared
Title: Example
Vendor: MegaAntCo

Name: Copyright
Copy: (C) MegaAntCo 2005
Want to sign your JAR file for distribution? Use the jarsign task like this:
<signjar jar="jarfile.jar" alias="development"
          keystore="local.keystore" 
          storepass="secret"/>
The attributes of the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Setting Build Numbers
Anyone who has released software commercially knows how important it is to keep track of build numbers. The first version of your software might be 1.0.0, an update might be 1.0.1, a major update might be 2.0.0, and so on. The buildnumber task is a basic task that can be used to track these kinds of build numbers.
This task will first attempt to read a build number from a file (by default, build.number in the current directory) and set the property build.number to the value that was read in (or to 0, if no value was read). It will increment the number by one and write the new value back to the file.
This task has only one attribute, file, which holds the name in which you want to store the build number. This attribute is not required. I'll take a look at an example using buildnumber after discussing time stamps, the next topic.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Setting Timestamps
The tstamp task sets properties holding the current time so you can time stamp your builds. This task creates the DSTAMP (day stamp), TSTAMP (time stamp) and TODAY properties in the current project. By default, the DSTAMP property is in the format "yyyyMMdd", TSTAMP is in the format "hhmm", and TODAY is in the format "MMMM dd yyyy". If you use this task, it's almost invariably run in an initialization target.
You can see how this works in Example 3-5, which stores the build number and creation date in the project's .jar file, using buildnumber and tstamp.
Example 3-5. Using the build number and tstamp tasks (ch03/buildnumber/build.xml)
<?xml version="1.0" ?>
<project default="main">

    <property name="message" value="Building the .jar file." />
    <property name="src" location="source" />
    <property name="output" location="bin" />

    <target name="main" depends="init, compile, compress">
        <echo>
            ${message}
        </echo>
    </target>
  
    <target name="init">
        <buildnumber/>
        <tstamp/>
        <delete dir="${output}"/>
        <mkdir dir="${output}" />
    </target>
  
    <target name="compile">
        <javac srcdir="${src}" destdir="${output}" />
    </target>
  
  <target name="compress">
        <jar destfile="${output}/Project.jar" basedir="${output}" 
            includes="*.class" >
            <manifest>
            <attribute name="Author" value="${user.name}"/>
            <section name="Shared">
                <attribute name="Title" value="Example"/>
                <attribute name="Vendor" value="MegaAntCo"/>
                <attribute name="Build" value="${build.number}"/>
                <attribute name="Date" value="${TODAY}"/>
            </section>
            <section name="Copyright">
                <attribute name="Copy" value="(C) MegaAntCo 2005"/>
            </section>
        </manifest>
     </jar>
  </target>
</project>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 4: Deploying Builds
This chapter starts coverage of one of the things Ant does best: deployment. This chapter covers tasks to package applications for deployment like tar, gzip, and zip; tasks to prepare directories for deployment like delete and mkdir; and tasks to deploy applications like copy and move for local and network deployment, as well as ftp, telent, sshexec, and mail for remote deployment. You'll see other deployment-related tasks, such as touch to set the deployed files' modification dates to a specific value (as is done for commercial software deployments), fixcrlf to fix text file line endings (as in readme, .sh, .bat, .html, or .ini files) for different platforms, and more. Finally, you'll learn how to handle build automation, setting up builds to run on their own, at a schedule of your choosing.
There's more on deployment coming up in this book. Ant has a lot of support for deploying web applications, so much so that it'll take more than just this chapter to cover. Chapter 8 covers how to package and deploy web applications, including using get (used to send administrative commands to web servers remotely), serverdeploy, war, and other Ant tasks designed to load web applications to various servers. Chapter 8 and part of Chapter 9 also specifically discuss how to deploy to Enterprise JavaBean© (EJB) application servers.
We're going to start with deployment tasks designed to package applications for deployment: tar, gzip, and zip. These are not the only way to package applications; the jar task was covered in Chapter 3 on Java Development, and the war task, a special form of the jar task for Web applications that makes allowances for files like the deployment descriptor web.xml, will be covered in Chapter 8.
The tar task creates a TAR archive, handy for archiving files for distribution. This task is directory-based and, like other such tasks, forms an implicit FileSet that defines which files—relative to the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Packaging Applications for Deployment
We're going to start with deployment tasks designed to package applications for deployment: tar, gzip, and zip. These are not the only way to package applications; the jar task was covered in Chapter 3 on Java Development, and the war task, a special form of the jar task for Web applications that makes allowances for files like the deployment descriptor web.xml, will be covered in Chapter 8.
The tar task creates a TAR archive, handy for archiving files for distribution. This task is directory-based and, like other such tasks, forms an implicit FileSet that defines which files—relative to the basedir attribute setting—will be included in the archive.
If you set the compression attribute to gzip or bzip2, you can compress the output .tar file to the specified format. For instance, Example 4-1 compiles code and places the resulting Project.class file in a .tar.gz file, Project.tar.gz, by setting the compression attribute to gzip.
Example 4-1. Tarring a file (ch04/tar/build.xml)
<?xml version="1.0" ?>
<project default="main">

    <property name="message" value="Building the .tar.gz file." />
    <property name="src" location="source" />
    <property name="output" location="bin" />

    <target name="main" depends="init, compile, compress">
        <echo>
            ${message}
        </echo>
    </target>
  
    <target name="init">
        <mkdir dir="${output}" />
    </target>
  
    <target name="compile">
        <javac srcdir="${src}" destdir="${output}" />
    </target>
  
  <target name="compress">
        <tar 
            destfile="${output}/Project.tar.gz" 
            basedir="${output}" 
            includes="*.class" 
            compression="gzip"/>
  </target>
</project>
The attributes of this task appear in Table 4-1.
Table 4-1:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Preparing to Deploy
Ant supports several tasks for setting up a deployment environment, such as delete and mkdir. Both these tasks can be used locally or on a network to set up the directory structure you need to deploy applications.
If you want to create and delete directories remotely, take a look at the ftp task, coming up later in this chapter.
When deploying, delete is great to clean up a previous installation or to clean deployment directories before installing. This task deletes a single file, a directory and all its files and subdirectories, or a set of files specified by one or more FileSets.
Using this task, you can delete a single file:
<delete file="/lib/Project.jar"/>
Or you can delete an entire directory, including all files and subdirectories:
<delete dir="${dist}"/>
You can use filesets:
<delete includeEmptyDirs="true">
    <fileset dir="${dist}"/>
</delete>
You've seen delete at work in various places throughout the book, as in the build file in the input folder for Chapter 3s code (repeated in Example 4-2), where the user is asked for confirmation before deleting anything.
Example 4-2. Using the delete task (ch03/input/build.xml)
<?xml version="1.0" ?>
<project default="main">

    <property name="message" value="Building the .jar file." />
    <property name="src" location="source" />
    <property name="output" location="bin" />

    <target name="main" depends="init, compile, compress">
        <echo>
            ${message}
        </echo>
    </target>
  
    <target name="init">
        <input
            message="Deleting bin directory OK?"
            validargs="y,n"
            addproperty="do.delete"
        />
        <condition property="do.abort">
            <equals arg1="n" arg2="${do.delete}"/>
        </condition>
        <fail if="do.abort">Build aborted.</fail>
        <delete dir="${output}" />
        <mkdir dir="${output}" />
    </target>
  
    <target name="compile">
        <javac srcdir="${src}" destdir="${output}" />
    </target>
  
  <target name="compress">
        <jar destfile="${output}/Project.jar" basedir="${output}" includes="*.class" />
  </target>
</project>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Deploying Applications
Content preview·Buy PDF of this chapter|