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. | |||
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 | |||
=================================== | |||
@@ -1456,7 +1456,7 @@ | |||
<classpath refid="tests-classpath"/> | |||
<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="tests-classpath.value" | |||
value="${tests-classpath.value}"/> | |||
@@ -1606,7 +1606,7 @@ | |||
filtertrace="${junit.filtertrace}"> | |||
<!-- <jvmarg value="-classic"/> --> | |||
<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="tests-classpath.value" | |||
value="${tests-classpath.value}"/> | |||
@@ -32,6 +32,7 @@ import java.util.Vector; | |||
import java.util.zip.ZipEntry; | |||
import java.util.zip.ZipFile; | |||
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.JavaEnvUtils; | |||
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 | |||
* @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; | |||
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 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 | |||
@@ -70,5 +82,56 @@ public class AntClassLoaderTest extends TestCase { | |||
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); | |||
} | |||
} | |||
} | |||
} | |||