Ant hooks using Groovy, continued

The Ant Hook scripts using Groovy implementation is extended with the ability to also skip target execution. Thus, an “around” advice AOP like or filter.

In the last post, Ant Hooks using Groovy Script via Scriptdef, we used the Ant BuildListener interface to add a hooks feature that invokes a Groovy script mapped to build events. Now we implement a true “around advice”. Admittingly kludgy, but ….

Approach
Since the hook script has the Ant Event object, we have access to the Target object currently about to be executed. Target has a convenient method to allow target skip:

public void setUnless(java.lang.String property):  
 Sets the "unless" condition to test on execution. 
 if the property is set, the task will not execute. 

Demo
The demo Ant build script is modified with two new targets, ‘deploy’ and ‘build’. Also, the default target is changed to ‘build’.

<project name="demo1" default="build" basedir=".">
    ............ see original code .....
     
    <target name="compile">
        <echo>Hello compile world!</echo>  
    </target> 

    <target name="deploy">
        <echo>Deploying ... ${skipSet}</echo>
    </target>
    
    <target name="build" depends="compile,deploy">
        <echo>Building ... </echo>
    </target>

</project>

A new hook script to filter the ‘deploy’ target and skip it is added.
demo1/deploy_targetStarted.groovy

println "  hook: {project=${event.project.name},target=${event.target.name},when=pre,event=$event}"
hook.skipTarget(event)

Listener implementation
The actual listener is slightly modified to test for the skip property. If found the ‘unLess’ method is used on the target and the target is skipped.

/**
 * Ant build listener that invokes groovy hook scripts.
 *  
 * @author josef betancourt
 *
 */
class HookListener implements SubBuildListener {
    
    ...... see prior post ......

    /** Invoke the 'started' or 'finished' root or target hook script */
    def evokeTargetHook(BuildEvent event, When when){
        def b = new Binding()
        b.event=event
        b.hook=this

        def shell = new GroovyShell(b)
        
        def hookName = "${event.target.name}_${TARGETHOOK}${when.name}"
        
        def hooked = false
        
        def stored = projectHooks[hookName]        
        if(stored){
            hooked = true
            shell.evaluate(stored)
        }else{ 
            def hook = rootHooks[hookName]            
            if(hook){
                hooked = true
                shell.evaluate(hook)
            }
        }        
        
        if( hooked && (when == When.STARTED) ){
            def skipSet = event.project.getProperty(
                 "${event.target.name}_skipTarget")

            if(skipSet){
                event.project.setProperty(skipSet, "true")
                event.target.setUnless(skipSet)
            }            
        }
    }    

    /** invoked from a hook script */
    static void skipTarget(BuildEvent event) {
        def name = event.target.name
        def project = event.project
        project.setProperty(name + "_skipTarget", 'set')
    }

    ...... see prior post ......
}

    ...... see prior post ......

Output

Buildfile: C:\Users\jbetancourt\workspace-4.3\AntAroundAdvice\build.xml
compile:
  hook: {project=demo1,target=compile,when=pre,event=org.apache.tools.ant.BuildEvent}
     [echo] Hello compile world!
 hook: root,{target=compile,when=post,event=org.apache.tools.ant.BuildEvent}
deploy:
  hook: {project=demo1,target=deploy,when=pre,event=org.apache.tools.ant.BuildEvent}
build:
     [echo] Building ... 
BUILD SUCCESSFUL

Further reading

Similar Posts:

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

2 thoughts on “Ant hooks using Groovy, continued”

Leave a Reply

Your email address will not be published. Required fields are marked *