bodewig 2004/06/24 04:16:41 Modified: src/main/org/apache/tools/ant AntClassLoader.java Project.java src/main/org/apache/tools/ant/taskdefs Ant.java Recorder.java RecorderEntry.java Added: src/main/org/apache/tools/ant SubBuildListener.java Log: Follow Conor's and Jose Alberto's advice - improved fix for PR 8689 Revision Changes Path 1.83 +40 -15 ant/src/main/org/apache/tools/ant/AntClassLoader.java Index: AntClassLoader.java =================================================================== RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/AntClassLoader.java,v retrieving revision 1.82 retrieving revision 1.83 diff -u -r1.82 -r1.83 --- AntClassLoader.java 20 Apr 2004 13:25:08 -0000 1.82 +++ AntClassLoader.java 24 Jun 2004 11:16:40 -0000 1.83 @@ -44,7 +44,7 @@ * class will then use this loader rather than the system class loader. * */ -public class AntClassLoader extends ClassLoader implements BuildListener { +public class AntClassLoader extends ClassLoader implements SubBuildListener { private static final FileUtils fileUtils = FileUtils.newFileUtils(); @@ -118,7 +118,7 @@ private void findNextResource() { URL url = null; while ((pathElementsIndex < pathComponents.size()) - && (url == null)) { + && (url == null)) { try { File pathComponent = (File) pathComponents.elementAt(pathElementsIndex); @@ -222,7 +222,7 @@ Class protectionDomain = Class.forName("java.security.ProtectionDomain"); Class[] args = new Class[] {String.class, byte[].class, - Integer.TYPE, Integer.TYPE, protectionDomain}; + Integer.TYPE, Integer.TYPE, protectionDomain}; defineClassProtectionDomain = ClassLoader.class.getDeclaredMethod("defineClass", args); } catch (Exception e) { @@ -392,9 +392,9 @@ if (project != null) { project.log(message, priority); } -// else { -// System.out.println(message); -// } + // else { + // System.out.println(message); + // } } /** @@ -442,7 +442,7 @@ public void addPathElement(String pathElement) throws BuildException { File pathComponent = project != null ? project.resolveFile(pathElement) - : new File(pathElement); + : new File(pathElement); try { addPathFile(pathComponent); } catch (IOException e) { @@ -582,7 +582,7 @@ * on this loader's classpath. */ public Class forceLoadClass(String classname) - throws ClassNotFoundException { + throws ClassNotFoundException { log("force loading " + classname, Project.MSG_DEBUG); Class theClass = findLoadedClass(classname); @@ -611,7 +611,7 @@ * on this loader's classpath. */ public Class forceLoadSystemClass(String classname) - throws ClassNotFoundException { + throws ClassNotFoundException { log("force system loading " + classname, Project.MSG_DEBUG); Class theClass = findLoadedClass(classname); @@ -815,7 +815,7 @@ URL url = null; if (isParentFirst(name)) { url = (parent == null) ? super.getResource(name) - : parent.getResource(name); + : parent.getResource(name); } if (url != null) { @@ -907,7 +907,7 @@ if (entry != null) { try { return new URL("jar:" + fileUtils.getFileURL(file) - + "!/" + entry); + + "!/" + entry); } catch (MalformedURLException ex) { return null; } @@ -941,7 +941,7 @@ * classpath. */ protected synchronized Class loadClass(String classname, boolean resolve) - throws ClassNotFoundException { + throws ClassNotFoundException { // 'sync' is needed - otherwise 2 threads can load the same class // twice, resulting in LinkageError: duplicated class definition. // findLoadedClass avoids that, but without sync it won't work. @@ -1059,8 +1059,8 @@ * reading the class from the stream. */ private Class getClassFromStream(InputStream stream, String classname, - File container) - throws IOException, SecurityException { + File container) + throws IOException, SecurityException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); int bytesRead = -1; byte[] buffer = new byte[BUFFER_SIZE]; @@ -1120,7 +1120,7 @@ * on this loader's classpath. */ private Class findClassInComponents(String name) - throws ClassNotFoundException { + throws ClassNotFoundException { // we need to search the components of the path to see if // we can find the class we want. InputStream stream = null; @@ -1217,6 +1217,31 @@ */ public void buildFinished(BuildEvent event) { cleanup(); + } + + /** + * Cleans up any resources held by this classloader at the end of + * a subbuild if it has been created for the subbuild's project + * instance. + * + * @param event the buildFinished event + * + * @since Ant 1.6.2 + */ + public void subBuildFinished(BuildEvent event) { + if (event.getProject() == project) { + cleanup(); + } + } + + /** + * Empty implementation to satisfy the BuildListener interface. + * + * @param event the buildStarted event + * + * @since Ant 1.6.2 + */ + public void subBuildStarted(BuildEvent event) { } /** 1.169 +38 -1 ant/src/main/org/apache/tools/ant/Project.java Index: Project.java =================================================================== RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/Project.java,v retrieving revision 1.168 retrieving revision 1.169 diff -u -r1.168 -r1.169 --- Project.java 1 Jun 2004 14:51:55 -0000 1.168 +++ Project.java 24 Jun 2004 11:16:40 -0000 1.169 @@ -1790,6 +1790,43 @@ } } + /** + * Sends a "subbuild started" event to the build listeners for + * this project. + * + * @since Ant 1.6.2 + */ + public void fireSubBuildStarted() { + BuildEvent event = new BuildEvent(this); + Iterator iter = listeners.iterator(); + while (iter.hasNext()) { + Object listener = iter.next(); + if (listener instanceof SubBuildListener) { + ((SubBuildListener) listener).subBuildStarted(event); + } + } + } + + /** + * Sends a "subbuild finished" event to the build listeners for + * this project. + * @param exception an exception indicating a reason for a build + * failure. May be <code>null</code>, indicating + * a successful build. + * + * @since Ant 1.6.2 + */ + public void fireSubBuildFinished(Throwable exception) { + BuildEvent event = new BuildEvent(this); + event.setException(exception); + Iterator iter = listeners.iterator(); + while (iter.hasNext()) { + Object listener = iter.next(); + if (listener instanceof SubBuildListener) { + ((SubBuildListener) listener).subBuildFinished(event); + } + } + } /** * Sends a "target started" event to the build listeners for this project. 1.1 ant/src/main/org/apache/tools/ant/SubBuildListener.java Index: SubBuildListener.java =================================================================== /* * Copyright 2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.apache.tools.ant; /** * Instances of classes that implement this interface can register * to be also notified when things happened during a subbuild. * * <p>A subbuild is a separate project instance created by the * <code><ant></code> task family. These project instances will * never fire the buildStarted and buildFinished events, but they will * fire subBuildStarted/ and subBuildFinished. The main project * instance - the one created by running Ant in the first place - will * never invoke one of the methods of this interface.</p> * * @see BuildEvent * @see Project#addBuildListener(BuildListener) * * @since Ant 1.6.2 */ public interface SubBuildListener extends BuildListener { /** * Signals that a subbuild has started. This event * is fired before any targets have started. * * @param event An event with any relevant extra information. * Must not be <code>null</code>. */ void subBuildStarted(BuildEvent event); /** * Signals that the last target has finished. This event * will still be fired if an error occurred during the build. * * @param event An event with any relevant extra information. * Must not be <code>null</code>. * * @see BuildEvent#getException() */ void subBuildFinished(BuildEvent event); } 1.102 +7 -17 ant/src/main/org/apache/tools/ant/taskdefs/Ant.java Index: Ant.java =================================================================== RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/Ant.java,v retrieving revision 1.101 retrieving revision 1.102 diff -u -r1.101 -r1.102 --- Ant.java 23 Jun 2004 14:08:26 -0000 1.101 +++ Ant.java 24 Jun 2004 11:16:41 -0000 1.102 @@ -379,32 +379,22 @@ addReferences(); if (target != null && !"".equals(target)) { + Throwable t = null; try { log("Entering " + antFile + "...", Project.MSG_VERBOSE); + newProject.fireSubBuildStarted(); newProject.executeTarget(target); } catch (BuildException ex) { - throw ProjectHelper.addLocationToBuildException( - ex, getLocation()); - } finally { + t = ProjectHelper + .addLocationToBuildException(ex, getLocation()); + throw (BuildException) t; + } finally { log("Exiting " + antFile + ".", Project.MSG_VERBOSE); + newProject.fireSubBuildFinished(t); } } } finally { // help the gc - Iterator iter = getBuildListeners(); - while (iter.hasNext()) { - newProject.removeBuildListener((BuildListener) iter.next()); - } - iter = newProject.getBuildListeners().iterator(); - while (iter.hasNext()) { - Object o = iter.next(); - if (o instanceof RecorderEntry) { - ((RecorderEntry) o).close(); - } else if (o instanceof AntClassLoader) { - ((AntClassLoader) o).cleanup(); - } - } - newProject = null; Enumeration e = properties.elements(); while (e.hasMoreElements()) { 1.21 +1 -1 ant/src/main/org/apache/tools/ant/taskdefs/Recorder.java Index: Recorder.java =================================================================== RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/Recorder.java,v retrieving revision 1.20 retrieving revision 1.21 diff -u -r1.20 -r1.21 --- Recorder.java 9 Mar 2004 16:48:06 -0000 1.20 +++ Recorder.java 24 Jun 2004 11:16:41 -0000 1.21 @@ -211,7 +211,7 @@ throw new BuildException("Problems creating a recorder entry", ioe); } - proj.addBuildListener(entry); + entry.setProject(proj); recorderEntries.put(name, entry); } else { entry = (RecorderEntry) o; 1.18 +49 -3 ant/src/main/org/apache/tools/ant/taskdefs/RecorderEntry.java Index: RecorderEntry.java =================================================================== RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/RecorderEntry.java,v retrieving revision 1.17 retrieving revision 1.18 diff -u -r1.17 -r1.18 --- RecorderEntry.java 23 Jun 2004 14:08:26 -0000 1.17 +++ RecorderEntry.java 24 Jun 2004 11:16:41 -0000 1.18 @@ -21,6 +21,7 @@ import org.apache.tools.ant.BuildLogger; import org.apache.tools.ant.DefaultLogger; import org.apache.tools.ant.Project; +import org.apache.tools.ant.SubBuildListener; import org.apache.tools.ant.util.StringUtils; /** @@ -30,7 +31,7 @@ * @version 0.5 * @since Ant 1.4 */ -public class RecorderEntry implements BuildLogger { +public class RecorderEntry implements BuildLogger, SubBuildListener { ////////////////////////////////////////////////////////////////////// // ATTRIBUTES @@ -47,6 +48,8 @@ private long targetStartTime = 0L; /** Strip task banners if true. */ private boolean emacsMode = false; + /** project instance the recorder is associated with */ + private Project project; ////////////////////////////////////////////////////////////////////// // CONSTRUCTORS / INITIALIZERS @@ -99,7 +102,32 @@ + StringUtils.LINE_SEP); error.printStackTrace(out); } - close(); + cleanup(); + } + + /** + * Cleans up any resources held by this recorder entry at the end + * of a subbuild if it has been created for the subbuild's project + * instance. + * + * @param event the buildFinished event + * + * @since Ant 1.6.2 + */ + public void subBuildFinished(BuildEvent event) { + if (event.getProject() == project) { + cleanup(); + } + } + + /** + * Empty implementation to satisfy the BuildListener interface. + * + * @param event the buildStarted event + * + * @since Ant 1.6.2 + */ + public void subBuildStarted(BuildEvent event) { } @@ -209,11 +237,29 @@ } /** + * Set the project associated with this recorder entry. + * + * @param project the project instance + * * @since 1.6.2 */ - public void close() { + public void setProject(Project project) { + this.project = project; + if (project != null) { + project.addBuildListener(this); + } + } + + /** + * @since 1.6.2 + */ + public void cleanup() { out.flush(); out.close(); + if (project != null) { + project.removeBuildListener(this); + } + project = null; } }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]