diff --git a/src/main/org/apache/tools/ant/types/resources/AbstractClasspathResource.java b/src/main/org/apache/tools/ant/types/resources/AbstractClasspathResource.java index eb01eaed1..b70b5a785 100644 --- a/src/main/org/apache/tools/ant/types/resources/AbstractClasspathResource.java +++ b/src/main/org/apache/tools/ant/types/resources/AbstractClasspathResource.java @@ -172,6 +172,31 @@ public abstract class AbstractClasspathResource extends Resource { return ((Resource) getCheckedRef()).getInputStream(); } dieOnCircularReference(); + + final ClassLoaderWithFlag classLoader = getClassLoader(); + return !classLoader.needsCleanup() + ? openInputStream(classLoader.getLoader()) + : new FilterInputStream(openInputStream(classLoader.getLoader())) { + public void close() throws IOException { + FileUtils.close(in); + classLoader.cleanup(); + } + protected void finalize() throws Throwable { + try { + close(); + } finally { + super.finalize(); + } + } + }; + } + + /** + * combines the various ways that could specify a ClassLoader and + * potentially creates one that needs to be cleaned up when it is + * no longer needed so that classes can get garbage collected. + */ + protected ClassLoaderWithFlag getClassLoader() { ClassLoader cl = null; boolean clNeedsCleanup = false; if (loader != null) { @@ -196,23 +221,7 @@ public abstract class AbstractClasspathResource extends Resource { getProject().addReference(loader.getRefId(), cl); } } - - final ClassLoader classLoader = cl; - return !clNeedsCleanup - ? openInputStream(cl) - : new FilterInputStream(openInputStream(cl)) { - public void close() throws IOException { - FileUtils.close(in); - ((AntClassLoader) classLoader).cleanup(); - } - protected void finalize() throws Throwable { - try { - close(); - } finally { - super.finalize(); - } - } - }; + return new ClassLoaderWithFlag(cl, clNeedsCleanup); } /** @@ -237,4 +246,20 @@ public abstract class AbstractClasspathResource extends Resource { } } + public static class ClassLoaderWithFlag { + private final ClassLoader loader; + private final boolean cleanup; + + ClassLoaderWithFlag(ClassLoader l, boolean needsCleanup) { + loader = l; + cleanup = needsCleanup && l instanceof AntClassLoader; + } + public ClassLoader getLoader() { return loader; } + public boolean needsCleanup() { return cleanup; } + public void cleanup() { + if (cleanup) { + ((AntClassLoader) loader).cleanup(); + } + } + } } diff --git a/src/main/org/apache/tools/ant/types/resources/JavaResource.java b/src/main/org/apache/tools/ant/types/resources/JavaResource.java index 1d265c38b..ed15e96bc 100644 --- a/src/main/org/apache/tools/ant/types/resources/JavaResource.java +++ b/src/main/org/apache/tools/ant/types/resources/JavaResource.java @@ -20,6 +20,7 @@ package org.apache.tools.ant.types.resources; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.net.URL; import org.apache.tools.ant.types.Path; @@ -27,7 +28,8 @@ import org.apache.tools.ant.types.Path; * A Resource representation of something loadable via a Java classloader. * @since Ant 1.7 */ -public class JavaResource extends AbstractClasspathResource { +public class JavaResource extends AbstractClasspathResource + implements URLProvider { /** * Default constructor. @@ -48,8 +50,9 @@ public class JavaResource extends AbstractClasspathResource { } /** - * open the inpout stream from a specific classloader - * @param cl the classloader to use. Will be null if the system classloader is used + * open the input stream from a specific classloader + * @param cl the classloader to use. Will be null if the system + * classloader is used * @return an open input stream for the resource * @throws IOException if an error occurs. */ @@ -71,6 +74,27 @@ public class JavaResource extends AbstractClasspathResource { return inputStream; } + /** + * Get the URL represented by this Resource. + * @since Ant 1.8.0 + */ + public URL getURL() { + if (isReference()) { + return ((JavaResource) getCheckedRef()).getURL(); + } + AbstractClasspathResource.ClassLoaderWithFlag classLoader = + getClassLoader(); + if (classLoader.getLoader() == null) { + return ClassLoader.getSystemResource(getName()); + } else { + try { + return classLoader.getLoader().getResource(getName()); + } finally { + classLoader.cleanup(); + } + } + } + /** * Compare this JavaResource to another Resource. * @param another the other Resource against which to compare. diff --git a/src/tests/junit/org/apache/tools/ant/types/resources/JavaResourceTest.java b/src/tests/junit/org/apache/tools/ant/types/resources/JavaResourceTest.java index 697fee63d..d07a649cd 100644 --- a/src/tests/junit/org/apache/tools/ant/types/resources/JavaResourceTest.java +++ b/src/tests/junit/org/apache/tools/ant/types/resources/JavaResourceTest.java @@ -38,4 +38,15 @@ public class JavaResourceTest extends BuildFileTest { assertTrue(getProject().getProperty("manifest") .startsWith("Manifest-Version:")); } + + public void testIsURLProvider() { + JavaResource r = new JavaResource(); + assertSame(r, r.as(URLProvider.class)); + } + + public void testGetURLOfManifest() { + JavaResource r = new JavaResource(); + r.setName("META-INF/MANIFEST.MF"); + assertNotNull(r.getURL()); + } }