PR: 30161 Submitted by: Jesse Glick (jglick at netbeans dot org) git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@276721 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -48,6 +48,10 @@ Fixed bugs: | |||||
| * AbstractCvsTask prematurely closed its outputStream and errorStream. | * AbstractCvsTask prematurely closed its outputStream and errorStream. | ||||
| Bugzilla 30097. | Bugzilla 30097. | ||||
| * Impossible to use implicit classpath for <taskdef> | |||||
| when Ant core loader != Java application loader and Path.systemClassPath taken from ${java.class.path} | |||||
| Bugzilla 30161. | |||||
| Changes from Ant 1.6.1 to Ant 1.6.2 | Changes from Ant 1.6.1 to Ant 1.6.2 | ||||
| =================================== | =================================== | ||||
| @@ -1456,7 +1456,7 @@ | |||||
| <classpath refid="tests-classpath"/> | <classpath refid="tests-classpath"/> | ||||
| <sysproperty key="ant.home" value="${ant.home}"/> | <sysproperty key="ant.home" value="${ant.home}"/> | ||||
| <sysproperty key="build.tests" value="${build.tests}"/> | |||||
| <sysproperty key="build.tests" file="${build.tests}"/> | |||||
| <sysproperty key="build.tests.value" value="${build.tests.value}"/> | <sysproperty key="build.tests.value" value="${build.tests.value}"/> | ||||
| <sysproperty key="tests-classpath.value" | <sysproperty key="tests-classpath.value" | ||||
| value="${tests-classpath.value}"/> | value="${tests-classpath.value}"/> | ||||
| @@ -1606,7 +1606,7 @@ | |||||
| filtertrace="${junit.filtertrace}"> | filtertrace="${junit.filtertrace}"> | ||||
| <!-- <jvmarg value="-classic"/> --> | <!-- <jvmarg value="-classic"/> --> | ||||
| <sysproperty key="ant.home" value="${ant.home}"/> | <sysproperty key="ant.home" value="${ant.home}"/> | ||||
| <sysproperty key="build.tests" value="${build.tests}"/> | |||||
| <sysproperty key="build.tests" file="${build.tests}"/> | |||||
| <sysproperty key="build.tests.value" value="${build.tests.value}"/> | <sysproperty key="build.tests.value" value="${build.tests.value}"/> | ||||
| <sysproperty key="tests-classpath.value" | <sysproperty key="tests-classpath.value" | ||||
| value="${tests-classpath.value}"/> | value="${tests-classpath.value}"/> | ||||
| @@ -32,6 +32,7 @@ import java.util.Vector; | |||||
| import java.util.zip.ZipEntry; | import java.util.zip.ZipEntry; | ||||
| import java.util.zip.ZipFile; | import java.util.zip.ZipFile; | ||||
| import org.apache.tools.ant.types.Path; | import org.apache.tools.ant.types.Path; | ||||
| import org.apache.tools.ant.util.CollectionUtils; | |||||
| import org.apache.tools.ant.util.FileUtils; | import org.apache.tools.ant.util.FileUtils; | ||||
| import org.apache.tools.ant.util.JavaEnvUtils; | import org.apache.tools.ant.util.JavaEnvUtils; | ||||
| import org.apache.tools.ant.util.LoaderUtils; | import org.apache.tools.ant.util.LoaderUtils; | ||||
| @@ -864,8 +865,24 @@ public class AntClassLoader extends ClassLoader implements SubBuildListener { | |||||
| * @return an enumeration of URLs for the resources | * @return an enumeration of URLs for the resources | ||||
| * @exception IOException if I/O errors occurs (can't happen) | * @exception IOException if I/O errors occurs (can't happen) | ||||
| */ | */ | ||||
| protected Enumeration findResources(String name) throws IOException { | |||||
| return new ResourceEnumeration(name); | |||||
| protected Enumeration/*<URL>*/ findResources(String name) throws IOException { | |||||
| Enumeration/*<URL>*/ mine = new ResourceEnumeration(name); | |||||
| Enumeration/*<URL>*/ base; | |||||
| if (parent != null && parent != getParent()) { | |||||
| // Delegate to the parent: | |||||
| base = parent.getResources(name); | |||||
| // Note: could cause overlaps in case ClassLoader.this.parent has matches. | |||||
| } else { | |||||
| // ClassLoader.this.parent is already delegated to from ClassLoader.getResources, no need: | |||||
| base = new CollectionUtils.EmptyEnumeration(); | |||||
| } | |||||
| if (isParentFirst(name)) { | |||||
| // Normal case. | |||||
| return CollectionUtils.append(base, mine); | |||||
| } else { | |||||
| // Inverted. | |||||
| return CollectionUtils.append(mine, base); | |||||
| } | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -113,4 +113,39 @@ public class CollectionUtils { | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Append one enumeration to another. | |||||
| * Elements are evaluated lazily. | |||||
| * @param e1 the first enumeration | |||||
| * @param e2 the subsequent enumeration | |||||
| * @return an enumeration representing e1 followed by e2 | |||||
| * @since Ant 1.6.3 | |||||
| */ | |||||
| public static Enumeration append(Enumeration e1, Enumeration e2) { | |||||
| return new CompoundEnumeration(e1, e2); | |||||
| } | |||||
| private static final class CompoundEnumeration implements Enumeration { | |||||
| private final Enumeration e1, e2; | |||||
| public CompoundEnumeration(Enumeration e1, Enumeration e2) { | |||||
| this.e1 = e1; | |||||
| this.e2 = e2; | |||||
| } | |||||
| public boolean hasMoreElements() { | |||||
| return e1.hasMoreElements() || e2.hasMoreElements(); | |||||
| } | |||||
| public Object nextElement() throws NoSuchElementException { | |||||
| if (e1.hasMoreElements()) { | |||||
| return e1.nextElement(); | |||||
| } else { | |||||
| return e2.nextElement(); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||
| @@ -16,8 +16,20 @@ | |||||
| */ | */ | ||||
| package org.apache.tools.ant; | package org.apache.tools.ant; | ||||
| import org.apache.tools.ant.types.Path; | |||||
| import java.io.File; | |||||
| import java.io.IOException; | |||||
| import java.net.URL; | |||||
| import java.util.ArrayList; | |||||
| import java.util.Arrays; | |||||
| import java.util.Collections; | |||||
| import java.util.Enumeration; | |||||
| import java.util.List; | |||||
| import junit.framework.TestCase; | import junit.framework.TestCase; | ||||
| import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.Project; | |||||
| import org.apache.tools.ant.types.Path; | |||||
| import org.apache.tools.ant.util.FileUtils; | |||||
| /** | /** | ||||
| * Test case for ant class loader | * Test case for ant class loader | ||||
| @@ -70,5 +82,56 @@ public class AntClassLoaderTest extends TestCase { | |||||
| fail("loader should not fail even if project finished"); | fail("loader should not fail even if project finished"); | ||||
| } | } | ||||
| } | } | ||||
| /** Sample resource present in build/testcases/ */ | |||||
| private static final String TEST_RESOURCE = "org/apache/tools/ant/IncludeTest.class"; | |||||
| public void testFindResources() throws Exception { | |||||
| //System.err.println("loading from: " + AntClassLoader.class.getProtectionDomain().getCodeSource().getLocation()); | |||||
| // See bug #30161. | |||||
| // This path should contain the class files for these testcases: | |||||
| String buildTestcases = System.getProperty("build.tests"); | |||||
| assertNotNull("defined ${build.tests}", buildTestcases); | |||||
| assertTrue("have a dir " + buildTestcases, new File(buildTestcases).isDirectory()); | |||||
| Path path = new Path(p, buildTestcases); | |||||
| // A special parent loader which is not the system class loader: | |||||
| ClassLoader parent = new ParentLoader(); | |||||
| // An AntClassLoader which is supposed to delegate to the parent and then to the disk path: | |||||
| ClassLoader acl = new AntClassLoader(parent, p, path, true); | |||||
| // The intended result URLs: | |||||
| URL urlFromPath = new URL(FileUtils.newFileUtils().toURI(buildTestcases) + TEST_RESOURCE); | |||||
| URL urlFromParent = new URL("http://ant.apache.org/" + TEST_RESOURCE); | |||||
| assertEquals("correct resources (regular delegation order)", | |||||
| Arrays.asList(new URL[] {urlFromParent, urlFromPath}), | |||||
| enum2List(acl.getResources(TEST_RESOURCE))); | |||||
| acl = new AntClassLoader(parent, p, path, false); | |||||
| assertEquals("correct resources (reverse delegation order)", | |||||
| Arrays.asList(new URL[] {urlFromPath, urlFromParent}), | |||||
| enum2List(acl.getResources(TEST_RESOURCE))); | |||||
| } | |||||
| private static List enum2List(Enumeration e) { | |||||
| // JDK 1.4: return Collections.list(e); | |||||
| List l = new ArrayList(); | |||||
| while (e.hasMoreElements()) { | |||||
| l.add(e.nextElement()); | |||||
| } | |||||
| return l; | |||||
| } | |||||
| /** Special loader that just knows how to find TEST_RESOURCE. */ | |||||
| private static final class ParentLoader extends ClassLoader { | |||||
| public ParentLoader() {} | |||||
| protected Enumeration findResources(String name) throws IOException { | |||||
| if (name.equals(TEST_RESOURCE)) { | |||||
| return Collections.enumeration(Collections.singleton(new URL("http://ant.apache.org/" + name))); | |||||
| } else { | |||||
| return Collections.enumeration(Collections.EMPTY_SET); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||