How to do String operations in Ant

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…

8 Responses to How to do String operations in Ant

  1. Alex says:

    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

  2. Peter Thomas says:

    Maybe. With this admittedly cranky approach however, you don’t need to modify the Ant classpath or add any binaries to the build.

  3. 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!

  4. Neal Belair says:

    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.

  5. Pingback: String Casing in Ant | More, Better Clicks

  6. Lon says:

    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/

  7. Pingback: Why you should use the Maven Ant Tasks instead of Maven or Ivy « Incremental Operations

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: