Extending Ant with Jython


Though Ant comes complete with an extensive range of built-in tasks suitable for most build-related operations, you will likely encounter situations in the design of your environment that are not accommodated by the existing Ant tasks. In this scenario, we can use Ant's extensibility to define our own tasks.

Ant tasks are traditionally implemented in Java. However, as build tasks are usually the domain of scripting languages, another option is to use Jython. The advantage of this approach is that we get the rapid development benefits of the Jython scripting languages as well as access to Jython's extensive library of functions.

Chapter 9 covers the basics of the Jython language.


Creating a New Ant Task

Implementing a basic Ant task involves the following steps:

1.

Define a Java class that extends org.apache.tools.ant.Task.

2.

Provide public setter methods for all task attributes.

3.

Implement a public execute() method.

Listing 12-5 shows an implementation of an Ant task in Jython. The task has a single attribute called message. Invoking the task from an Ant build file prints out the message held in the attribute and then prints further information on the owning target's dependency information.

You can use this example as a template for creating your own Jython Ant tasks.

Listing 12-5. Jython Ant Task RapidTask.py
 from org.apache.tools.ant import Task from org.apache.tools.ant import Target class RapidTask(Task):   # Overrides the Task.execute() method   #   def execute(self):     "@sig public void execute()"     # Print out properties of task     #   self.log('Task Name: ' + self.taskName)   self.log('Description: ' + self.description)   # Print out the message property   #   self.log('Message: ' + self.message)   # Get the owning target and list dependencies   #   target = self.owningTarget   self.log('Target name: ' + target.name)   for dependency in target.dependencies:     self.log('\tDepends: ' + dependency) # Ant attribute setter method # def setMessage(self, message):   "@sig public void setMessage(java.lang.String str)"   self.message = message 

Compiling Jython Classes

The Jython class shown in Listing 12-5 has a few differences from a normal Jython class, as it must be complied if Ant is to use it. Compiling Jython to standard Java bytecode involves moving from the type-less world of Jython to the strongly typed world of Java. This presents a few problems when defining methods on Java classes as Jython methods have no signature.

To get around this problem, it is necessary to embed a string in the __doc__ namespace of each method that defines the Jython method's Java signature. Here are the embedded method signatures for both the setMessage() and execute() methods on the RapidTask class:

 @sig public void setMessage(java.lang.String str) @sig public void execute() 

The @sig preamble at the start of the string tells the jythonc compiler the Java method signature to generate. This is all jythonc needs to compile the class to bytecode.

The Jython class is compiled from the command line:

 jythonc -a -c -d -j rapidTask.jar RapidTask.py 

The parameters -a, -c, and, -d instruct jythonc to include the entire core Jython libraries in the build. The j rapidTask.jar specifies to place the compiled classes into the named JAR file.

With the new task successfully compiled, it is ready for use from within a build file.

Testing the New Task

The new task is included in the build script using the <taskdef>, which defines the name of the new task and the class to load. Listing 12-6 shows an example of an extract from a small test build file for the new Ant task.

Listing 12-6. Test Build File for the Jython Ant Task
 <target name="test"       depends="clean, package"       description="Access the Jython Ant task">   <!-- Declare the new Jython task -->   <taskdef name="Rapid"             classname="RapidTask">     <classpath>       <pathelement location="${task.jar}"/>     </classpath>   </taskdef>   <!-- Set a property on the task -->   <Rapid description="Example task"           message="My Jython Task" /> </target> 

Invoking the <test> target generates the following output from the Jython Ant task.

 test:     [Rapid] Task Name: Rapid     [Rapid] Description: Example task     [Rapid] Message: My Jython Task     [Rapid] Target name: test     [Rapid]     Depends: clean     [Rapid]     Depends: package BUILD SUCCESSFUL 

The Jython task uses methods on the Task class to obtain information about its environment, such as the name of the task, the name of the owning target, and a list of all dependencies. It also prints out the message attribute we added as part of the task.

That's all there is to building an Ant task with Jython. Mixing Ant and Jython gives us the structure and control of Ant coupled with the rapid scripting capabilities of Jythonthe perfect combination for constructing build processes.



    Rapid J2EE Development. An Adaptive Foundation for Enterprise Applications
    Rapid J2EEв„ў Development: An Adaptive Foundation for Enterprise Applications
    ISBN: 0131472208
    EAN: 2147483647
    Year: 2005
    Pages: 159
    Authors: Alan Monnox

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net