rsitze 2002/12/12 14:35:40 Modified: discovery/src/test/org/apache/commons/discovery/test TestAll.java discovery build.xml discovery/sandbox/java/org/apache/commons/discovery/jdk JDK11Hooks.java JDK12Hooks.java discovery/src/java/org/apache/commons/discovery/jdk JDK12Hooks.java JDK11Hooks.java Added: discovery/src/testAlt2 testResource discovery/src/testAlt1 testResource discovery/src/test testResource Log: ClassLoader.getResources() is declared final in all current JDK specs. ClassLoaders that change expected behavior by searching parents last, instead of first, (as with some J2EE environments/settings) will then return a different result for the FIRST value of getResources() versus a call to getResource(). This can cause unexpected (and difficult to debug) behavior if the discovery mechanism is used to find ONE resource. Discovery abstracts the classloader behavior, so we use that abstraction to force the first value returned by 'getResources' to be the value returned by 'getResource'. Revision Changes Path 1.6 +56 -4 jakarta-commons/discovery/src/test/org/apache/commons/discovery/test/TestAll.java Index: TestAll.java =================================================================== RCS file: /home/cvs/jakarta-commons/discovery/src/test/org/apache/commons/discovery/test/TestAll.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- TestAll.java 12 Oct 2002 17:26:08 -0000 1.5 +++ TestAll.java 12 Dec 2002 22:35:39 -0000 1.6 @@ -63,22 +63,27 @@ package org.apache.commons.discovery.test; +import java.net.URL; import java.util.Properties; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; +import org.apache.commons.discovery.Resource; import org.apache.commons.discovery.ResourceClass; import org.apache.commons.discovery.ResourceClassIterator; +import org.apache.commons.discovery.ResourceIterator; +import org.apache.commons.discovery.jdk.JDKHooks; +import org.apache.commons.discovery.resource.ClassLoaders; +import org.apache.commons.discovery.resource.DiscoverResources; +import org.apache.commons.discovery.resource.classes.DiscoverClasses; import org.apache.commons.discovery.tools.DefaultClassHolder; import org.apache.commons.discovery.tools.DiscoverClass; import org.apache.commons.discovery.tools.DiscoverSingleton; import org.apache.commons.discovery.tools.ManagedProperties; import org.apache.commons.discovery.tools.PropertiesHolder; import org.apache.commons.discovery.tools.SPInterface; -import org.apache.commons.discovery.resource.ClassLoaders; -import org.apache.commons.discovery.resource.classes.DiscoverClasses; /** @@ -88,6 +93,7 @@ public class TestAll extends TestCase { private static final int logLevel = org.apache.commons.discovery.log.SimpleLog.LOG_LEVEL_INFO; +// org.apache.commons.discovery.log.SimpleLog.LOG_LEVEL_DEBUG; public TestAll(String testName) { @@ -243,7 +249,6 @@ } public void testFindServiceFileDefault() { -// org.apache.commons.discovery.log.SimpleLog.setLevel(org.apache.commons.discovery.log.SimpleLog.LOG_LEVEL_DEBUG); org.apache.commons.discovery.log.SimpleLog.setLevel(logLevel); TestInterface2 ti = null; @@ -262,6 +267,8 @@ } public void testLowLevelFind() { + org.apache.commons.discovery.log.SimpleLog.setLevel(logLevel); + ClassLoaders loaders = ClassLoaders.getAppLoaders(TestInterface2.class, getClass(), false); String name = "org.apache.commons.discovery.test.TestImpl2_1"; @@ -280,11 +287,56 @@ fail("Could not load service: " + resource ); } } - fail("failed to load resource: " + name); + fail("failed to load class resource: " + name); + } + + public void testFindResources() { + org.apache.commons.discovery.log.SimpleLog.setLevel(logLevel); + + ClassLoaders loaders = new ClassLoaders(); + + /** + * To many class loaders when searching for multiple + * resources means that we can find the same (same URL) + * resource for each loader... + * let's keep this to a minimum. + */ + ClassLoader cl = getClass().getClassLoader(); + if (cl != null) + loaders.put(getClass().getClassLoader(), true); + else + loaders.put(JDKHooks.getJDKHooks().getSystemClassLoader(), true); + + + String name = "testResource"; + + String partialPaths[] = { "/test/", "/testAlt1/", "/testAlt2/" }; + int expected = partialPaths.length; + + DiscoverResources discovery = new DiscoverResources(loaders); + ResourceIterator iter = discovery.findResources(name); + int count = 0; + while (iter.hasNext()) { + Resource resource = iter.nextResource(); + URL url = resource.getResource(); + if ( url != null ) { + System.out.println("URL = " + url.toString()); + + if (url.getFile().indexOf(partialPaths[count]) == -1) { + fail("expected to locate URL containing " + partialPaths[count]); + } + count++; + } + } + if (count != expected) { + fail("located " + count + " resources, failed to locate all " + expected + " resources: " + name); + } } public void testViaDiscoverClass() { + org.apache.commons.discovery.log.SimpleLog.setLevel(logLevel); + ClassLoaders loaders = ClassLoaders.getAppLoaders(TestInterface2.class, getClass(), false); DiscoverClass discover = new DiscoverClass(loaders); 1.9 +15 -4 jakarta-commons/discovery/build.xml Index: build.xml =================================================================== RCS file: /home/cvs/jakarta-commons/discovery/build.xml,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- build.xml 12 Sep 2002 16:31:14 -0000 1.8 +++ build.xml 12 Dec 2002 22:35:39 -0000 1.9 @@ -74,7 +74,12 @@ <!-- Construct unit test classpath --> <path id="test.classpath"> <pathelement location="${build.home}/classes"/> - <pathelement location="${build.home}/tests"/> + + <!-- test depends on the order of the following 3 lines: --> + <pathelement location="${build.home}/test"/> + <pathelement location="${build.home}/testAlt1"/> + <pathelement location="${build.home}/testAlt2"/> + <pathelement location="${logger.jar}"/> <pathelement location="${junit.jar}"/> </path> @@ -102,7 +107,7 @@ <mkdir dir="${build.home}/conf"/> <mkdir dir="${build.home}/docs"/> <mkdir dir="${build.home}/docs/api"/> - <mkdir dir="${build.home}/tests"/> + <mkdir dir="${build.home}/test"/> <tstamp/> <copy todir="${build.home}/conf" filtering="on"> <fileset dir="${conf.home}" includes="*.MF"/> @@ -172,14 +177,20 @@ <target name="compile.tests" depends="compile" description="Compile unit test cases"> <javac srcdir="${test.home}" - destdir="${build.home}/tests" + destdir="${build.home}/test" debug="${compile.debug}" deprecation="${compile.deprecation}" optimize="${compile.optimize}"> <classpath refid="test.classpath"/> </javac> - <copy todir="${build.home}/tests" filtering="on"> + <copy todir="${build.home}/test" filtering="on"> <fileset dir="${test.home}" excludes="**/*.java"/> + </copy> + <copy todir="${build.home}/testAlt1" filtering="on"> + <fileset dir="${test.home}/../testAlt1" excludes="**/*.java"/> + </copy> + <copy todir="${build.home}/testAlt2" filtering="on"> + <fileset dir="${test.home}/../testAlt2" excludes="**/*.java"/> </copy> </target> 1.2 +73 -2 jakarta-commons/discovery/sandbox/java/org/apache/commons/discovery/jdk/JDK11Hooks.java Index: JDK11Hooks.java =================================================================== RCS file: /home/cvs/jakarta-commons/discovery/sandbox/java/org/apache/commons/discovery/jdk/JDK11Hooks.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- JDK11Hooks.java 1 Sep 2002 04:12:48 -0000 1.1 +++ JDK11Hooks.java 12 Dec 2002 22:35:39 -0000 1.2 @@ -107,8 +107,79 @@ throws IOException { /** - * Not yet implemented... + * The simple answer is/was: + * return loader.getResources(resourceName); + * + * However, some classloaders overload the behavior of getResource + * (loadClass, etc) such that the order of returned results changes + * from normally expected behavior. + * + * Example: locate classes/resources from child ClassLoaders first, + * parents last (in some J2EE environs). + * + * The resource returned by getResource() should be the same as the + * first resource returned by getResources(). Unfortunately, this + * is not, and cannot be: getResources() is 'final' in the current + * JDK's (1.2, 1.3, 1.4). + * + * To address this, the implementation of this method will + * return an Enumeration such that the first element is the + * results of getResource, and all trailing elements are + * from getResources. On each iteration, we check so see + * if the resource (from getResources) matches the first resource, + * and eliminate the redundent element. */ - return null; + + final URL first = (URL)loader.getResource(resourceName); + final Enumeration rest = loader.getResources(resourceName); + + return new Enumeration() { + private boolean firstDone = (first == null); + private URL next = getNext(); + + public Object nextElement() { + URL o = next; + next = getNext(); + return o; + } + + public boolean hasMoreElements() { + return next != null; + } + + private URL getNext() { + URL n; + + if (!firstDone) { + /** + * First time through, use results of getReference() + * if they were non-null. + */ + firstDone = true; + n = first; + } else { + /** + * Subsequent times through, + * use results of getReferences() + * but take out anything that matches 'first'. + * + * Iterate through list until we find one that + * doesn't match 'first'. + */ + n = null; + while (rest.hasMoreElements() && n == null) { + n = (URL)rest.nextElement(); + if (first != null && + n != null && + n.equals(first)) + { + n = null; + } + } + } + + return n; + } + }; } } 1.2 +76 -2 jakarta-commons/discovery/sandbox/java/org/apache/commons/discovery/jdk/JDK12Hooks.java Index: JDK12Hooks.java =================================================================== RCS file: /home/cvs/jakarta-commons/discovery/sandbox/java/org/apache/commons/discovery/jdk/JDK12Hooks.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- JDK12Hooks.java 1 Sep 2002 04:12:48 -0000 1.1 +++ JDK12Hooks.java 12 Dec 2002 22:35:39 -0000 1.2 @@ -124,12 +124,86 @@ } /** - * Implement ClassLoader.getResources for JDK 1.1 + * Implement ClassLoader.getResources for JDK 1.2 */ public Enumeration getResources(ClassLoader loader, String resourceName) throws IOException { - return loader.getResources(resourceName); + /** + * The simple answer is/was: + * return loader.getResources(resourceName); + * + * However, some classloaders overload the behavior of getResource + * (loadClass, etc) such that the order of returned results changes + * from normally expected behavior. + * + * Example: locate classes/resources from child ClassLoaders first, + * parents last (in some J2EE environs). + * + * The resource returned by getResource() should be the same as the + * first resource returned by getResources(). Unfortunately, this + * is not, and cannot be: getResources() is 'final' in the current + * JDK's (1.2, 1.3, 1.4). + * + * To address this, the implementation of this method will + * return an Enumeration such that the first element is the + * results of getResource, and all trailing elements are + * from getResources. On each iteration, we check so see + * if the resource (from getResources) matches the first resource, + * and eliminate the redundent element. + */ + + final URL first = (URL)loader.getResource(resourceName); + final Enumeration rest = loader.getResources(resourceName); + + return new Enumeration() { + private boolean firstDone = (first == null); + private URL next = getNext(); + + public Object nextElement() { + URL o = next; + next = getNext(); + return o; + } + + public boolean hasMoreElements() { + return next != null; + } + + private URL getNext() { + URL n; + + if (!firstDone) { + /** + * First time through, use results of getReference() + * if they were non-null. + */ + firstDone = true; + n = first; + } else { + /** + * Subsequent times through, + * use results of getReferences() + * but take out anything that matches 'first'. + * + * Iterate through list until we find one that + * doesn't match 'first'. + */ + n = null; + while (rest.hasMoreElements() && n == null) { + n = (URL)rest.nextElement(); + if (first != null && + n != null && + n.equals(first)) + { + n = null; + } + } + } + + return n; + } + }; } } 1.2 +78 -3 jakarta-commons/discovery/src/java/org/apache/commons/discovery/jdk/JDK12Hooks.java Index: JDK12Hooks.java =================================================================== RCS file: /home/cvs/jakarta-commons/discovery/src/java/org/apache/commons/discovery/jdk/JDK12Hooks.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- JDK12Hooks.java 23 Aug 2002 00:15:25 -0000 1.1 +++ JDK12Hooks.java 12 Dec 2002 22:35:39 -0000 1.2 @@ -61,8 +61,9 @@ package org.apache.commons.discovery.jdk; -import java.util.Enumeration; import java.io.IOException; +import java.net.URL; +import java.util.Enumeration; /** @@ -124,12 +125,86 @@ } /** - * Implement ClassLoader.getResources for JDK 1.1 + * Implement ClassLoader.getResources for JDK 1.2 */ public Enumeration getResources(ClassLoader loader, String resourceName) throws IOException { - return loader.getResources(resourceName); + /** + * The simple answer is/was: + * return loader.getResources(resourceName); + * + * However, some classloaders overload the behavior of getResource + * (loadClass, etc) such that the order of returned results changes + * from normally expected behavior. + * + * Example: locate classes/resources from child ClassLoaders first, + * parents last (in some J2EE environs). + * + * The resource returned by getResource() should be the same as the + * first resource returned by getResources(). Unfortunately, this + * is not, and cannot be: getResources() is 'final' in the current + * JDK's (1.2, 1.3, 1.4). + * + * To address this, the implementation of this method will + * return an Enumeration such that the first element is the + * results of getResource, and all trailing elements are + * from getResources. On each iteration, we check so see + * if the resource (from getResources) matches the first resource, + * and eliminate the redundent element. + */ + + final URL first = (URL)loader.getResource(resourceName); + final Enumeration rest = loader.getResources(resourceName); + + return new Enumeration() { + private boolean firstDone = (first == null); + private URL next = getNext(); + + public Object nextElement() { + URL o = next; + next = getNext(); + return o; + } + + public boolean hasMoreElements() { + return next != null; + } + + private URL getNext() { + URL n; + + if (!firstDone) { + /** + * First time through, use results of getReference() + * if they were non-null. + */ + firstDone = true; + n = first; + } else { + /** + * Subsequent times through, + * use results of getReferences() + * but take out anything that matches 'first'. + * + * Iterate through list until we find one that + * doesn't match 'first'. + */ + n = null; + while (rest.hasMoreElements() && n == null) { + n = (URL)rest.nextElement(); + if (first != null && + n != null && + n.equals(first)) + { + n = null; + } + } + } + + return n; + } + }; } } 1.2 +75 -3 jakarta-commons/discovery/src/java/org/apache/commons/discovery/jdk/JDK11Hooks.java Index: JDK11Hooks.java =================================================================== RCS file: /home/cvs/jakarta-commons/discovery/src/java/org/apache/commons/discovery/jdk/JDK11Hooks.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- JDK11Hooks.java 23 Aug 2002 00:15:25 -0000 1.1 +++ JDK11Hooks.java 12 Dec 2002 22:35:39 -0000 1.2 @@ -61,8 +61,9 @@ package org.apache.commons.discovery.jdk; -import java.util.Enumeration; import java.io.IOException; +import java.net.URL; +import java.util.Enumeration; /** @@ -107,8 +108,79 @@ throws IOException { /** - * Not yet implemented... + * The simple answer is/was: + * return loader.getResources(resourceName); + * + * However, some classloaders overload the behavior of getResource + * (loadClass, etc) such that the order of returned results changes + * from normally expected behavior. + * + * Example: locate classes/resources from child ClassLoaders first, + * parents last (in some J2EE environs). + * + * The resource returned by getResource() should be the same as the + * first resource returned by getResources(). Unfortunately, this + * is not, and cannot be: getResources() is 'final' in the current + * JDK's (1.2, 1.3, 1.4). + * + * To address this, the implementation of this method will + * return an Enumeration such that the first element is the + * results of getResource, and all trailing elements are + * from getResources. On each iteration, we check so see + * if the resource (from getResources) matches the first resource, + * and eliminate the redundent element. */ - return null; + + final URL first = (URL)loader.getResource(resourceName); + final Enumeration rest = loader.getResources(resourceName); + + return new Enumeration() { + private boolean firstDone = (first == null); + private URL next = getNext(); + + public Object nextElement() { + URL o = next; + next = getNext(); + return o; + } + + public boolean hasMoreElements() { + return next != null; + } + + private URL getNext() { + URL n; + + if (!firstDone) { + /** + * First time through, use results of getReference() + * if they were non-null. + */ + firstDone = true; + n = first; + } else { + /** + * Subsequent times through, + * use results of getReferences() + * but take out anything that matches 'first'. + * + * Iterate through list until we find one that + * doesn't match 'first'. + */ + n = null; + while (rest.hasMoreElements() && n == null) { + n = (URL)rest.nextElement(); + if (first != null && + n != null && + n.equals(first)) + { + n = null; + } + } + } + + return n; + } + }; } } 1.1 jakarta-commons/discovery/src/testAlt2/testResource Index: testResource =================================================================== this is a resource for the test(s) to find.. 1.1 jakarta-commons/discovery/src/testAlt1/testResource Index: testResource =================================================================== this is a resource for the test(s) to find.. 1.1 jakarta-commons/discovery/src/test/testResource Index: testResource =================================================================== this is a resource for the test(s) to find..
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>