diff --git a/classpath/avian/SystemClassLoader.java b/classpath/avian/SystemClassLoader.java index 71759c7a54..ce9cdcd7a3 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) @@ -106,20 +107,51 @@ public class SystemClassLoader extends ClassLoader { } } - URL url = findResource(name); - if (url != null) { - urls.add(url); + Enumeration urls2 = findResources(name); + while (urls2.hasMoreElements()) { + urls.add(urls2.nextElement()); } return Collections.enumeration(urls); } + 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(); + } + + 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) { - Collection urls = new ArrayList(1); - URL url = findResource(name); - if (url != null) { - urls.add(url); - } - return Collections.enumeration(urls); + return new ResourceEnumeration(name); } } diff --git a/classpath/avian/jar/Handler.java b/classpath/avian/jar/Handler.java index 3b5f64fd5f..726f12e413 100644 --- a/classpath/avian/jar/Handler.java +++ b/classpath/avian/jar/Handler.java @@ -42,7 +42,7 @@ public class Handler extends URLStreamHandler { ("protocol " + file.getProtocol() + " not yet supported"); } - url.set("jar", "", -1, s, null); + url.set("jar", null, -1, s, null); } private static class MyJarURLConnection extends JarURLConnection { diff --git a/makefile b/makefile index c55ce91aed..113593478b 100755 --- a/makefile +++ b/makefile @@ -1487,13 +1487,20 @@ ifeq ($(continuations),true) $(build)/compile-x86-asm.o: $(src)/continuations-x86.$(asm-format) endif -$(build)/run-tests.sh: $(test-classes) makefile +$(build)/run-tests.sh: $(test-classes) makefile $(build)/extra-dir/multi-classpath-test.txt $(build)/test/multi-classpath-test.txt echo 'cd $$(dirname $$0)' > $(@) echo "sh ./test.sh 2>/dev/null \\" >> $(@) - echo "$(shell echo $(library-path) | sed 's|$(build)|\.|g') ./$(name)-unittest${exe-suffix} ./$(notdir $(test-executable)) $(mode) \"-Djava.library.path=. -cp test\" \\" >> $(@) + echo "$(shell echo $(library-path) | sed 's|$(build)|\.|g') ./$(name)-unittest${exe-suffix} ./$(notdir $(test-executable)) $(mode) \"-Djava.library.path=. -cp test:extra-dir\" \\" >> $(@) echo "$(call class-names,$(test-build),$(filter-out $(test-support-classes), $(test-classes))) \\" >> $(@) echo "$(continuation-tests) $(tail-tests)" >> $(@) +$(build)/extra-dir/multi-classpath-test.txt: + mkdir -p $(build)/extra-dir + echo "$@" > $@ + +$(build)/test/multi-classpath-test.txt: + echo "$@" > $@ + $(build)/test.sh: $(test)/test.sh cp $(<) $(@) diff --git a/src/avian/finder.h b/src/avian/finder.h index cf92044b72..c7fdbd547b 100644 --- a/src/avian/finder.h +++ b/src/avian/finder.h @@ -168,6 +168,7 @@ class Finder { unsigned* length, bool tryDirectory = false) = 0; virtual const char* urlPrefix(const char* name) = 0; + virtual const char* nextUrlPrefix(const char* name, void *&finderElementPtr) = 0; virtual const char* sourceUrl(const char* name) = 0; virtual const char* path() = 0; virtual void dispose() = 0; 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) diff --git a/src/finder.cpp b/src/finder.cpp index b170abc6e7..27969321ba 100644 --- a/src/finder.cpp +++ b/src/finder.cpp @@ -908,7 +908,16 @@ class MyFinder: public Finder { } virtual const char* urlPrefix(const char* name) { - for (Element* e = path_; e; e = e->next) { + void *finderElementPtr = NULL; + return nextUrlPrefix(name, finderElementPtr); + } + + virtual const char* nextUrlPrefix(const char* name, + void *&finderElementPtr) + { + Element *&e = reinterpret_cast(finderElementPtr); + e = e ? e->next : path_; + for (; e; e = e->next) { unsigned length; System::FileType type = e->stat(name, &length, true); if (type != System::TypeDoesNotExist) { diff --git a/test/Misc.java b/test/Misc.java index 91195d5f13..b0fde2d44b 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -1,3 +1,7 @@ +import java.io.IOException; +import java.net.URL; +import java.util.Enumeration; + public class Misc { private static class μClass { public int μField; @@ -262,6 +266,27 @@ public class Misc { expect((Protected.class.getModifiers() & java.lang.reflect.Modifier.PUBLIC) == 0); + + try { + int count = 0; + boolean test = false, extraDir = false; + ClassLoader loader = Misc.class.getClassLoader(); + Enumeration resources = loader.getResources("multi-classpath-test.txt"); + while (resources.hasMoreElements()) { + ++count; + String url = resources.nextElement().toString(); + if (url.contains("extra-dir")) { + extraDir = true; + } else if (url.contains("test")) { + test = true; + } + } + expect(count == 2); + expect(test); + expect(extraDir); + } catch (IOException e) { + throw new RuntimeException(e); + } } protected class Protected { }