antExec – Executing external processes in Groovy

Groovy is a nice language. I currently use it for writing maven plugins and for doing scripting tasks in the realm of build automation.

Poor mans integration with .NET or other systems is the command-line. Groovy has built-in support for that:

"myprog".execute()

And if you need parameters:

["cmd", "/C", "cd"].execute()

But there are some problems with how to wait for the process and retrieve the streams. Often you just want the output back – and you want to make sure that the command exited with no error.

There is also a ant-integration in groovy. So I wrote a little wrapper that makes using ant’s exec-task feasible:

mixinAntExec() // has to be called once
// prints the stdout
// if the error code is != 0, 
// it throws an exeption with 
// helpful information
println ("myprog".antExec())

def result = ["myprog", "/fail"].antExec(false)
println (result.exitValue) // error code
println (result.error) // err out
println (result.text) // std out

This script can either be pasted to the bottom, or included on the script path:

def mixinAntExec() {
    String.metaClass.antExec = {failOnError=true -> antExec([delegate], failOnError)}
    ArrayList.metaClass.antExec << {failOnError=true -> antExec(delegate, failOnError)}
}

def antExec(command, failOnError=true) {
    def commandLiteral = command.collect{it.contains(' ') ? '"' + it + '"' : it}.join(' ')
    
    println "ant exec with: ${commandLiteral}"
    
    def ant = new AntBuilder()
    ant.exec(outputproperty:"text",
             errorproperty: "error",
             resultproperty: "exitValue",
             failonerror: false,
             executable: command[0]) {
               if (command.size()>1)
                   arg(line:command[1..-1].collect{it.contains(' ') ? '"' + it + '"' : it}.join(' '))
             }
         
     def result = new Expando(
         text: ant.project.properties.text,
         error: ant.project.properties.error,
         exitValue: ant.project.properties.exitValue as Integer,
         toString: {text}
     )
     
     if (failOnError && result.exitValue != 0){
         throw new Exception("""command failed with ${result.exitValue}
executed: ${commandLiteral}
error: ${result.error}
text: ${result.text}""")

     }
     
     return result
}
Advertisements

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