GMaven

Access Maven Classpaths for Ant Tasks

Details

  • Type: Improvement Improvement
  • Status: Open Open
  • Priority: Critical Critical
  • Resolution: Unresolved
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None
  • Environment:
    gmaven 1.0-rc4
  • Number of attachments :
    0

Description

One of my biggest desires for the GMaven plugin is the ability to encapsulate legacy Ant build targets in a Maven plugin using the Ant Builder. This allows people to configure a Maven plugin as expected without knowledge of Ant (or Groovy of course) being used 'under the hood'. Granted, this is already available today, but it is missing one big thing that I know of that precludes many Ant tasks from running:

Any ant scripts require a taskdef definition. e.g.:

ant.taskdef( name: "blah", classname:"some.pkg.FQCN", classpath:"$aClasspath" )

It doesn't appear that there is any way to access a Maven classpath to achieve this. The Maven AntRun plugin for example generates 4 classpaths:

maven.compile.classpath
maven.runtime.classpath
maven.test.classpath
maven.plugin.classpath

It would be greatly beneficial if GMaven also enabled these (or similar) classpaths for use with the Ant Builder, then we could encapsulate all Ant details inside a GMaven plugin and the plugin consumer never needs to know these details. Perhaps use the AntRun plugin's support for this?

Until then, our POMs must be littered with numerous unsightly embedded ant xml chunks (via the maven-antrun-plugin) since we need access to many 3rd party ant tasks that do not have a maven plugin equivalent. It'd be much nicer to hide this away from the POM configurer via a GMaven-based plugin with normal Maven configuration attributes.

Issue Links

Activity

Hide
Jason Dillon added a comment -

You have access to the MavenProject instance, which provides all of the details to create such classpaths already. If the intent is to wrap these Ant tasks into a Maven plugin via GMaven, then all you need to do is to create Ant classpath constructs for the various scoped artifact access which MavenProject already exposes.

Show
Jason Dillon added a comment - You have access to the MavenProject instance, which provides all of the details to create such classpaths already. If the intent is to wrap these Ant tasks into a Maven plugin via GMaven, then all you need to do is to create Ant classpath constructs for the various scoped artifact access which MavenProject already exposes.
Hide
Les Hazlewood added a comment -

I looked at the Maven AntRun plugin's source - it is not a trivial exercise (at least not in their code) to enable the 4 classpath references noted above - wouldn't it be nice if the GMaven plugin provided similar references to avoid people defining these themselves?

Would you mind pointing me to an example of how to do what you recommend? If it looks dead easy, then I'll be happy to close this issue ASAP. Any pointers? (If anything, your link would be in this issue and help other people searching for similar solutions).

Show
Les Hazlewood added a comment - I looked at the Maven AntRun plugin's source - it is not a trivial exercise (at least not in their code) to enable the 4 classpath references noted above - wouldn't it be nice if the GMaven plugin provided similar references to avoid people defining these themselves? Would you mind pointing me to an example of how to do what you recommend? If it looks dead easy, then I'll be happy to close this issue ASAP. Any pointers? (If anything, your link would be in this issue and help other people searching for similar solutions).
Hide
Jason Dillon added a comment -

Do you have an example Ant task which you are attempting to use via Maven? Its actually really simple to setup those paths, but if you can point me at an actually task you are trying to use I can give you a more meaningful example.

Show
Jason Dillon added a comment - Do you have an example Ant task which you are attempting to use via Maven? Its actually really simple to setup those paths, but if you can point me at an actually task you are trying to use I can give you a more meaningful example.
Hide
Les Hazlewood added a comment -

I was trying to use the AntBuilder inside of a GMaven Mojo. I needed to do something like this:

ant.taskdef( name: "myDelcaredTask", classname:"some.pkg.FQCN", classpath:"$aClasspath" );
ant.myDeclaredTask(attr1: "someValue", attr2: "anotherValue", ... );

the key here is the $aClasspath reference. I don't know how to reference that classpath from within the GMaven Mojo's execute() method

The usage scenario is this:

1. I declare an task .jar file as one of the plugin's dependencies. Naturally this .jar gets downloaded into the local repository ($HOME/.m2/...)
2. I want to reference that .jar in a classpath
3. I want to use that classpath ($aClasspath) in the ant.taskdef line above when using the AntBuilder.

What is the cleanest way to do this?

Thanks for the help Jason!

Show
Les Hazlewood added a comment - I was trying to use the AntBuilder inside of a GMaven Mojo. I needed to do something like this: ant.taskdef( name: "myDelcaredTask", classname:"some.pkg.FQCN", classpath:"$aClasspath" ); ant.myDeclaredTask(attr1: "someValue", attr2: "anotherValue", ... ); the key here is the $aClasspath reference. I don't know how to reference that classpath from within the GMaven Mojo's execute() method The usage scenario is this: 1. I declare an task .jar file as one of the plugin's dependencies. Naturally this .jar gets downloaded into the local repository ($HOME/.m2/...) 2. I want to reference that .jar in a classpath 3. I want to use that classpath ($aClasspath) in the ant.taskdef line above when using the AntBuilder. What is the cleanest way to do this? Thanks for the help Jason!
Hide
Jason Dillon added a comment -

