As you'd expect, Ant excels at deploying applications, and there
are a number of tasks to choose from. You've saw the javac
task's destdir
attribute for deployment back in Chapter 1. In this section, you'll see
copy
, move
, ftp
,
telnet
, and sshexec
.
The copy
and move
tasks are useful for local and network
deployments, and tasks like ftp
are
great for remote deployments. Additionally, Chapter 8 will cover deployment to web
servers with tasks like get
, which
you can use to send administrative commands to servers like Tomcat (I'll
cover Tomcat's built-in custom Ant tasks), and serverdeploy
.
Tip
Want to get a file's name without the path attached? Pass the
filename to the basename
task. Want
to get just the path? Use dirname
.
The pathconvert
task converts a
nested path
or reference to a Path,
FileSet, DirSet, or FileList into a path (automatically adjusted for
the target platform) and stores the result in a given property.
This task copies a file, or a fileset, to a new file or a new directory. This is Ant's most basic deployment task for local and network deployment. Here are a few examples, starting with copying just one file:
<copy file="file.txt" tofile="backup.txt"/>
This example copies a file to a new location:
<copy file="file.txt" todir="../backup"/>
This example copies an entire directory to a new location:
<copy todir="../backup"> <fileset dir="${src}"/> </copy>
This copies a set of files to a new directory:
<copy todir="../backup"> <fileset dir="src"> <include name="**/*.java"/> </fileset> </copy>
Want to copy files and change their names? Use a
mapper
element like this:
<copy todir="../backup"> <fileset dir="src"/> <mapper type="glob" from="*" to="*.old"/> </copy>
Here's how to copy a set of files to a directory, replacing
@TODO@
with "DONE
" in all copied files:
<copy todir="../backup"> <fileset dir="src"/> <filter set> <filter token="TODO" value="DONE"/> </filter set> </copy>
Warning
In Unix, file permissions are not retained when files are
copied; files end up with the default UMASK
permissions instead. If you need a
permission-preserving copy function, use the system copy
utilities—see the exec
task in
Chapter 7 (you'd use <exec executable="cp" ... >
here).
Or use the chmod
task, coming up
in this chapter, after the copy.
Example 4-3
uses copy
to copy a documentation
file to make sure it's included in the final JAR for a project and
then deploys the JAR file to a directory named
user.
Example 4-3. Using the copy task (ch04/copy/build.xml)
<?xml version="1.0" ?> <project default="main"> <property name="message" value="Deploying the .jar file." /> <property name="src" location="source" /> <property name="output" location="bin" /> <property name="dist" location="user" /> <target name="main" depends="init, compile, compress, deploy"> <echo> ${message} </echo> </target> <target name="init"> <mkdir dir="${output}" /> <mkdir dir="${dist}" /> </target> <target name="compile"> <javac srcdir="${src}" destdir="${output}" /> </target> <target name="compress"> <copy todir="${output}" file="${src}/readme.txt"/> <jar destfile="${output}/Project.jar" basedir="${output}"> <include name="*.class"/> <include name="*.txt"/> </jar> </target> <target name="deploy"> <copy todir="${dist}"> <fileset dir="${output}"> <exclude name="*.java"/> <exclude name="*.class"/> <exclude name="*.txt"/> </fileset> </copy> </target> </project>
You can see the attributes of this task in Table 4-11.
Table 4-11. The copy task's attributes
Tip
By default, files are only copied if the source file is newer
than the destination file or when the destination file does not
exist. However, you can explicitly overwrite files with the overwrite
attribute.
You can use fileset
elements inside copy
elements to
create a fileset to copy. If you want to use a fileset, the todir
attribute must be set. You can use
nested mapper
elements, and
filter set
elements and the
copy
task supports nested
FilterChains.
The move
task moves a
file (copies and then deletes the original) to a new file or a new
directory or it moves sets of files to a new directory. The attributes
and nested elements are the same as for copy
(see Table 4-11 and related
sections).
Tip
By default, the destination file is overwritten if it already
exists. When overwrite
is turned
off, files are only moved if the source file is newer than the
destination file, or when the destination file does not
exist.
Here's an example that moves a single file (the net result is that the file is renamed):
<move file="file.txt" tofile="file.backup"/>
Here's how to move a directory to a new directory:
<move todir="source"> <fileset dir="backup"/> </move>
Example 4-4 uses
move
to deploy the files it
creates.
Example 4-4. Moving a file (ch04/move/build.xml)
<?xml version="1.0" ?> <project default="main"> <property name="message" value="Deploying the .jar file." /> <property name="src" location="source" /> <property name="output" location="bin" /> <property name="dist" location="user" /> <target name="main" depends="init, compile, compress, deploy"> <echo> ${message} </echo> </target> <target name="init"> <mkdir dir="${output}" /> <mkdir dir="${dist}" /> </target> <target name="compile"> <javac srcdir="${src}" destdir="${output}" /> </target> <target name="compress"> <jar destfile="${output}/Project.jar" basedir="${output}" includes="*.class" /> </target> <target name="deploy"> <move todir="${dist}"> <fileset dir="${output}"> <exclude name="*.java"/> <exclude name="*.class"/> </fileset> </move> </target> </project>
The ftp
task is handy
for remote deployment. This task can send, receive, list, delete
files, and create directories. This is one of Ant's optional tasks, so
you'll need two JAR files, which you place in the Ant
lib directory:
jakarta-oro.jar (available from http://jakarta.apache.org/oro/) and
commons-net.jar (available from http://jakarta.apache.org/commons/net/index.html).
Warning
If you want to use this task with MS FTP servers, you need a version of commons-net.jar and jakarta-oro.jar released after 02/01/2004, or a release of commons-net.jar after 1.1.0 and jakarta-oro.jar after 2.0.8.
Here's an example that deploys the results of a build to
the directory /cgi-bin on a remote server. Since
it's a bad idea to hardcode the username and password in build files,
I'll set those as properties on the command line (you can use the
input
task here) using the
properties name
and password
:
%ant -Dname=Steve -Dpassword=let_me_in
The build file is shown in Example 4-5. Before running the
file, supply the IP address of the server by changing the value of the
server
attribute from
"000.000.000.000" to the IP address of your server or use the name of
the server, like "ftp.apache.org." Though you usually supply an
action
attribute telling ftp
what to do, the default action is to
send files (action="send
"), so you
can omit action
here.
Example 4-5. Using ftp (ch04/ftp/build.xml)
<?xml version="1.0" ?> <project default="main"> <property name="message" value="Deploying the .jar file." /> <property name="src" location="source" /> <property name="output" location="bin" /> <target name="main" depends="init, compile, compress, deploy"> <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}"> <include name="*.class"/> <include name="*.txt"/> </jar> </target> <target name="deploy"> <ftp server="000.000.000.000" binary="true" verbose="true" userid="${name}" password="${password}" remotedir="/cgi-bin"> <fileset dir="${output}"> <exclude name="*.java"/> <exclude name="*.class"/> <exclude name="*.txt"/> </fileset> </ftp> </target> </project>
Here's what running this build file looks like in Windows when uploading the results of a build to a remote server:
C:\ant\ch04\ftp>ant -Dname=steven -Dpassword=let_me_in Buildfile: build.xml init: [mkdir] Created dir: C:\ant\ch04\ftp\bin compile: [javac] Compiling 1 source file to C:\ant\ch04\ftp\bin compress: [jar] Building jar: C:\ant\ch04\ftp\bin\Project.jar deploy: [ftp] sending files [ftp] transferring C:\ant\ch04\ftp\bin\Project.jar [ftp] 1 files sent main: [echo] [echo] Deploying the .jar file. [echo] BUILD SUCCESSFUL Total time: 10 seconds
That's it; you've deployed the results of the build remotely. Very cool!
Tip
If you want to build in delay times to take into account
delays in getting responses from a server, use the Ant waitfor
task. You can use the sleep
task for this purpose.
To retrieve files from the server using ftp
, you set action
to get
, the remotedir
attribute to the remote directory,
and the dir
attribute to the
directory you want the retrieved files stored in locally:
<ftp action="get" server="000.000.000.000" remotedir="/cgi-bin" userid="${name}" password="${password}"> <fileset dir="docs"> <include name="**/*.html"/> </fileset> </ftp>
To delete files, set action
to "del":
<ftp action="del" server="000.000.000.000" remotedir="/cgi-bin" userid="${name}" password="${password}"> <fileset> <include name="**/*.html"/> </fileset> </ftp>
To list files, set action
to "list;" here's how to store the
listing of files in the remote /cgi-bin directory
in a file named file.list:
<ftp action="list" server="000.000.000.000" remotedir="/cgi-bin" userid="${name}" password="${password}" listing="ftp.list"> <fileset> <include name="**"/> </fileset> </ftp>
Here's how to create a directory, /cgi-bin,
by setting action
to
"mkdir:"
<ftp action="mkdir" server="000.000.000.000" remotedir="/cgi-bin" userid="${name}" password="${password}"/>
You can see the attributes of this task in Table 4-12.
Table 4-12. The ftp task's attributes
Attribute | Description | Required | Default |
---|---|---|---|
Specifies the ftp action you want to perform.
Possible values: | No | | |
Specifies the transfer mode. Possible values:
binary-mode ( | No | | |
Specifies the file permissions for new or existing files (Unix only). | No | ||
Specifies you want to transfer only new or
changed files. Set to | No | | |
Specifies you want to allow the task to continue despite some non-fatal error codes. | No | | |
Specifies a file to write output from the "list" action. | Required for the "list" action, but ignored otherwise. | ||
The same as the | No | ||
Specifies you want to use passive transfers. | No | | |
Specifies the login password for the FTP server. | Yes | ||
Specifies the port of the FTP server. | No | | |
Specifies whether you want to give downloaded files the same modified time as the original files. | No | | |
Specifies a directory on the FTP server you want to use. | No | ||
Specifies the directory separator used on the target FTP server. | No | | |
Specifies the address of the FTP server. | Yes | ||
Specifies unsuccessful transfers should be skipped (with a warning). | No | | |
Specifies if to make this task calculate the time difference between you and server. Available in Ant 1.6 or later. | No | ||
Specifies the number of milliseconds between times on the target machine compared to the local machine. Available since Ant 1.6. | No | ||
Specifies the default file permission (unix only). | No | ||
Specifies the login you want to use on the FTP server. | Yes | ||
Specifies whether you want to see information on
each file as it's transferred. Set to | No | |
Tip
The condition
task lets you
probe if remote systems are available before attempting an FTP
operationYou can use two nested elements in condition
: http
(which can test can probe for remote
servers) and socket
(which can
send messages to remote servers).
The ftp
task supports
any number of nested fileset
elements, which is how you specify the files to be retrieved, deleted,
or listed, or whose mode you want to change.
Ant includes a telnet
task that you can use when deploying remotely. For security reasons,
Telnet is losing popularity (in favor of SSH), but I'll take a look at
telnet
, followed by the sshexec
task. This is one of Ant's optional
tasks, so you'll need commons-net.jar (available
from http://jakarta.apache.org/commons/net/index.html)
in the Ant lib directory.
This task uses nested read
elements to indicate strings to wait
for and write
elements to specify
text to send. Here's an example that connects to a server, and asks
for a listing of the directory
/home/steven:
<telnet userid="steven" password="let_me_in" server="000.000.000.000"> <read>/home/steven</read> <write>ls</write> </telnet>
You can see the attributes of this task in Table 4-13.
Table 4-13. The telnet task's attributes
Attribute | Values | Required | Default |
---|---|---|---|
Specifies that you want to send a carriage return after connecting to the server. | No | | |
Specifies the login password you want to use on the Telnet server. | Yes, if | ||
Specifies the port on the Telnet server to use. | No | | |
Specifies the address of the remote Telnet server you want to use. | Yes | ||
Specifies a default timeout for Telnet actions (in seconds). | No | No timeout | |
Specifies the username to use to log into the Telnet server. | Yes, if |
The more secure SSH protocol is replacing Telnet in
general use, and Ant 1.6 added the sshexec
task to execute SSH commands on a
remote system. This is an optional task, so you'll need
jsch.jar (which you can get at http://www.jcraft.com/jsch/index.html) in the
Ant lib directory. Here's an example that runs a
command, touch
, on a remote
machine, using sshexec
:
<sshexec host="000.000.000.000" username="${name}" password="${password}" command="touch index.html"/>
You can find the attributes of this task in Table 4-14.
Tip
See the scp
task for
copying files for deployment to web servers using SSH in Chapter 8.
Table 4-14. The sshexec task's attributes
Attribute | Description | Required | Default |
---|---|---|---|
Specifies if you want the output file to be appended to or overwritten. | No | | |
Specifies the command to run remotely. | Yes | ||
Specifies whether you want to stop the build if there are errors. | No | | |
Specifies the host you want to work with. | Yes | ||
Specifies the name of a file holding a private key. | Yes, if you are using key-based authentication. | ||
Specifies the known hosts file. Used to check the identity of remote hosts. Must be an SSH2 format file. | No | ${user.home}/.ssh/known_hostswn_hostts | |
Specifies the name of a file in which you want output written. | No | ||
Specifies the name of a property in which you want output written. | No | ||
Specifies a passphrase you want to use for your private key. | No | "" | |
Specifies the password to use for SSH. | No | ||
Specifies the port to connect to. | No | | |
Specifies whether you want the operation stopped if it timed out (in milliseconds). | No | | |
Specifies if to trust all unknown hosts if set to "yes." | No | | |
Yes |
You can deploy using email with the mail
task, attaching files you want to
deploy (attachments can be sent using the files
attribute or nested fileset
elements). You'll need access to an
SMTP server, which you specify in the mailhost
attribute and need two JAR files in
the Ant lib directory:
mail.jar (which you can get from http://java.sun.com/products/javamail/) and
activation.jar (which you can get from
http://java.sun.com/products/javabeans/glasgow/jaf.html).
Here's an example, where the results of a build are deployed as an attachment to an email message. This email has the subject "New Build", the message body "Here is the new build.", and has the build's newly created .tar.gz files attached:
<target name="deploy"> <mail mailhost="smtp.isp.com" mailport="1025" subject="New Build"> <from address="developer@isp.com"/> <replyto address="developer@isp.com"/> <to address="list@xyz.com"/> <message>Here is the new build.</message> <fileset dir="dist"> <includes name="**/*.tar.gz"/> </fileset> </mail> </target>
Now you're deploying via email using Ant. You can see the
attributes of the mail
task in
Table 4-15.
Table 4-15. The mailTask's attributes
Attribute | Description | Required | Default |
---|---|---|---|
List of addresses to send a blind copy of the email to. A comma-separated list. | At least one of | ||
List of addresses to send a copy of the email to. A comma-separated list. | At least one of | ||
Specifies the character set you want to use in the email. | No | ||
Specifies the encoding to use. Possible values
are | No | | |
Specifies whether you want to stop the build if there are errors. | No | | |
Specifies files you want to send as attachments.
Use a comma-separated list. You can use nested | No | ||
Specifies the email address of the sender. | Either a | ||
Specifies whether you want to include filename(s) before file contents. | No | | |
Specifies the hostname of the SMTP server. | No | | |
No | | ||
Specifies the email's body. | One of | ||
Specifies a file to send as the email's body. | One of | ||
Specifies the type of the message's content. | No | | |
Specifies the password for SMTP authorization. | Yes, if SMTP authorization is required on your SMTP server. | ||
Specifies the reply-to address. | No | ||
Specifies if you want to use TLS/SSL. | No | ||
Specifies the email's subject. | No | ||
Specifies a list of recipients. A comma-separated list. | At least one of | ||
Specifies the username used to log into the SMTP server. | Yes, if SMTP authorization is required on your SMTP server. |
The mail
task can
take nested to
, cc
, bcc
,
from
, and replyto
elements, which hold email
addresses. Here are the attributes of these elements (these attributes
are common across all these elements):
address
Specifies the email address
name
Specifies the display name for the email address
In addition, the nested message
element sets the message to include
in the email body. Here are the attributes of this element (all are
optional):
charset
Specifies the character set used in the message
mimetype
Specifies the content type of the message
src
Specifies the file to use as the message
You can use email to send the results of a build with
the mail logger, which is useful if you've set up unattended nightly
builds with utilities like at
in
Windows or crontab
in Unix (see
Chapter 7 for coverage of both of
these). Here's how you use this logger:
%ant -logger org.apache.tools.ant.listener.MailLogger
You set these properties in the build file to set up the email you want sent:
MailLogger.mailhost
Specifies the mail server to use (default: localhost)
MailLogger.port
Specifies the default port for SMTP (default: 25)
MailLogger.from
Specifies the mail "from" address (required)
MailLogger.failure.notify
Specifies if to send on failure (default: true)
MailLogger.success.notify
Specifies if to send on success (default: true)
MailLogger.failure.to
Specifies the address to send failure messages to (required if failure mail to be sent)
MailLogger.success.toSpecifies
The address to send success messages to (required if success mail to be sent)
MailLogger.failure.subject
Specifies the subject of failed build (default: "Build Failure")
MailLogger.success.subject
Specifies the subject of successful build (default: "Build Success")
The chmod
task
changes the permissions of a file or files, and it's useful in
deployment after you've got your files deployed in case you need to
set file permissions. You set the permissions in Unix style (just as
the arguments for the Unix chmod
command).
Here's an example that makes run.sh readable, writable and executable for the owner on a Unix system, and readable and executable for others:
<chmod file="${dist}/run.sh" perm="755"/>
This makes all .sh files in and below
${dist}
readable and executable for
anyone on a Unix system:
<chmod dir="${dist}" perm="ugo+rx" includes="**/*.sh"/>
You can see the attributes for this task in Table 4-16.
Table 4-16. The chmod task's attributes
Attribute | Description | Required | Default |
---|---|---|---|
Specifies if you want to use default excludes.
Set to | No | Default excludes are used. | |
Specifies the directory holding the files to work on. | One of | ||
Specifies the patterns matching files to exclude, as a comma- or space-separated list. | No | ||
Specifies the file or single directory where you want permissions to be changed. | One of | ||
Specifies the patterns matching files to include, as a comma- or space-separated list. | No | ||
Specifies limits on how many files to pass at once. Set this attribute to 0 or negative values for unlimited parallelism. Available in Ant 1.6 or later. | No | | |
Specifies the task should process multiple files
using a single | No | | |
Specifies the new permissions you want. | Yes | ||
Specifies the target type. Possible values:
| No | | |
Specifies whether the task should display what it's doing as it does it. Available in Ant 1.6 or later. | No | |
This task holds an implicit FileSet and supports all of
FileSet's attributes and nested elements directly. Since Ant 1.6, you
can specify nested fileset
or
dirset
elements, and you can use
nested filelists.
Get Ant: The Definitive Guide, 2nd Edition now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.