I was trying to create an Ant based wizard to generate a Wicket quickstart project. So like the trend nowadays the script should prompt you for the project name at the start then *boom* – you get your Maven2 directory structure, pom.xml, web.xml, a couple of placeholder web-pages – just type mvn jetty:run and you are up and running.
I wanted the user to only enter the project-name: a lower-case string without spaces or special characters. Then I wanted the Wicket Application class to be generated as per tradition i.e. if your project short name is “test” the file should be “TestApplication.java”
But then it hit me – there is no way to do things like uppercase / lowercase string conversion in Ant! Yikes. I could make-do with a second prompt for the user to get the application class name, but hey, that’s so not-DRY, and I like an Ant challenge :)
One option was to use Beanshell – but I’m obsessed with getting things to work with a “clean” Ant install, without messing around with the classpath or ant-home. After being spoilt by Maven, I don’t like having orphan jar files lying around in the project directory structure either.
So I ended up doing this. Here is a small Java class that processes a command line argument and writes the result to a file:
import java.io.FileOutputStream;
import java.io.PrintWriter;
public class TitleCaser {
public static void main(String[] args) throws Exception {
FileOutputStream os = new FileOutputStream("target/temp.txt");
PrintWriter out = new PrintWriter(os);
String s = args[0];
out.write(Character.toUpperCase(s.charAt(0)) + s.substring(1));
out.close();
os.close();
}
}
This java file resides in an “etc” folder. And the start of the Ant script looks like this:
<javac srcdir="etc" includes="TitleCaser.java"/>
<input message="Enter Project Name:" addproperty="project.name"/>
<java classpath="etc" classname="TitleCaser">
<arg value="${project.name}"/>
</java>
<loadfile property="project.name.titleCase" srcFile="target/temp.txt"/>
I know, I know, Ant is XML, it is a declarative language, I must be crazy etc. But I can think of all kinds of interesting things to do with this approach. There are various ways to load stuff into Ant from files, “loadfile” is just one of them. Think of the possibilities – you can generate Java code from Ant, “javac” it on the fly and work around all the Ant limitations like not having good control-flow support etc. Maybe you can even generate some XML and use that in a downstream target and tell your boss that your Ant build is SOA compliant…





Hi Peter,
in your case – for just changing a simple string – wouldn’t it have been easier to just extend the Task class, implement the execute method and set the property therein (using getProject().setProperty(…))?
The property to set could be an attribute of this custom task, too.
~Alex
Comment by Alex — May 22, 2007 @ 8:18 pm
Maybe. With this admittedly cranky approach however, you don’t need to modify the Ant classpath or add any binaries to the build.
Comment by Peter Thomas — May 25, 2007 @ 9:56 am
Hi, Peter.
Recently I have started interesting in Buildr, and it looks really nice.
Buildr – build tool for java, but uses Ruby as scripting language and based on Rake (very powerful and mature tool for Ruby)
Check it – you could do in your build script what do you like – it is Ruby!
Comment by Anatol Pomozov — July 11, 2007 @ 4:03 pm
Another way is to use Javascript or to create a task:
http://xins.sourceforge.net/j2h/latest/org/xins/common/ant/UppercaseTask.java.html
Comment by Anthony Goubard — July 25, 2007 @ 3:56 pm
I like the way you think, Peter. Along those same lines, for people who want to use existing functions of their operating system, rather than Java (as long as we are breaking all the rules :-) the new ant exec task could allow this. For example, if running ant under Linux, the ant project name could be lowercased as follows, using the Linux tr command:
This idea should work in other operating systems as well; but, you would have to find the correct command and argument values for the particular OS under which you were running ant.
Comment by Neal Belair — April 10, 2008 @ 2:25 am
[...] there isn’t one for String manipulation. After a bit of Googling, the best I found was in a blog post by Peter Thomas which suggested writing a small Java class, that was compiled during the Ant build, and then used [...]
Pingback by String Casing in Ant | More, Better Clicks — August 14, 2008 @ 8:58 pm
Peter, good post. Your approach (of trying to avoid manipulating the Ant install environment for simple string manipulation) makes sense. I took your idea an iteration further, avoiding the temp file, which I think is the most important change.
I started fixing the java class as well to do real title casing (rather than just the first letter of the whole text)… then got carried away and adding options for upper and lower casing.
Anyway, if you’re interested in seeing the change, I posted it on my company’s blog (sorry about the lack of formatting):
http://morebetterclicks.com/2008/08/14/string-casing-in-ant/
Comment by Lon — August 14, 2008 @ 9:55 pm
[...] even Ant may not have all the answers and a technique I use (or misuse) effectively is to use a custom Java class to extend Ant. So I don’t even need to learn how to create custom Ant tasks and mess around [...]
Pingback by Why you should use the Maven Ant Tasks instead of Maven or Ivy « Incremental Operations — March 8, 2009 @ 11:55 pm