Here is a wee example for you:

import org.codehaus.groovy.maven.mojo.GroovyMojo

import org.apache.maven.project.MavenProject

import org.apache.tools.ant.types.Path

/**
 * Simple mojo to display some classpath muck.
 *
 * @goal display-classpath
 *
 * @version $Id$
 */
class DisplayClassPathMojo
    extends GroovyMojo
{
    /**
     * @parameter expression="${project}"
     * @required
     * @readonly
     */
    MavenProject project
    
    /**
     * @parameter expression="${plugin.artifacts}"
     * @required
     * @readonly
     */
    List pluginArtifacts
    
    void execute() {
        println "Classpaths:"
        Path p
        
        p = new Path(ant.antProject)
        p.path = project.compileClasspathElements.join(File.pathSeparator)
        println "    Compile=${p}"
        
        p = new Path(ant.antProject)
        p.path = project.runtimeClasspathElements.join(File.pathSeparator)
        println "    Runtime=${p}"
        
        p = new Path(ant.antProject)
        p.path = buildPluginClassPath()
        println "    Plugin=${p}"
    }
    
    private Path buildPluginClassPath() {
        if (pluginArtifacts == null) {
            return new Path(ant.antProject)
        }
        
        List files = []
        pluginArtifacts.each { artifact ->
            files << artifact.file
        }
        
        Path path = new Path(ant.antProject)
        path.path = files.join(File.pathSeparator)
        
        return path
    }
}

For the runtime, compile, etc classpaths its very simple, for the plugins classpath a bit more work, but still quite simple.

Show
Jason Dillon added a comment - Here is a wee example for you:
import org.codehaus.groovy.maven.mojo.GroovyMojo

import org.apache.maven.project.MavenProject

import org.apache.tools.ant.types.Path

/**
 * Simple mojo to display some classpath muck.
 *
 * @goal display-classpath
 *
 * @version $Id$
 */
class DisplayClassPathMojo
    extends GroovyMojo
{
    /**
     * @parameter expression="${project}"
     * @required
     * @readonly
     */
    MavenProject project
    
    /**
     * @parameter expression="${plugin.artifacts}"
     * @required
     * @readonly
     */
    List pluginArtifacts
    
    void execute() {
        println "Classpaths:"
        Path p
        
        p = new Path(ant.antProject)
        p.path = project.compileClasspathElements.join(File.pathSeparator)
        println "    Compile=${p}"
        
        p = new Path(ant.antProject)
        p.path = project.runtimeClasspathElements.join(File.pathSeparator)
        println "    Runtime=${p}"
        
        p = new Path(ant.antProject)
        p.path = buildPluginClassPath()
        println "    Plugin=${p}"
    }
    
    private Path buildPluginClassPath() {
        if (pluginArtifacts == null) {
            return new Path(ant.antProject)
        }
        
        List files = []
        pluginArtifacts.each { artifact ->
            files << artifact.file
        }
        
        Path path = new Path(ant.antProject)
        path.path = files.join(File.pathSeparator)
        
        return path
    }
}
For the runtime, compile, etc classpaths its very simple, for the plugins classpath a bit more work, but still quite simple.
Hide
Jason Dillon added a comment -

I'd still like to know what Ant tasks you are attempting to wrap... mainly because I want to add a new example showing how to do that, but I'm not sure what Ant task to use as an example, and I'd rather not go write one. Do you know of a suitable Ant task which is published into an m2 repo that would do?

Show
Jason Dillon added a comment - I'd still like to know what Ant tasks you are attempting to wrap... mainly because I want to add a new example showing how to do that, but I'm not sure what Ant task to use as an example, and I'd rather not go write one. Do you know of a suitable Ant task which is published into an m2 repo that would do?
Hide
Jason Dillon added a comment -

Actually, after peeping at MGROOVY-152 I realize that in a GMaven Mojo, the pre-created AntBuilder should already have access to the plugins classpath, but due to the way the classloader is constructed it does not. I hope to fix this soonish, though it should work to use the above snips to create the classpath directly when loading the custom task.

Show
Jason Dillon added a comment - Actually, after peeping at MGROOVY-152 I realize that in a GMaven Mojo, the pre-created AntBuilder should already have access to the plugins classpath, but due to the way the classloader is constructed it does not. I hope to fix this soonish, though it should work to use the above snips to create the classpath directly when loading the custom task.

People

Vote (0)
Watch (0)

Dates

  • Created:
    Updated: