Hi all,
Here is the code and a bit of documentation for RemoteAnt. Please let me
know if you have any questions or comments.
Sorry about the raw attachments, the mail list wouldn't allow a zip file.
You'll have to recreate the package structure to get a build.
Many thanks,
Robert
-----Original Message-----
From: Robert Smith [mailto:[EMAIL PROTECTED]
Sent: 08 March 2004 20:30
To: '[EMAIL PROTECTED]'
Subject: Any interest in a remote Ant server?
Hi all,
I've written an add-on for Ant that allows for remote builds. It consists of
an RMI based server application and a handful of custom Ant tasks on the
client side. My motivation for this was to allow C/C++ code to be built on
remote machines for multiple architectures from the comfort of the
developer's Eclipse IDE on Windows. I tried Rant, but found it too limiting,
so I've done my own version, complete with file transfers and synchronous
logging (which took some work to make it all serialize/deserialize properly
across RMI!)
<snip>
<project name="RemoteAnt" default="jar">
<!--========================================-->
<!--= jar =-->
<!--========================================-->
<target name="jar" depends="rmic">
<copy todir="${dir.classes}">
<fileset dir="${dir.src}"
excludes="**/*.java,
**/*.html"/>
</copy>
<jar destfile="${dir.lib}/ant-remote.jar"
basedir="${dir.classes}"/>
</target>
<!--========================================-->
<!--= rmic =-->
<!--========================================-->
<target name="rmic" depends="compile">
<rmic base = "${dir.classes}"
includes = "${classes.stub}"
classpathref = "path.classpath"
stubversion = "1.2"/>
</target>
<!--========================================-->
<!--= compile =-->
<!--========================================-->
<target name="compile" depends="init">
<mkdir dir="${dir.classes}"/>
<!-- compile our source code -->
<javac srcdir="${dir.src}"
destdir="${dir.classes}"
classpathref="path.classpath"/>
</target>
<!--========================================-->
<!--= clean =-->
<!--========================================-->
<target name="clean" depends="init">
<delete includeEmptyDirs="true" quiet="true">
<fileset dir="${dir.classes}"/>
</delete>
<delete file="${dir.lib}/ant-remote.jar"
quiet="true"/>
</target>
<!--========================================-->
<!--= javadoc =-->
<!--========================================-->
<target name="javadoc"
depends="init"
description="Generate JavaDocs">
<mkdir dir="${dir.doc}"/>
<javadoc packagenames="com.rjmpsmith.*"
sourcepath="${dir.src}"
classpathref="path.classpath"
destdir="${dir.doc}"
author="true"
version="true"
use="true"
windowtitle="Remote Ant API"/>
</target>
<!--========================================-->
<!--= init =-->
<!--========================================-->
<target name="init">
<property name="dir.classes" value="classes"/>
<property name="dir.src" value="src"/>
<property name="dir.lib" value="lib"/>
<property name="dir.doc" value="doc"/>
<property name="classes.stub"
value="com/rjmpsmith/ant/taskdefs/RemoteTask.class
com/rjmpsmith/ant/RemoteBuildServices.class"/>
<path id="path.classpath">
<pathelement location="${dir.classes}"/>
<pathelement path="${dir.lib}/log104j.jar"/>
<pathelement path="${dir.lib}/ant.jar"/>
</path>
</target>
</project>
Building RemoteAnt
------------------
1. Modify the classpath in the build.xml file to point to your versions
of ant.jar and log104j.jar, *or* copy these jars into the lib directory
2. type ant
3. For javadocs, type ant javadocs
Using the RemoteAnt server
--------------------------
Note: My Unix scripting and knowledge of RMI security and configuration are
somewhat limited, so I could seriously use some help standardising the launch
of the server
1. I am using Exception chaining in my code, so it's probably best if you use
JDK1.4+.
2. Make certain that Ant is installed on the server.
3. Add ant-remote.jar to the lib directory of your ant installation(s)
4. In order for the server to work, You will need to provide two files
somewhere on the
classpath - an RMI policy file, and a log4j configuration file. I've attached
simple examples at the end of this file. I've also attached the bash script I
use to kick things off - though I'm no Unix guru. I could really use some
help
5. Start rmiregistry on your desired port.
6. Start the server. Command line arguments are:
1. The RMI port from step 5
2. Some location in the filesystem to store files to support the builds
3. (optional) Default time to live (in minutes) for abandoned sessions
The default is 240 minutes. If the session hasn't been closed by
then,
a timer fires, and the server will close the session automatically,
deleting all files stored on the session's behalf.
example - see bellow for my sad attempt at a script
---------------------------------------------------
% export CLASSPATH=<current dir and all ant jars>
% rmiregistry 2020
% java -Djava.security.policy=policy.txt
com.rjmpsmith.ant.RemoteAntServer 2020 /tmp/builds 120
My first shot at a script to launch the server on Unix
------------------------------------------------------
I created a directory which contains the script, the policy.txt file, and
log4j.properties.
I've always been a bit hazy on exactly what I have to make available to the
rmiregistry and
the server class in order to avoid the dreaded unmarshaling exceptions, so I
tend to
throw everything at them.
Here's the script - obviously the paths are for our own server
#
# This file starts an Ant build server on Unix
#
# Get the OS name
UNAME=`uname`
# set up the common environment
ANT_HOME=/usr/shared/scm/tools/apache-ant-1.6.1
RMI_PORT=2020
BUILD_DIR=/tmp/builds
# set up OS specific environment
if [ $UNAME == 'Linux' ]
then
JAVA_HOME=/usr/shared/scm/tools/linux/j2sdk1.4.2_03
PATH=$JAVA_HOME/bin:$ANT_HOME/bin:/usr/shared/scm/tools/linux/bin
else
JAVA_HOME=/usr/shared/scm/tools/solaris/j2sdk1.4.2_03
PATH=$JAVA_HOME/bin:$ANT_HOME/bin:/usr/shared/scm/tools/solaris/bin
fi
# set up the Java classpath
CLASSPATH=.
for jar in $ANT_HOME/lib/*.jar
do
CLASSPATH=$CLASSPATH:$jar
done
# export our environment variables
export JAVA_HOME
export ANT_HOME
export PATH
export CLASSPATH
# start an RMI registry server
echo Starting RMI registry on port $RMI_PORT...
$JAVA_HOME/bin/rmiregistry $RMI_PORT&
echo PID=$!
# start the remote build server
echo Starting remote build server...
$JAVA_HOME/bin/java -classpath $CLASSPATH -Djava.security.policy=policy.txt
com.rjmpsmith.ant.RemoteAntServer $RMI_PORT $BUILD_DIR 120 &
echo PID=$!
Sample policy file - not safe!
------------------------------
grant {
permission java.security.AllPermission;
};
Sample log4j configuration - console only
-----------------------------------------
# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A1
# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender
# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
Using the client
----------------
In your buildfile, import the task definitions:
<taskdef resource="remoteant.taskdefs"/>
The following tasks are supported:
createSession=com.rjmpsmith.ant.taskdefs.CreateRemoteSessionTask
closeSession=com.rjmpsmith.ant.taskdefs.CloseRemoteSessionTask
remoteBuild=com.rjmpsmith.ant.taskdefs.RemoteBuildTask
putFiles=com.rjmpsmith.ant.taskdefs.RemotePutFileTask
getFile=com.rjmpsmith.ant.taskdefs.RemoteGetFileTask
Here's how to use them:
createSession
-------------
Creates a session for this build on the remote server. When a session is
created,
A RemoteSession object is created and placed into a synchronized HashMap. This
object maps a unique ID (String) to a location in the filesystem where files
will
be stored on it's behalf. In order to prevent failed builds from causing
sessions
to build up, it also contains the watchdog timer which will fire after a given
length of time, removing the session.
<createSession host="somehost"
port="rmiregistryport"
property="sessionname"
ttl="60"/> <-- Optional. Overrides the
default time to
live. Given In minutes.
If the tasks succedes, the property specified in the property attribute will be
set
to the unique ID for the session. This property is then used with the other
tasks.
CloseSession
------------
Pretty self explanitory - removes all files associated with the session from
the server, cancels the watchdog timer, and removes the RemoteSession object
from
the HashMap.
<closeSession session="${sessionname}"/>
putFiles
--------
Transfers files from the client to the server. Files on the server are placed
into
a directory structure as follows. This location is stored in the RemoteSession
object.
root build path (given as arg to server)
|
|_ hostname of the client
|
|_ timestamp of the session (This would be the project root of the
ant build)
|
|_ dir structure given in remotedir attribute (if present)
|
|_ dir structure which mirrors the fileset, or none
if flatten attribute is set.
<putFiles session="${sessionname}"
remotedir="some/extra/dir" <-- optional. Applies to all
filesets
flatten="true"> <-- optional. Applies to all
filesets
<fileset dir="cfg">
<include name="SolarisCBuild.xml"/>
</fileset>
<fileset dir="${basedir}"
includes="**/c/**"
excludes="**/Makefile"/>
<fileset dir="src"/>
</putFiles>
Through the use of remotedir and flatten attributes, you can easily create
complex
file heirarchies on the server. However, you would probably need to use several
calls
to putFiles. File transfer is blindingly fast, though, so no harm putting more
than
you really need if you wish to keep things simple.
remoteBuild
-----------
Kicks off an Ant build on the remote server. BuildEvents are captured by a
custom
listener on the remote end and forwarded on in real time (via an RMI callback)
to
a custom listener on the local client (implemented by the RemoteTask base
class),
which in turn publishes them on to all (standard) registered listeners in the
local Ant process.
<remoteBuild session="${sessionname}"
buildfile="remotebuild.xml" <-- Optional. Defaults to
build.xml
targets="build,deploy"/> <-- Optional. Defaults to the
default
target in the build file.
Comma
seperated list.
getFile
-------
Retrieves a file from the remote session. Remote file is given relative to the
project
root on the server side (see above). Local file is ABSOLUTE.
<getFile session="${sessionname}"
remoteFile="ctjava"
localFile="${basedir}/Configuration/bin/ctjava"/>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]