Browse Source

Follow Conor's and Jose Alberto's advice - improved fix for PR 8689

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@276622 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 21 years ago
parent
commit
a22c8c09c8
6 changed files with 191 additions and 36 deletions
  1. +40
    -15
      src/main/org/apache/tools/ant/AntClassLoader.java
  2. +37
    -0
      src/main/org/apache/tools/ant/Project.java
  3. +57
    -0
      src/main/org/apache/tools/ant/SubBuildListener.java
  4. +7
    -17
      src/main/org/apache/tools/ant/taskdefs/Ant.java
  5. +1
    -1
      src/main/org/apache/tools/ant/taskdefs/Recorder.java
  6. +49
    -3
      src/main/org/apache/tools/ant/taskdefs/RecorderEntry.java

+ 40
- 15
src/main/org/apache/tools/ant/AntClassLoader.java View File

@@ -44,7 +44,7 @@ import org.apache.tools.ant.util.LoaderUtils;
* class will then use this loader rather than the system class loader. * 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(); private static final FileUtils fileUtils = FileUtils.newFileUtils();


@@ -118,7 +118,7 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
private void findNextResource() { private void findNextResource() {
URL url = null; URL url = null;
while ((pathElementsIndex < pathComponents.size()) while ((pathElementsIndex < pathComponents.size())
&& (url == null)) {
&& (url == null)) {
try { try {
File pathComponent File pathComponent
= (File) pathComponents.elementAt(pathElementsIndex); = (File) pathComponents.elementAt(pathElementsIndex);
@@ -222,7 +222,7 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
Class protectionDomain Class protectionDomain
= Class.forName("java.security.ProtectionDomain"); = Class.forName("java.security.ProtectionDomain");
Class[] args = new Class[] {String.class, byte[].class, Class[] args = new Class[] {String.class, byte[].class,
Integer.TYPE, Integer.TYPE, protectionDomain};
Integer.TYPE, Integer.TYPE, protectionDomain};
defineClassProtectionDomain defineClassProtectionDomain
= ClassLoader.class.getDeclaredMethod("defineClass", args); = ClassLoader.class.getDeclaredMethod("defineClass", args);
} catch (Exception e) { } catch (Exception e) {
@@ -392,9 +392,9 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
if (project != null) { if (project != null) {
project.log(message, priority); project.log(message, priority);
} }
// else {
// System.out.println(message);
// }
// else {
// System.out.println(message);
// }
} }


/** /**
@@ -442,7 +442,7 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
public void addPathElement(String pathElement) throws BuildException { public void addPathElement(String pathElement) throws BuildException {
File pathComponent File pathComponent
= project != null ? project.resolveFile(pathElement) = project != null ? project.resolveFile(pathElement)
: new File(pathElement);
: new File(pathElement);
try { try {
addPathFile(pathComponent); addPathFile(pathComponent);
} catch (IOException e) { } catch (IOException e) {
@@ -582,7 +582,7 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* on this loader's classpath. * on this loader's classpath.
*/ */
public Class forceLoadClass(String classname) public Class forceLoadClass(String classname)
throws ClassNotFoundException {
throws ClassNotFoundException {
log("force loading " + classname, Project.MSG_DEBUG); log("force loading " + classname, Project.MSG_DEBUG);


Class theClass = findLoadedClass(classname); Class theClass = findLoadedClass(classname);
@@ -611,7 +611,7 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* on this loader's classpath. * on this loader's classpath.
*/ */
public Class forceLoadSystemClass(String classname) public Class forceLoadSystemClass(String classname)
throws ClassNotFoundException {
throws ClassNotFoundException {
log("force system loading " + classname, Project.MSG_DEBUG); log("force system loading " + classname, Project.MSG_DEBUG);


Class theClass = findLoadedClass(classname); Class theClass = findLoadedClass(classname);
@@ -815,7 +815,7 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
URL url = null; URL url = null;
if (isParentFirst(name)) { if (isParentFirst(name)) {
url = (parent == null) ? super.getResource(name) url = (parent == null) ? super.getResource(name)
: parent.getResource(name);
: parent.getResource(name);
} }


if (url != null) { if (url != null) {
@@ -907,7 +907,7 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
if (entry != null) { if (entry != null) {
try { try {
return new URL("jar:" + fileUtils.getFileURL(file) return new URL("jar:" + fileUtils.getFileURL(file)
+ "!/" + entry);
+ "!/" + entry);
} catch (MalformedURLException ex) { } catch (MalformedURLException ex) {
return null; return null;
} }
@@ -941,7 +941,7 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* classpath. * classpath.
*/ */
protected synchronized Class loadClass(String classname, boolean resolve) protected synchronized Class loadClass(String classname, boolean resolve)
throws ClassNotFoundException {
throws ClassNotFoundException {
// 'sync' is needed - otherwise 2 threads can load the same class // 'sync' is needed - otherwise 2 threads can load the same class
// twice, resulting in LinkageError: duplicated class definition. // twice, resulting in LinkageError: duplicated class definition.
// findLoadedClass avoids that, but without sync it won't work. // findLoadedClass avoids that, but without sync it won't work.
@@ -1059,8 +1059,8 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* reading the class from the stream. * reading the class from the stream.
*/ */
private Class getClassFromStream(InputStream stream, String classname, private Class getClassFromStream(InputStream stream, String classname,
File container)
throws IOException, SecurityException {
File container)
throws IOException, SecurityException {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
int bytesRead = -1; int bytesRead = -1;
byte[] buffer = new byte[BUFFER_SIZE]; byte[] buffer = new byte[BUFFER_SIZE];
@@ -1120,7 +1120,7 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
* on this loader's classpath. * on this loader's classpath.
*/ */
private Class findClassInComponents(String name) private Class findClassInComponents(String name)
throws ClassNotFoundException {
throws ClassNotFoundException {
// we need to search the components of the path to see if // we need to search the components of the path to see if
// we can find the class we want. // we can find the class we want.
InputStream stream = null; InputStream stream = null;
@@ -1219,6 +1219,31 @@ public class AntClassLoader extends ClassLoader implements BuildListener {
cleanup(); 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) {
}

/** /**
* Empty implementation to satisfy the BuildListener interface. * Empty implementation to satisfy the BuildListener interface.
* *


+ 37
- 0
src/main/org/apache/tools/ant/Project.java View File

@@ -1790,6 +1790,43 @@ public class Project {
} }
} }


/**
* 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. * Sends a "target started" event to the build listeners for this project.


+ 57
- 0
src/main/org/apache/tools/ant/SubBuildListener.java View File

@@ -0,0 +1,57 @@
/*
* 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>&lt;ant&gt;</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);
}

+ 7
- 17
src/main/org/apache/tools/ant/taskdefs/Ant.java View File

@@ -379,32 +379,22 @@ public class Ant extends Task {
addReferences(); addReferences();


if (target != null && !"".equals(target)) { if (target != null && !"".equals(target)) {
Throwable t = null;
try { try {
log("Entering " + antFile + "...", Project.MSG_VERBOSE); log("Entering " + antFile + "...", Project.MSG_VERBOSE);
newProject.fireSubBuildStarted();
newProject.executeTarget(target); newProject.executeTarget(target);
} catch (BuildException ex) { } catch (BuildException ex) {
throw ProjectHelper.addLocationToBuildException(
ex, getLocation());
} finally {
t = ProjectHelper
.addLocationToBuildException(ex, getLocation());
throw (BuildException) t;
} finally {
log("Exiting " + antFile + ".", Project.MSG_VERBOSE); log("Exiting " + antFile + ".", Project.MSG_VERBOSE);
newProject.fireSubBuildFinished(t);
} }
} }
} finally { } finally {
// help the gc // 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; newProject = null;
Enumeration e = properties.elements(); Enumeration e = properties.elements();
while (e.hasMoreElements()) { while (e.hasMoreElements()) {


+ 1
- 1
src/main/org/apache/tools/ant/taskdefs/Recorder.java View File

@@ -211,7 +211,7 @@ public class Recorder extends Task {
throw new BuildException("Problems creating a recorder entry", throw new BuildException("Problems creating a recorder entry",
ioe); ioe);
} }
proj.addBuildListener(entry);
entry.setProject(proj);
recorderEntries.put(name, entry); recorderEntries.put(name, entry);
} else { } else {
entry = (RecorderEntry) o; entry = (RecorderEntry) o;


+ 49
- 3
src/main/org/apache/tools/ant/taskdefs/RecorderEntry.java View File

@@ -21,6 +21,7 @@ import org.apache.tools.ant.BuildEvent;
import org.apache.tools.ant.BuildLogger; import org.apache.tools.ant.BuildLogger;
import org.apache.tools.ant.DefaultLogger; import org.apache.tools.ant.DefaultLogger;
import org.apache.tools.ant.Project; import org.apache.tools.ant.Project;
import org.apache.tools.ant.SubBuildListener;
import org.apache.tools.ant.util.StringUtils; import org.apache.tools.ant.util.StringUtils;


/** /**
@@ -30,7 +31,7 @@ import org.apache.tools.ant.util.StringUtils;
* @version 0.5 * @version 0.5
* @since Ant 1.4 * @since Ant 1.4
*/ */
public class RecorderEntry implements BuildLogger {
public class RecorderEntry implements BuildLogger, SubBuildListener {


////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// ATTRIBUTES // ATTRIBUTES
@@ -47,6 +48,8 @@ public class RecorderEntry implements BuildLogger {
private long targetStartTime = 0L; private long targetStartTime = 0L;
/** Strip task banners if true. */ /** Strip task banners if true. */
private boolean emacsMode = false; private boolean emacsMode = false;
/** project instance the recorder is associated with */
private Project project;


////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// CONSTRUCTORS / INITIALIZERS // CONSTRUCTORS / INITIALIZERS
@@ -99,7 +102,32 @@ public class RecorderEntry implements BuildLogger {
+ StringUtils.LINE_SEP); + StringUtils.LINE_SEP);
error.printStackTrace(out); 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 @@ public class RecorderEntry implements BuildLogger {
} }


/** /**
* Set the project associated with this recorder entry.
*
* @param project the project instance
*
* @since 1.6.2 * @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.flush();
out.close(); out.close();
if (project != null) {
project.removeBuildListener(this);
}
project = null;
} }
} }



Loading…
Cancel
Save