Browse Source

override getResources in a new AntClassLoader subclass that will be used consistently when Ant is running on Java5+. PR 46752

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@796647 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 16 years ago
parent
commit
8ebe808f72
7 changed files with 211 additions and 9 deletions
  1. +8
    -0
      WHATSNEW
  2. +1
    -0
      build.xml
  3. +62
    -3
      src/main/org/apache/tools/ant/AntClassLoader.java
  4. +56
    -0
      src/main/org/apache/tools/ant/loader/AntClassLoader5.java
  5. +18
    -0
      src/main/org/apache/tools/ant/util/ReflectUtil.java
  6. +1
    -6
      src/tests/junit/org/apache/tools/ant/AntClassLoaderDelegationTest.java
  7. +65
    -0
      src/tests/junit/org/apache/tools/ant/loader/AntClassLoader5Test.java

+ 8
- 0
WHATSNEW View File

@@ -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
=============================================



+ 1
- 0
build.xml View File

@@ -175,6 +175,7 @@
<or>
<filename name="${taskdefs.package}/AptTest*"/>
<filename name="${util.package}/java15/*"/>
<filename name="${ant.package}/loader/*5*"/>
</or>
</selector>



+ 62
- 3
src/main/org/apache/tools/ant/AntClassLoader.java View File

@@ -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);
}


+ 56
- 0
src/main/org/apache/tools/ant/loader/AntClassLoader5.java View File

@@ -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);
}
}

+ 18
- 0
src/main/org/apache/tools/ant/util/ReflectUtil.java View File

@@ -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.


+ 1
- 6
src/tests/junit/org/apache/tools/ant/AntClassLoaderDelegationTest.java View File

@@ -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. */


+ 65
- 0
src/tests/junit/org/apache/tools/ant/loader/AntClassLoader5Test.java View File

@@ -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();
}
}
}

Loading…
Cancel
Save