Ant scripting with Groovy
I've been playing a lot with Ant lately, and while it's a great tool - I like to think of it as the duct tape of Java programming - the restrictions of its XML format can make it a pain to use it for more complicated things. Yes, you can always write an Ant task to do what you need, but that has its disadvantages too - you need to worry about imports, compiling it, adding the jar to the classpath, adding a taskdef... a lot of work for what should be a simple scripting operation.
One possible solution - the Groovy Ant Task.
Here's a very simple example of the power Groovy brings to Ant. Let's take your standard Ant echo task:
There are several ways to write this using the Groovy task:
or
or even
This might not seem like it's worth the trouble... but keep in mind that the string "Groovy is great" can be treated as a Java string for all intensive purposes... and manipulated with any of the Java methods. Not exactly trivial to do that using only Ant.
Let's try something more complex. I need to apply a XSL transform to all the XML files in a folder (quite achievable with Ant tasks) and create a simple HTML file with links to all the transformed files (not that easy using Ant). This is part of a Canoo Webtest Ant runner script, so ignore any of the specifics.
Not TOO bad, hopefully. Let's break it down into parts:
Nothing that couldn't be done using Ant here, this is just the fileScanner task. One thing worth noting is
This is just Groovy code... which isn't that different from plain Java code. Create a file and start writing to it. Again, here we're using the Ant property
Again, mostly just Groovy code. Iterate through all the files and add a link to them in the html file we're building. The fun part is
This is a straightforward translation of the Ant style task into Groovy syntax.
Just one step left. Because of all the < > signs in there, I couldn't figure out how to include this directly in the Ant file. So I saved it as
That wasn't so bad! The Groovy code isn't really any harder to read than the Ant syntax; it doesn't need to be compiled, so the source is simply stored alongside the Ant file, and modifications aren't any more difficult than changing the Ant script itself; and best of all, it allows much greater flexibility than the traditional Ant format.
So far I've used snippets of Groovy code inside an existing Ant script. As the Groovy site shows, it's quite possible to go to the logical extreme and write the entire Ant script as Groovy code - or have a Groovy script with calls to Ant tasks in it, really.
I guess the above is just a really longwinded way to say: if you're using Ant for anything more complex than a simple build script, take the half an hour to set up and play with Groovy a bit. It's well worth it.
One possible solution - the Groovy Ant Task.
Here's a very simple example of the power Groovy brings to Ant. Let's take your standard Ant echo task:
<echo message="Ant is great"/>
There are several ways to write this using the Groovy task:
<groovy>
ant.echo(message:"Groovy is great")
</groovy>
or
<groovy>
ant.echo("Groovy is great")
</groovy>
or even
<groovy>
println("Groovy is great")
</groovy>
This might not seem like it's worth the trouble... but keep in mind that the string "Groovy is great" can be treated as a Java string for all intensive purposes... and manipulated with any of the Java methods. Not exactly trivial to do that using only Ant.
Let's try something more complex. I need to apply a XSL transform to all the XML files in a folder (quite achievable with Ant tasks) and create a simple HTML file with links to all the transformed files (not that easy using Ant). This is part of a Canoo Webtest Ant runner script, so ignore any of the specifics.
<groovy>
def scanner = ant.fileScanner {
fileset(dir:new File(properties.get('webtest.config.resultpath'))) {
include(name:'**/*.xml')
}
}
resultFile = new File(properties.get('webtest.config.resultpath') + "/results.html");
resultFile.write("<html><body><h1>Canoo Webtest results</h1><ul>");
for (f in scanner) {
ant.echo(message:f.name){}
fileName = (f.name =~ "xml").replaceAll("html");
resultFile.append('<li><a href="'+fileName+'">'+fileName+'</a></li>');
ant.style(basedir:properties.get('webtest.config.resultpath'),
destdir:properties.get('webtest.config.resultpath'),
includes:f.name,
force:"true",
extension:".html",
style:properties.get('webtest.config.resultpath')+"/WebTestReport.xsl")
{
ant.param(name:"reporttime", expression:properties.get('report.time'));
ant.param(name:"title", expression:properties.get('ant.project.name'));
}
resultFile.append("</ul></body></html>");
}
</groovy>
Not TOO bad, hopefully. Let's break it down into parts:
def scanner = ant.fileScanner {
fileset(dir:new File(properties.get('webtest.config.resultpath'))) {
include(name:'**/*.xml')
}
}Nothing that couldn't be done using Ant here, this is just the fileScanner task. One thing worth noting is
properties.get('webtest.config.resultpath'), which is the equivalent of ${webtest.config.resultpath}. Next:resultFile = new File(properties.get('webtest.config.resultpath') + "/results.html");
resultFile.write("<html><body><h1>Canoo Webtest results</h1><ul>");
This is just Groovy code... which isn't that different from plain Java code. Create a file and start writing to it. Again, here we're using the Ant property
${webtest.config.resultpath} which is defined elsewhere in the Ant project. Next:for (f in scanner) {
ant.echo(message:f.name){}
fileName = (f.name =~ "xml").replaceAll("html");
resultFile.append('<li><a href="'+fileName+'">'+fileName+'</a></li>');
Again, mostly just Groovy code. Iterate through all the files and add a link to them in the html file we're building. The fun part is
fileName = (f.name =~ "xml").replaceAll("html"); - a simple regular expression to replace the xml extension in the file name to html. Lastly:ant.style(basedir:properties.get('webtest.config.resultpath'),
destdir:properties.get('webtest.config.resultpath'),
includes:f.name,
force:"true",
extension:".html",
style:properties.get('webtest.config.resultpath')+"/WebTestReport.xsl")
{
ant.param(name:"reporttime", expression:properties.get('report.time'));
ant.param(name:"title", expression:properties.get('ant.project.name'));
}
This is a straightforward translation of the Ant style task into Groovy syntax.
Just one step left. Because of all the < > signs in there, I couldn't figure out how to include this directly in the Ant file. So I saved it as
formatresults.groovy, and called it with: <groovy src="${resources.dir}/formatresults.groovy"/>That wasn't so bad! The Groovy code isn't really any harder to read than the Ant syntax; it doesn't need to be compiled, so the source is simply stored alongside the Ant file, and modifications aren't any more difficult than changing the Ant script itself; and best of all, it allows much greater flexibility than the traditional Ant format.
So far I've used snippets of Groovy code inside an existing Ant script. As the Groovy site shows, it's quite possible to go to the logical extreme and write the entire Ant script as Groovy code - or have a Groovy script with calls to Ant tasks in it, really.
I guess the above is just a really longwinded way to say: if you're using Ant for anything more complex than a simple build script, take the half an hour to set up and play with Groovy a bit. It's well worth it.

0 Comments:
Post a Comment
Links to this post:
Create a Link
<< Home