Merge pull request #89 from dscho/get-resources

Support ClassLoader#getResources with multiple class path elements
This commit is contained in:
Joshua Warner 2013-11-04 16:29:40 -08:00
commit 790fcff73e
7 changed files with 111 additions and 13 deletions

View File

@ -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<URL> urls2 = findResources(name);
while (urls2.hasMoreElements()) {
urls.add(urls2.nextElement());
}
return Collections.enumeration(urls);
}
private class ResourceEnumeration implements Enumeration<URL> {
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<URL> findResources(String name) {
Collection<URL> urls = new ArrayList(1);
URL url = findResource(name);
if (url != null) {
urls.add(url);
}
return Collections.enumeration(urls);
return new ResourceEnumeration(name);
}
}

View File

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

View File

@ -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 $(<) $(@)

View File

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

View File

@ -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<object>(arguments[1]);
object name = reinterpret_cast<object>(arguments[2]);
object finderElementPtrPtr = reinterpret_cast<object>(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<void *&>(longArrayBody(t,
finderElementPtrPtr, 0));
const char* name = static_cast<Finder*>
(systemClassLoaderFinder(t, loader))->nextUrlPrefix(RUNTIME_ARRAY_BODY(n),
finderElementPtr);
return name ? reinterpret_cast<uintptr_t>(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)

View File

@ -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<Element*&>(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) {

View File

@ -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<URL> 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 { }