From 0602d4a44705dbdf8f13c1c2572b9a0beb019dd0 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 28 Oct 2013 08:52:58 -0500 Subject: [PATCH] Consider all class path elements in SystemClassLoader#findResources The findResources method is supposed to enumerate all the class path elements' matching paths' URLs, but we used to stop at the first one. While this is good enough when the system class path contains only a single .jar file, since b88438d2(sketch of JAR support in Finder) supports more than a single .jar file in the class path. Signed-off-by: Johannes Schindelin --- classpath/avian/SystemClassLoader.java | 44 ++++++++++++++++++++++---- src/builtin.cpp | 24 ++++++++++++++ 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/classpath/avian/SystemClassLoader.java b/classpath/avian/SystemClassLoader.java index 71759c7a54..afdee82ed3 100644 --- a/classpath/avian/SystemClassLoader.java +++ b/classpath/avian/SystemClassLoader.java @@ -17,6 +17,7 @@ import java.util.Collection; import java.util.Collections; import java.util.ArrayList; import java.util.Enumeration; +import java.util.NoSuchElementException; public class SystemClassLoader extends ClassLoader { private native VMClass findVMClass(String name) @@ -114,12 +115,43 @@ public class SystemClassLoader extends ClassLoader { return Collections.enumeration(urls); } - protected Enumeration findResources(String name) { - Collection urls = new ArrayList(1); - URL url = findResource(name); - if (url != null) { - urls.add(url); + private class ResourceEnumeration implements Enumeration { + private long[] finderElementPtrPtr; + private String name, urlPrefix; + + public ResourceEnumeration(String name) { + this.name = name; + finderElementPtrPtr = new long[1]; + urlPrefix = nextResourceURLPrefix(); } - return Collections.enumeration(urls); + + private native String nextResourceURLPrefix(SystemClassLoader loader, + String name, long[] finderElementPtrPtr); + + private String nextResourceURLPrefix() { + return nextResourceURLPrefix(SystemClassLoader.this, name, + finderElementPtrPtr); + } + + public boolean hasMoreElements() { + return urlPrefix != null; + } + + public URL nextElement() { + if (urlPrefix == null) throw new NoSuchElementException(); + URL result; + try { + result = new URL(urlPrefix + name); + } catch (MalformedURLException ignored) { + result = null; + } + if (finderElementPtrPtr[0] == 0l) urlPrefix = null; + else urlPrefix = nextResourceURLPrefix(); + return result; + } + } + + protected Enumeration findResources(String name) { + return new ResourceEnumeration(name); } } diff --git a/src/builtin.cpp b/src/builtin.cpp index f7f9a28d53..7fda369dbf 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -152,6 +152,30 @@ Avian_avian_SystemClassLoader_resourceURLPrefix } } +extern "C" JNIEXPORT int64_t JNICALL +Avian_avian_SystemClassLoader_00024ResourceEnumeration_nextResourceURLPrefix +(Thread* t, object, uintptr_t* arguments) +{ + object loader = reinterpret_cast(arguments[1]); + object name = reinterpret_cast(arguments[2]); + object finderElementPtrPtr = reinterpret_cast(arguments[3]); + + if (LIKELY(name) && LIKELY(finderElementPtrPtr)) { + THREAD_RUNTIME_ARRAY(t, char, n, stringLength(t, name) + 1); + stringChars(t, name, RUNTIME_ARRAY_BODY(n)); + + void *&finderElementPtr = reinterpret_cast(longArrayBody(t, + finderElementPtrPtr, 0)); + const char* name = static_cast + (systemClassLoaderFinder(t, loader))->nextUrlPrefix(RUNTIME_ARRAY_BODY(n), + finderElementPtr); + + return name ? reinterpret_cast(makeString(t, "%s", name)) : 0; + } else { + throwNew(t, Machine::NullPointerExceptionType); + } +} + extern "C" JNIEXPORT int64_t JNICALL Avian_avian_SystemClassLoader_getClass (Thread* t, object, uintptr_t* arguments)