Hi Jochen, unfortunately, the displayed delegation hierarchy is typically not correct. oata.AntClassLoader allways returns the System Classloader (class sun.misc.Launcher$AppClassLoader) as its parent. See http://issues.apache.org/bugzilla/show_bug.cgi?id=35436 If you run ant from it's shell script you will have typically the following delegation hierarchy: * class org.apache.tools.ant.AntClassLoader (loads a task explicitely defined by taskdef, contains the jars/dirs defined in taskdefs classpath argument) * class java.net.URLClassLoader (created by Launcher, Classloader of oata.Project, default tasks and most of the other ant stuff; typically contains your classpath, the jars in $ANT_HOME/lib and the jdk's tools.jar) * class sun.misc.Launcher$AppClassLoader (known as System-, Application- or User- Classloader, that only loads the oata.launch.* classes, normally only contains ant-launcher.jar) * class sun.misc.Launcher$ExtClassLoader (Extension classloader, typically contains the jars in $JRE_HOME/lib/ext) * null (bootstrap classloader for all the jdk stuff, typically contains the jars in $JRE_HOME/lib resp. $JDK_HOME/lib)
To find out the delegation hierarchy in maven you have to change your code to something like this (not clean but should work, assumed your task extends oata.Task): public void execute() throws BuildException { ClassLoader loader = this.getClass().getClassLoader(); if (loader instanceof AntClassLoader) { System.out.println(loader.getClass()); loader = getProject().getCoreloader(); if (loader == null) loader = Project.class.getClassLoader(); } while (loader!=null) { System.out.println(loader.getClass()); loader = loader.getParent(); } } In the next weeks, I will publish a new patch (and a ready-to-use trial version) for the proposed <classloader> and <classloaderreport> task (see http://issues.apache.org/bugzilla/show_bug.cgi?id=28228) that gives a more common solution for this problem. Once knowing the environment's delegation hierarchy you have to decide whether it is really possible to create a consistent second delegation hierarchy for the conflicting jars or not. (This could be done by the proposed <classloader> task). However, if you want to run your task in very different environments (in terms of classloading), I think forking is the cleanest solution. (BTW, forking of compile tasks is IMHO mostly allways the best solution). Cheers Rainer > -----Original Message----- > From: Jochen Theodorou [mailto:[EMAIL PROTECTED] > Sent: Tuesday, August 30, 2005 10:49 AM > To: Ant Users List > Subject: Re: custom classloader for a task > > > Conor MacNeill schrieb: > > > > > Jochen Theodorou wrote: > > > >>Hi all, > >> > >>Te problem I have is a little complex but I hope you can help me. > >>Groovy has an ant task to compile groovy classes and a task to use > >>groovy from within ant see > http://groovy.codehaus.org/Groovy+Ant+Task > >>for details. But in some enviroments such as in maven with certain > >>plugins we have conflicting jars. I mean jars of a > different version > >>than needed by groovy. For example antlr or asm. > >> > >>Our current workaround for the compile task (groovyc) is to > fork the > >>VM. But this can't be the solution? I mean isn't there a > possibility > >>to load a task through a custom classloader? It's no > problem for me to > >>write such a loader, but where to wire it in? I know about the > >>loaderref attribute, but as far as I understand this > attribute is for > >>reusing a classloader. A normal classloader can't be used since a > >>normal classloader looks for a class first in the parent and if the > >>parent knows the conflicting jar/class then we have the > same problem > >>as before. > > > > Since you are passing a classpath to the taskdef above, Ant will > > create a classloader to load this task's classes. What classes this > > classloader can see will depend on the classloader hierarchy under > > Maven. I have no idea what that will be. > > classloader hirarchy for the task class without loaderref: > > class org.apache.tools.ant.AntClassLoader > class sun.misc.Launcher$AppClassLoader > class sun.misc.Launcher$ExtClassLoader > > printed by a task: > > public void execute() throws BuildException { > ClassLoader loader = this.getClass().getClassLoader(); > while (loader!=null) { > System.out.println(loader.getClass()); > loader = loader.getParent(); > } > } > > so it seems maven does not change the hirarchy... > > > It is possible to specify a reverseloader="true" attribute > on an Ant > > taskdef. It is highly deprecated, unsupported, bad things > happen, etc. > > It will cause the classloader to consult it's jars first, > before those > > of its parent. > > well, reverseloader=true might be the thing I am searching for, and a > test shows it works then... But these deprecated warnings are > annoying. > No way to work around this problem? > > >>I heard that when you do loaderref="root" in a maven > project you get > >>the ant-loader, but that will be no help if the normal classpath > >>contains a conflicting jar for another task. Maybe someone > can explain > >>me if a classpath from a taskdef is added to the loader reffered by > >>loaderref. If so the ant-loader will be polluted too. > > > > No, this does not happen - loaderref and classpath are exclusive, I > > think. > > my tests are showing that with a loaderref I hae a different > AntClassLoader, than the normal Classloader, but I have still the > conflicting jar. When I enable reverseloader, then it's ok. > So the new > Loader has to share some classpath parts with the normal antloader > somewhere, because I am sure the sun.misc.Launcher does not caontain > that jar. > > by blackdrag > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]