git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@796647 13f79535-47bb-0310-9956-ffa450edef68master
@@ -789,6 +789,14 @@ Other changes: | |||
task's (compiler) adapter class. | |||
Bugzilla Issue 11143. | |||
* A new subclass org.apache.tools.ant.loader.AntClassLoader5 of | |||
AntClassLoader has been added which overrides getResources | |||
which became non-final in ClassLoader with Java5+ so | |||
this method now behaves as expected. | |||
The new subclass will be used by Ant internally if it is available | |||
and Ant is running on Java5 or more recent. | |||
Bugzilla Issue 46752. | |||
Changes from Ant 1.7.0 TO Ant 1.7.1 | |||
============================================= | |||
@@ -175,6 +175,7 @@ | |||
<or> | |||
<filename name="${taskdefs.package}/AptTest*"/> | |||
<filename name="${util.package}/java15/*"/> | |||
<filename name="${ant.package}/loader/*5*"/> | |||
</or> | |||
</selector> | |||
@@ -46,6 +46,7 @@ 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; | |||
import org.apache.tools.ant.util.ReflectUtil; | |||
import org.apache.tools.ant.util.VectorSet; | |||
import org.apache.tools.ant.launch.Locator; | |||
@@ -910,6 +911,19 @@ public class AntClassLoader extends ClassLoader implements SubBuildListener { | |||
return url; | |||
} | |||
/** | |||
* Finds all the resources with the given name. A resource is some | |||
* data (images, audio, text, etc) that can be accessed by class | |||
* code in a way that is independent of the location of the code. | |||
* | |||
* <p>Would override getResources if that wasn't final in Java | |||
* 1.4.</p> | |||
*/ | |||
public Enumeration/*<URL>*/ getNamedResources(String name) | |||
throws IOException { | |||
return findResources(name, false); | |||
} | |||
/** | |||
* Returns an enumeration of URLs representing all the resources with the | |||
* given name by searching the class loader's classpath. | |||
@@ -920,14 +934,34 @@ public class AntClassLoader extends ClassLoader implements SubBuildListener { | |||
* @exception IOException if I/O errors occurs (can't happen) | |||
*/ | |||
protected Enumeration/*<URL>*/ findResources(String name) throws IOException { | |||
return findResources(name, true); | |||
} | |||
/** | |||
* Returns an enumeration of URLs representing all the resources with the | |||
* given name by searching the class loader's classpath. | |||
* | |||
* @param name The resource name to search for. | |||
* Must not be <code>null</code>. | |||
* @param parentHasBeenSearched whether ClassLoader.this.parent | |||
* has been searched - will be true if the method is (indirectly) | |||
* called from ClassLoader.getResources | |||
* @return an enumeration of URLs for the resources | |||
* @exception IOException if I/O errors occurs (can't happen) | |||
*/ | |||
protected Enumeration/*<URL>*/ findResources(String name, | |||
boolean parentHasBeenSearched) | |||
throws IOException { | |||
Enumeration/*<URL>*/ mine = new ResourceEnumeration(name); | |||
Enumeration/*<URL>*/ base; | |||
if (parent != null && parent != getParent()) { | |||
if (parent != null && (!parentHasBeenSearched || parent != getParent())) { | |||
// Delegate to the parent: | |||
base = parent.getResources(name); | |||
// Note: could cause overlaps in case ClassLoader.this.parent has matches. | |||
// Note: could cause overlaps in case | |||
// ClassLoader.this.parent has matches and | |||
// parentHasBeenSearched is true | |||
} else { | |||
// ClassLoader.this.parent is already delegated to from | |||
// ClassLoader.this.parent is already delegated to for example from | |||
// ClassLoader.getResources, no need: | |||
base = new CollectionUtils.EmptyEnumeration(); | |||
} | |||
@@ -1456,6 +1490,22 @@ public class AntClassLoader extends ClassLoader implements SubBuildListener { | |||
return "AntClassLoader[" + getClasspath() + "]"; | |||
} | |||
private static Class subClassToLoad = null; | |||
private static final Class[] CONSTRUCTOR_ARGS = new Class[] { | |||
ClassLoader.class, Project.class, Path.class, Boolean.TYPE | |||
}; | |||
static { | |||
if (JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_1_5)) { | |||
try { | |||
subClassToLoad = | |||
Class.forName("org.apache.tools.ant.loader.AntClassLoader5"); | |||
} catch (ClassNotFoundException e) { | |||
// this is Java5 but the installation is lacking our subclass | |||
} | |||
} | |||
} | |||
/** | |||
* Factory method | |||
*/ | |||
@@ -1463,6 +1513,15 @@ public class AntClassLoader extends ClassLoader implements SubBuildListener { | |||
Project project, | |||
Path path, | |||
boolean parentFirst) { | |||
if (subClassToLoad != null) { | |||
return (AntClassLoader) | |||
ReflectUtil.newInstance(subClassToLoad, | |||
CONSTRUCTOR_ARGS, | |||
new Object[] { | |||
parent, project, path, | |||
Boolean.valueOf(parentFirst) | |||
}); | |||
} | |||
return new AntClassLoader(parent, project, path, parentFirst); | |||
} | |||
@@ -0,0 +1,56 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one or more | |||
* contributor license agreements. See the NOTICE file distributed with | |||
* this work for additional information regarding copyright ownership. | |||
* The ASF licenses this file to You 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.loader; | |||
import java.util.Enumeration; | |||
import java.io.IOException; | |||
import org.apache.tools.ant.AntClassLoader; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.types.Path; | |||
/** | |||
* Overrides getResources which became non-final in Java5 | |||
*/ | |||
public class AntClassLoader5 extends AntClassLoader { | |||
/** | |||
* Creates a classloader for the given project using the classpath given. | |||
* | |||
* @param parent The parent classloader to which unsatisfied loading | |||
* attempts are delegated. May be <code>null</code>, | |||
* in which case the classloader which loaded this | |||
* class is used as the parent. | |||
* @param project The project to which this classloader is to belong. | |||
* Must not be <code>null</code>. | |||
* @param classpath the classpath to use to load the classes. | |||
* May be <code>null</code>, in which case no path | |||
* elements are set up to start with. | |||
* @param parentFirst If <code>true</code>, indicates that the parent | |||
* classloader should be consulted before trying to | |||
* load the a class through this loader. | |||
*/ | |||
public AntClassLoader5(ClassLoader parent, Project project, | |||
Path classpath, boolean parentFirst) { | |||
super(parent, project, classpath, parentFirst); | |||
} | |||
/** {@inheritDoc} */ | |||
public Enumeration getResources(String name) throws IOException { | |||
return getNamedResources(name); | |||
} | |||
} |
@@ -17,6 +17,7 @@ | |||
*/ | |||
package org.apache.tools.ant.util; | |||
import java.lang.reflect.Constructor; | |||
import java.lang.reflect.InvocationTargetException; | |||
import java.lang.reflect.Method; | |||
import org.apache.tools.ant.BuildException; | |||
@@ -35,6 +36,23 @@ public class ReflectUtil { | |||
private ReflectUtil() { | |||
} | |||
/** | |||
* Create an instance of a class using the constructor matching | |||
* the given arguments. | |||
* @since Ant 1.8.0 | |||
*/ | |||
public static Object newInstance(Class ofClass, | |||
Class[] argTypes, | |||
Object[] args) { | |||
try { | |||
Constructor con = ofClass.getConstructor(argTypes); | |||
return con.newInstance(args); | |||
} catch (Exception t) { | |||
throwBuildException(t); | |||
return null; // NotReached | |||
} | |||
} | |||
/** | |||
* Call a method on the object with no parameters. | |||
* @param obj the object to invoke the method on. | |||
@@ -99,12 +99,7 @@ public class AntClassLoaderDelegationTest extends TestCase { | |||
} | |||
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; | |||
return Collections.list(e); | |||
} | |||
/** Special loader that just knows how to find TEST_RESOURCE. */ | |||
@@ -0,0 +1,65 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one or more | |||
* contributor license agreements. See the NOTICE file distributed with | |||
* this work for additional information regarding copyright ownership. | |||
* The ASF licenses this file to You 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.loader; | |||
import java.io.IOException; | |||
import java.net.URL; | |||
import java.util.Enumeration; | |||
import junit.framework.TestCase; | |||
import org.apache.tools.ant.AntClassLoader; | |||
import org.apache.tools.ant.types.Path; | |||
import org.apache.tools.ant.util.CollectionUtils; | |||
public class AntClassLoader5Test extends TestCase { | |||
/** | |||
* Asserts that getResources won't return resources that cannot be | |||
* seen by AntClassLoader but by ClassLoader.this.parent. | |||
* | |||
* @see https://issues.apache.org/bugzilla/show_bug.cgi?id=46752 | |||
*/ | |||
public void testGetResources() throws IOException { | |||
AntClassLoader acl = new AntClassLoader5(new EmptyLoader(), null, | |||
new Path(null), true); | |||
assertNull(acl.getResource("META-INF/MANIFEST.MF")); | |||
assertFalse(acl.getResources("META-INF/MANIFEST.MF").hasMoreElements()); | |||
// double check using system classloader as parent | |||
acl = new AntClassLoader5(null, null, new Path(null), true); | |||
assertNotNull(acl.getResource("META-INF/MANIFEST.MF")); | |||
assertTrue(acl.getResources("META-INF/MANIFEST.MF").hasMoreElements()); | |||
} | |||
public void testGetResourcesUsingFactory() throws IOException { | |||
AntClassLoader acl = | |||
AntClassLoader.newAntClassLoader(new EmptyLoader(), null, | |||
new Path(null), true); | |||
assertNull(acl.getResource("META-INF/MANIFEST.MF")); | |||
assertFalse(acl.getResources("META-INF/MANIFEST.MF").hasMoreElements()); | |||
} | |||
private static class EmptyLoader extends ClassLoader { | |||
public URL getResource(String n) { | |||
return null; | |||
} | |||
public Enumeration getResources(String n) { | |||
return new CollectionUtils.EmptyEnumeration(); | |||
} | |||
} | |||
} |