Mitch Gitman | 31 May 2012 18:33
Picon

example of correctly consuming an Ant project programmatically

Can someone point me to a good, reference example of consuming an Ant
project programmatically? The code needs to have access to the
org.apache.tools.ant.Project object.

I have been able to do this, but with just one catch. Below are the
relevant lines of Java code:
Project project = new Project();
project.setBaseDir(basedir); // basedir is a File object
project.init();
ProjectHelper.configureProject(project, buildFile); // buildFile is a File
object

From here, I can call executeTarget on the Project object as needed.

Everything works fine, but here's the catch. Whatever the code is that
instantiates the Project object, the Project will take the libraries in the
classpath for that code (typically a JUnit test) and put that in its own
classpath.

So, for example, if the programmatically instantiated Ant needs to call the
javac Ant task, then I would need to add lib/tools.jar in the JDK to the
runtime classpath for the code that launches Ant. Likewise, there might be
some libraries that are needed in the test's classpath but aren't needed by
the Ant project that is launched by the test but which will then leak into
the Project's classpath and wreak havoc.

My guess is there's something about the coreLoader member of the Project
object I need to be controlling. I've also looked at the AntClassLoader
class. My fear is there's something really fundamental about the Ant
ClassLoader, or maybe just ClassLoaders in general, that I'm not quite
(Continue reading)

Nicolas Lalevée | 31 May 2012 23:17
Favicon
Gravatar

Re: example of correctly consuming an Ant project programmatically


Le 31 mai 2012 à 18:33, Mitch Gitman a écrit :

> Can someone point me to a good, reference example of consuming an Ant
> project programmatically? The code needs to have access to the
> org.apache.tools.ant.Project object.
> 
> I have been able to do this, but with just one catch. Below are the
> relevant lines of Java code:
> Project project = new Project();
> project.setBaseDir(basedir); // basedir is a File object
> project.init();
> ProjectHelper.configureProject(project, buildFile); // buildFile is a File
> object
> 
> From here, I can call executeTarget on the Project object as needed.
> 
> Everything works fine, but here's the catch. Whatever the code is that
> instantiates the Project object, the Project will take the libraries in the
> classpath for that code (typically a JUnit test) and put that in its own
> classpath.
> 
> So, for example, if the programmatically instantiated Ant needs to call the
> javac Ant task, then I would need to add lib/tools.jar in the JDK to the
> runtime classpath for the code that launches Ant. Likewise, there might be
> some libraries that are needed in the test's classpath but aren't needed by
> the Ant project that is launched by the test but which will then leak into
> the Project's classpath and wreak havoc.
> 
> My guess is there's something about the coreLoader member of the Project
(Continue reading)

Mitch Gitman | 1 Jun 2012 04:16
Picon

Re: example of correctly consuming an Ant project programmatically

Nicolas, thanks. I think this is what I'm looking for.

Here's the relevant passage from Launcher:
        URL[] jars = getJarArray(
            libURLs, userURLs, systemURLs, Locator.getToolsJar());
…
        URLClassLoader loader = new URLClassLoader(jars);
        Thread.currentThread().setContextClassLoader(loader);
        Class mainClass = null;
        int exitCode = 0;
        try {
            mainClass = loader.loadClass(mainClassname);
            AntMain main = (AntMain) mainClass.newInstance();
            main.startAnt(newArgs, null, null);
        } catch (InstantiationException ex) {

The one way I may have to tweak this (well, aside from instantiating
Project directly instead of Main) is to do:
new URLClassLoader(jars, null);

Passing null for the extra ClassLoader argument obviates the possibility of
the parent classloader creeping in.

I went looking for how AntUnit initializes the Ant Project, and
interestingly, it does something not unlike what I was doing. No
controlling of the ClassLoader. I suppose the existing ClassLoader for
AntUnit, already normally being invoked by Ant, suffices.

I also opened up the Manning "Ant in Action" book and came across a whole
section on "Embedding Ant." Same story. And again, that seems to suffice,
(Continue reading)


Gmane