Hi, This patch fixes an odd class loading problem, where the classes used by a BuildListener's buildFinished() method cannot be loaded. This is how the problem happens:
- The task is loaded via an AntClassLoader (e.g. using <taskdef> with a classpath specified). - The AntClassLoader adds a BuildListener to the project, so that it can clean up when the build finishes. - When the task executes, it adds a BuildListener to its project. - The build finishes, and a build finished event is fired. - The AntClassLoader's buildFinished() method is called. The class loader cleans itself up. - The task's buildFinished() method is called. If this method uses classes which have not been loaded, the AntClassLoader's findClass() method is called. - The AntClassLoader is in an unusable state, and a NPE is thrown. This patch defers AntClassLoader (and IntrospectionHelper) cleanup until after the build finished event has been handled by all build listeners. Adam
Index: src/main/org/apache/tools/ant/AntClassLoader.java =================================================================== RCS file: /home/cvspublic/jakarta-ant/src/main/org/apache/tools/ant/AntClassLoader.java,v retrieving revision 1.35 diff -u -r1.35 AntClassLoader.java --- src/main/org/apache/tools/ant/AntClassLoader.java 28 Oct 2001 21:25:26 -0000 1.35 +++ src/main/org/apache/tools/ant/AntClassLoader.java 29 Dec 2001 23:57:15 -0000 @@ -79,7 +79,7 @@ * @author <a href="mailto:[EMAIL PROTECTED]">Conor MacNeill</a> * @author <a href="mailto:[EMAIL PROTECTED]">Jesse Glick</a> */ -public class AntClassLoader extends ClassLoader implements BuildListener { +public class AntClassLoader extends ClassLoader implements CleanupListener { /** * An enumeration of all resources of a given name found within the @@ -254,7 +254,7 @@ public AntClassLoader(Project project, Path classpath) { parent = AntClassLoader.class.getClassLoader(); this.project = project; - project.addBuildListener(this); + project.addCleanupListener(this); if (classpath != null) { Path actualClasspath = classpath.concatSystemClasspath("ignore"); String[] pathElements = actualClasspath.list(); @@ -955,9 +955,14 @@ } } + /** + * Cleanup the class loader. + */ public void cleanup() { - pathComponents = null; + // Detach from the project project = null; + + // Close any open Zip/Jar files for (Enumeration e = zipFiles.elements(); e.hasMoreElements(); ) { ZipFile zipFile = (ZipFile)e.nextElement(); try { @@ -968,27 +973,5 @@ } } zipFiles = new Hashtable(); - } - - public void buildStarted(BuildEvent event) { - } - - public void buildFinished(BuildEvent event) { - cleanup(); - } - - public void targetStarted(BuildEvent event) { - } - - public void targetFinished(BuildEvent event) { - } - - public void taskStarted(BuildEvent event) { - } - - public void taskFinished(BuildEvent event) { - } - - public void messageLogged(BuildEvent event) { } } Index: src/main/org/apache/tools/ant/IntrospectionHelper.java =================================================================== RCS file: /home/cvspublic/jakarta-ant/src/main/org/apache/tools/ant/IntrospectionHelper.java,v retrieving revision 1.30 diff -u -r1.30 IntrospectionHelper.java --- src/main/org/apache/tools/ant/IntrospectionHelper.java 25 Dec 2001 19:30:26 -0000 1.30 +++ src/main/org/apache/tools/ant/IntrospectionHelper.java 29 Dec 2001 23:57:19 -0000 @@ -75,7 +75,7 @@ * @author <a href="mailto:[EMAIL PROTECTED]">Stefan Bodewig</a> * @author <a href="mailto:[EMAIL PROTECTED]">Magesh Umasankar</a> */ -public class IntrospectionHelper implements BuildListener { +public class IntrospectionHelper implements CleanupListener { /** * holds the types of the attributes that could be set. @@ -704,8 +704,10 @@ BuildException; } - public void buildStarted(BuildEvent event) {} - public void buildFinished(BuildEvent event) { + /** + * Cleans up after the build has finished + */ + public void cleanup() { attributeTypes.clear(); attributeSetters.clear(); nestedTypes.clear(); @@ -713,10 +715,4 @@ addText = null; helpers.clear(); } - - public void targetStarted(BuildEvent event) {} - public void targetFinished(BuildEvent event) {} - public void taskStarted(BuildEvent event) {} - public void taskFinished(BuildEvent event) {} - public void messageLogged(BuildEvent event) {} } Index: src/main/org/apache/tools/ant/Project.java =================================================================== RCS file: /home/cvspublic/jakarta-ant/src/main/org/apache/tools/ant/Project.java,v retrieving revision 1.89 diff -u -r1.89 Project.java --- src/main/org/apache/tools/ant/Project.java 14 Dec 2001 11:15:42 -0000 1.89 +++ src/main/org/apache/tools/ant/Project.java 29 Dec 2001 23:57:22 -0000 @@ -121,6 +121,7 @@ private File baseDir; private Vector listeners = new Vector(); + private Vector cleanupListeners = new Vector(); /** The Ant core classloader - may be null if using system loader */ private ClassLoader coreLoader = null; @@ -1258,6 +1259,12 @@ BuildListener listener = (BuildListener) listeners.elementAt(i); listener.buildFinished(event); } + + // Notify the cleanup listeners + for ( int i = 0; i < cleanupListeners.size(); i++ ) { + CleanupListener listener = (CleanupListener)cleanupListeners.elementAt(i); + listener.cleanup(); + } } @@ -1328,5 +1335,21 @@ protected void fireMessageLogged(Task task, String message, int priority) { BuildEvent event = new BuildEvent(task); fireMessageLoggedEvent(event, message, priority); + } + + /** + * Adds a cleanup listener. + */ + protected void addCleanupListener(CleanupListener listener) + { + cleanupListeners.addElement(listener); + } + + /** + * Removes a cleanup listener. + */ + protected void removeCleanupListener(CleanupListener listener) + { + cleanupListeners.removeElement(listener); } } Index: src/main/org/apache/tools/ant/ProjectHelper.java =================================================================== RCS file: /home/cvspublic/jakarta-ant/src/main/org/apache/tools/ant/ProjectHelper.java,v retrieving revision 1.70 diff -u -r1.70 ProjectHelper.java --- src/main/org/apache/tools/ant/ProjectHelper.java 18 Dec 2001 20:19:07 -0000 1.70 +++ src/main/org/apache/tools/ant/ProjectHelper.java 29 Dec 2001 23:57:25 -0000 @@ -672,7 +672,7 @@ IntrospectionHelper ih = IntrospectionHelper.getHelper(target.getClass()); - project.addBuildListener(ih); + project.addCleanupListener(ih); for (int i = 0; i < attrs.getLength(); i++) { // reflect these into the target
CleanupListener.java
Description: Binary data
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>
