Customize ant class loader

I’m writing a custom plugin to call a legacy ant task.

This ant task needs some jars i ant classpath.

In groovy, I could do something like

project.antBuilder.withClasspath(.....)
or
myclasspath.each{ jarpath ->
    antClassLoader.addURL(file("${jarpath}").toURI().toURL())
}

Bu my plugin is written in java. What’s the corresponding way to add things to the underlying ant project ?

Your first example is trying to use the internal ‘IsolatedAntBuilder’. The second (as far as I understand it) is modifying global classloaders, which is always a bad idea.

I’d recommend using the public AntBuilder, and using the http://groovy.codehaus.org/api/groovy/util/AntBuilder.html API to use ‘typedef’ (and friends) constructs, directly via the Ant project object (i.e. using Ant’s Java API).

Hi Luke

you’re right, my second example was missing the antClassLoader declaration, which was

def antClassLoader = org.apache.tools.ant.Project.class.classLoader

But anyway, based on your intel, I coded :

String jarToInclude = "full/path/to/ant/contrib.jar"
Typedef typeDef = new Typedef();
typeDef.setProject(getProject().getAnt().getAntProject());
typeDef.setURI(new File(jarToInclude).toURI().toString());
typeDef.setOnError(new Typedef.OnError(Typedef.OnError.POLICY_FAILALL));
typeDef.execute();

But the build still fails. My (legacy) ant script (that I cannot modify) does

<condition property="IfTaskAvailable">
    <available classname="net.sf.antcontrib.logic.IfTask"/>
 </condition>
<fail message="The If task is not defined" unless="IfTaskAvailable"/>

Looks like you need to use ‘taskdef’.

http://ant-contrib.sourceforge.net/

BTW, there’s some interesting info on this thread: http://forums.gradle.org/gradle/topics/need_help_trying_to_invoke_an_external_ant_script

In java, I tried various combinations close to the following code

Taskdef taskDef = new Taskdef();
taskDef .setProject(getProject().getAnt().getAntProject());
taskDef .setURI("antlib:net.sf.antcontrib");
taskDef .setClasspath(new Path(getProject().getAnt().getAntProject(), ajcrcAntConfPath));
taskDef .execute();

but every time, the class cannot be found when executing the legacy ant file. I do not know how to populate the taskdef object (and did not find any good example over the net)

ant.taskdef resource: "net/sf/antcontrib/antcontrib.properties",
                 classpath: configurations.antcp.asPath

is the way to do it in the build.gradle script or in the groovy file of the plugin.

But what’s the java way ? I also tried

Taskdef taskDef = new Taskdef();
        taskDef .setResource("net/sf/antcontrib/antcontrib.properties");
        taskDef .setProject(getProject().getAnt().getAntProject());
        taskDef .setClasspath(new Path(getProject().getAnt().getAntProject(), "full/path/to/ant-contrib.jar"));
        taskDef .execute();

but this does not work either

to be more accurate, it seems to work

15:19:54 15:19:54.880 [DEBUG] [org.gradle.api.internal.project.ant.AntLoggingAdapter] Finding class net.sf.antcontrib.logic.IfTask$ElseIf
15:19:54 15:19:54.881 [DEBUG] [org.gradle.api.internal.project.ant.AntLoggingAdapter] Loaded from /xxxxx/ant-contrib.jar net/sf/antcontrib/logic/IfTask$ElseIf.class
15:19:54 15:19:54.882 [DEBUG] [org.gradle.api.internal.project.ant.AntLoggingAdapter] Class net.sf.antcontrib.logic.IfTask$ElseIf loaded from ant loader (parentFirst)

but then when importing the legacy build, it fails.

My plugin does

Taskdef taskDef = new Taskdef();
        taskDef .setResource("net/sf/antcontrib/antcontrib.properties");
        taskDef .setProject(getProject().getAnt().getAntProject());
        taskDef .setClasspath(new Path(getProject().getAnt().getAntProject(), "full/path/to/ant-contrib.jar"));
        taskDef .execute();
...
        getProject().getAnt().importBuild("legacyBuildFile");
        getProject().getAnt().getAntProject().executeTarget("legacy ant target");

but the gradle output is

15:19:57 15:19:56.484 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:echo] checking that the Ant If and For tasks are available for Ant
15:19:57 15:19:56.496 [DEBUG] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:available] class "net.sf.antcontrib.logic.IfTask" was not found
15:19:57 15:19:56.496 [DEBUG] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:available] Unable to load class net.sf.antcontrib.logic.IfTask