groovyantclassloadergroovy-grapetaskdef

Groovy + Antbuilder: How to use Grape to with taskdef?


This is related to . I'm trying to dynamically add the maven-ant-tasks jars with Grape, simulating this:

  <taskdef uri="antlib:org.apache.maven.artifact.ant"
           resource="org/apache/maven/artifact/ant/antlib.xml"
           classpathref="ant.classpath" />

I've tried to use Grape.grab() to make maven-ant-tasks available to AntBuilder like this:

import groovy.grape.Grape

println "grab..."
Grape.grab(group:'ant', module:'ant', version:'1.7.0', classLoader:this.class.classLoader.rootLoader)
Grape.grab(group: 'org.apache.maven', module: 'maven-ant-tasks', version: '2.0.9')

println "ant taskdef..."
def ant = new AntBuilder()
ant.taskdef (resource: "org/apache/maven/artifact/ant/antlib.xml" )

but that doesn't work because Grape adds the modules to a different ClassLoader from the one that ANT engine is using. So, I took the advice from this AntBuilder classpath question and made Grape use the root ClassLoader:

import groovy.grape.Grape

println "grab..."
Grape.grab(group:'ant', module:'ant', version:'1.7.0', classLoader:this.class.classLoader.rootLoader)
Grape.grab(group: 'org.apache.maven', module: 'maven-ant-tasks', version: '2.0.9', classLoader: this.class.classLoader.rootLoader)

println "ant taskdef..."
def ant = new AntBuilder()
ant.taskdef (resource: "org/apache/maven/artifact/ant/antlib.xml" )

Now it throws a LinkageError:

Caught: : java.lang.LinkageError: loader constraint violation: when resolving overridden method "org.apache.tools.ant.helper.ProjectHelper2$RootHandler.setDocumentLocator(Lorg/xml/sax/Locator;)V" the class loader (instance of org/codehaus/groovy/tools/RootLoader) of the current class, org/apache/tools/ant/helper/ProjectHelper2$RootHandler, and its superclass loader (instance of <bootloader>), have different Class objects for the type org/xml/sax/Locator used in the signature
 at test.mavenanttasks.run(mavenanttasks.groovy:11)

Any hints on getting this to work? Or, is the whole thing a bad idea?


Solution

  • I found this: http://groovy.codehaus.org/Using+Ant+Libraries+with+AntBuilder

    First, put maven-ant-tasks in the root classloader with:

    @Grapes([
    @Grab(group = 'org.apache.maven', module = 'maven-ant-tasks', version = '2.1.3'),
    @GrabConfig(systemClassLoader = true)
    ])
    

    Alternatively, for older versions of Groovy:

    Grape.grab(group: 'org.apache.maven', module: 'maven-ant-tasks', version: '2.1.3', classLoader: this.class.classLoader.rootLoader)
    

    The Maven ANT tasks are an 'AntLib', and they can be loaded like this:

    import groovy.xml.NamespaceBuilder
    def ant = new AntBuilder()
    def mvn = NamespaceBuilder.newInstance(ant, 'antlib:org.apache.maven.artifact.ant')