|
4.3. Deploying ApplicationsAs 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.
4.3.1. Deploying by CopyingThis 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>
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.
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.
4.3.2. Moving FilesThe 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).
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>
4.3.3. Deploying Remotely Using FTPThe 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).
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" user 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!
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" user 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" user 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" user 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" user password="${password}"/>
You can see the attributes of this task in Table 4-12.
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. 4.3.4. Deploying Remotely Using TelnetAnt 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 user 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.
4.3.5. Deploying Remotely Using SSHThe 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.
4.3.6. Deploying Remotely Through EmailYou 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.
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):
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):
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:
4.3.7. Setting File Protections with chmodThe 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.
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. |
|