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

Attachment: CleanupListener.java
Description: Binary data

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to