diff --git a/classpath/java/io/PrintStream.java b/classpath/java/io/PrintStream.java index a63455af01..1e21d86ed3 100644 --- a/classpath/java/io/PrintStream.java +++ b/classpath/java/io/PrintStream.java @@ -63,11 +63,15 @@ public class PrintStream extends OutputStream { if (autoFlush) flush(); } - public void flush() throws IOException { - out.flush(); + public void flush() { + try { + out.flush(); + } catch (IOException e) { } } - public void close() throws IOException { - out.close(); + public void close() { + try { + out.close(); + } catch (IOException e) { } } } diff --git a/classpath/java/io/PrintWriter.java b/classpath/java/io/PrintWriter.java index 6ed4e02da4..b8829de24f 100644 --- a/classpath/java/io/PrintWriter.java +++ b/classpath/java/io/PrintWriter.java @@ -66,11 +66,15 @@ public class PrintWriter extends Writer { if (autoFlush) flush(); } - public void flush() throws IOException { - out.flush(); + public void flush() { + try { + out.flush(); + } catch (IOException e) { } } - public void close() throws IOException { - out.close(); + public void close() { + try { + out.close(); + } catch (IOException e) { } } } diff --git a/classpath/java/lang/ClassLoader.java b/classpath/java/lang/ClassLoader.java index c0b88fe669..6dab7a70a5 100644 --- a/classpath/java/lang/ClassLoader.java +++ b/classpath/java/lang/ClassLoader.java @@ -1,5 +1,9 @@ package java.lang; +import java.io.InputStream; +import java.io.IOException; +import java.net.URL; + public abstract class ClassLoader { private final ClassLoader parent; @@ -75,4 +79,38 @@ public abstract class ClassLoader { private ClassLoader getParent() { return parent; } + + protected URL findResource(String path) { + return null; + } + + public URL getResource(String path) { + URL url = null; + if (parent != null) { + url = parent.getResource(path); + } + + if (url == null) { + url = findResource(path); + } + + return url; + } + + public InputStream getResourceAsStream(String path) { + URL url = getResource(path); + try { + return (url == null ? null : url.openStream()); + } catch (IOException e) { + return null; + } + } + + public static URL getSystemResource(String path) { + return getSystemClassLoader().getResource(path); + } + + public static InputStream getSystemResourceAsStream(String path) { + return getSystemClassLoader().getResourceAsStream(path); + } } diff --git a/classpath/java/lang/SystemClassLoader.java b/classpath/java/lang/SystemClassLoader.java index 8603adc71f..9d223cce55 100644 --- a/classpath/java/lang/SystemClassLoader.java +++ b/classpath/java/lang/SystemClassLoader.java @@ -1,9 +1,23 @@ package java.lang; +import java.net.URL; +import java.net.MalformedURLException; + public class SystemClassLoader extends ClassLoader { private Object map; protected native Class findClass(String name) throws ClassNotFoundException; protected native Class findLoadedClass(String name); + + private native boolean resourceExists(String name); + + protected URL findResource(String name) { + if (resourceExists(name)) { + try { + return new URL("resource://" + name); + } catch (MalformedURLException ignored) { } + } + return null; + } } diff --git a/classpath/java/lang/Throwable.java b/classpath/java/lang/Throwable.java index 09632bc71f..50b79130e1 100644 --- a/classpath/java/lang/Throwable.java +++ b/classpath/java/lang/Throwable.java @@ -50,14 +50,14 @@ public class Throwable { StringBuilder sb = new StringBuilder(); printStackTrace(sb, System.getProperty("line.separator")); out.print(sb.toString()); - try { out.flush(); } catch (IOException e) { } + out.flush(); } public void printStackTrace(PrintWriter out) { StringBuilder sb = new StringBuilder(); printStackTrace(sb, System.getProperty("line.separator")); out.print(sb.toString()); - try { out.flush(); } catch (IOException e) { } + out.flush(); } public void printStackTrace() { diff --git a/classpath/java/net/URL.java b/classpath/java/net/URL.java index 2d25a7a060..3c8e447c6a 100644 --- a/classpath/java/net/URL.java +++ b/classpath/java/net/URL.java @@ -1,6 +1,7 @@ package java.net; import java.io.IOException; +import java.io.FileNotFoundException; import java.io.InputStream; public final class URL { @@ -46,8 +47,12 @@ public final class URL { return handler.openConnection(this); } + public InputStream openStream() throws IOException { + return openConnection().getInputStream(); + } + public Object getContent() throws IOException { - return openConnection().getContent(); + return openStream(); } private static URLStreamHandler findHandler(String protocol) @@ -88,39 +93,62 @@ public final class URL { private static class ResourceInputStream extends InputStream { private long peer; + private int position; public ResourceInputStream(String path) throws IOException { peer = open(path); + if (peer == 0) { + throw new FileNotFoundException(path); + } } private static native long open(String path) throws IOException; - private static native int read(long peer) throws IOException; + private static native int read(long peer, int position) throws IOException; - private static native int read(long peer, byte[] b, int offset, int length) + private static native int read(long peer, int position, + byte[] b, int offset, int length) throws IOException; public static native void close(long peer) throws IOException; public int read() throws IOException { - return read(peer); + if (peer != 0) { + int c = read(peer, position); + if (c >= 0) { + ++ position; + } + return c; + } else { + throw new IOException(); + } } public int read(byte[] b, int offset, int length) throws IOException { - if (b == null) { - throw new NullPointerException(); - } + if (peer != 0) { + if (b == null) { + throw new NullPointerException(); + } - if (offset < 0 || offset + length > b.length) { - throw new ArrayIndexOutOfBoundsException(); - } + if (offset < 0 || offset + length > b.length) { + throw new ArrayIndexOutOfBoundsException(); + } - return read(peer, b, offset, length); + int c = read(peer, position, b, offset, length); + if (c >= 0) { + position += c; + } + return c; + } else { + throw new IOException(); + } } public void close() throws IOException { - close(peer); - peer = 0; + if (peer != 0) { + close(peer); + peer = 0; + } } } } diff --git a/makefile b/makefile index c29bec3b08..be2562f2fb 100644 --- a/makefile +++ b/makefile @@ -72,7 +72,7 @@ interpreter-depends = \ $(src)/common.h \ $(src)/system.h \ $(src)/heap.h \ - $(src)/class-finder.h \ + $(src)/finder.h \ $(src)/stream.h \ $(src)/constants.h \ $(src)/run.h \ @@ -82,7 +82,7 @@ interpreter-depends = \ interpreter-sources = \ $(src)/system.cpp \ - $(src)/class-finder.cpp \ + $(src)/finder.cpp \ $(src)/machine.cpp \ $(src)/heap.cpp \ $(src)/run.cpp \ diff --git a/src/builtin.cpp b/src/builtin.cpp index 6bcae24db3..3dd77fff30 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -58,28 +58,6 @@ Object_notifyAll(Thread* t, jobject this_) vm::notifyAll(t, *this_); } -jclass -search(Thread* t, jstring name, object (*op)(Thread*, object)) -{ - if (LIKELY(name)) { - object n = makeByteArray(t, stringLength(t, *name) + 1, false); - char* s = reinterpret_cast(&byteArrayBody(t, n, 0)); - stringChars(t, *name, s); - - replace('.', '/', s); - - object c = op(t, n); - if (t->exception) { - return 0; - } - - return pushReference(t, c); - } else { - t->exception = makeNullPointerException(t); - return 0; - } -} - jclass ClassLoader_defineClass(Thread* t, jclass, jbyteArray b, jint offset, jint length) @@ -91,16 +69,54 @@ ClassLoader_defineClass(Thread* t, jclass, jbyteArray b, jint offset, return pushReference(t, c); } +jclass +search(Thread* t, jstring name, object (*op)(Thread*, object), + bool replaceDots) +{ + if (LIKELY(name)) { + object n = makeByteArray(t, stringLength(t, *name) + 1, false); + char* s = reinterpret_cast(&byteArrayBody(t, n, 0)); + stringChars(t, *name, s); + + if (replaceDots) { + replace('.', '/', s); + } + + object r = op(t, n); + if (t->exception) { + return 0; + } + + return pushReference(t, r); + } else { + t->exception = makeNullPointerException(t); + return 0; + } +} + jclass SystemClassLoader_findLoadedClass(Thread* t, jclass, jstring name) { - return search(t, name, findClass); + return search(t, name, findLoadedClass, true); } jclass SystemClassLoader_findClass(Thread* t, jclass, jstring name) { - return search(t, name, resolveClass); + return search(t, name, resolveClass, true); +} + +jboolean +SystemClassLoader_resourceExists(Thread* t, jclass, jstring name) +{ + if (LIKELY(name)) { + char n[stringLength(t, *name) + 1]; + stringChars(t, *name, n); + return t->vm->finder->exists(n); + } else { + t->exception = makeNullPointerException(t); + return 0; + } } jclass @@ -665,6 +681,53 @@ Thread_interrupt(Thread* t, jclass, jlong peer) interrupt(t, reinterpret_cast(peer)); } +jlong +ResourceInputStream_open(Thread* t, jclass, jstring path) +{ + if (LIKELY(path)) { + char p[stringLength(t, *path) + 1]; + stringChars(t, *path, p); + + return reinterpret_cast(t->vm->finder->find(p)); + } else { + t->exception = makeNullPointerException(t); + return 0; + } +} + +jint +ResourceInputStream_read(Thread*, jclass, jlong peer, jint position) +{ + Finder::Data* d = reinterpret_cast(peer); + if (position >= static_cast(d->length())) { + return -1; + } else { + return d->start()[position]; + } +} + +jint +ResourceInputStream_read2(Thread* t, jclass, jlong peer, jint position, + jbyteArray b, jint offset, jint length) +{ + Finder::Data* d = reinterpret_cast(peer); + if (length > static_cast(d->length()) - position) { + length = static_cast(d->length()) - position; + } + if (length < 0) { + return -1; + } else { + memcpy(&byteArrayBody(t, *b, offset), d->start() + position, length); + return length; + } +} + +void +ResourceInputStream_close(Thread*, jclass, jlong peer) +{ + reinterpret_cast(peer)->dispose(); +} + } // namespace namespace vm { @@ -693,6 +756,8 @@ populateBuiltinMap(Thread* t, object map) reinterpret_cast(::SystemClassLoader_findClass) }, { "Java_java_lang_SystemClassLoader_findLoadedClass", reinterpret_cast(::SystemClassLoader_findLoadedClass) }, + { "Java_java_lang_SystemClassLoader_resourceExists", + reinterpret_cast(::SystemClassLoader_resourceExists) }, { "Java_java_lang_Runtime_loadLibrary", reinterpret_cast(::Runtime_loadLibrary) }, @@ -749,6 +814,15 @@ populateBuiltinMap(Thread* t, object map) { "Java_java_lang_reflect_Method_invoke", reinterpret_cast(::Method_invoke) }, + { "Java_java_net_URL_00024ResourceInputStream_open", + reinterpret_cast(::ResourceInputStream_open) }, + { "Java_java_net_URL_00024ResourceInputStream_read_JI", + reinterpret_cast(::ResourceInputStream_read) }, + { "Java_java_net_URL_00024ResourceInputStream_read_JI_3BII", + reinterpret_cast(::ResourceInputStream_read2) }, + { "Java_java_net_URL_00024ResourceInputStream_close", + reinterpret_cast(::ResourceInputStream_close) }, + { 0, 0 } }; diff --git a/src/class-finder.cpp b/src/finder.cpp similarity index 76% rename from src/class-finder.cpp rename to src/finder.cpp index fffd356a3e..2a56f769ba 100644 --- a/src/class-finder.cpp +++ b/src/finder.cpp @@ -4,25 +4,22 @@ #include "fcntl.h" #include "system.h" -#include "class-finder.h" +#include "finder.h" using namespace vm; namespace { const char* -append(System* s, const char* a, const char* b, const char* c, - const char* d) +append(System* s, const char* a, const char* b, const char* c) { unsigned al = strlen(a); unsigned bl = strlen(b); unsigned cl = strlen(c); - unsigned dl = strlen(d); - char* p = static_cast(s->allocate(al + bl + cl + dl + 1)); + char* p = static_cast(s->allocate(al + bl + cl + 1)); memcpy(p, a, al); memcpy(p + al, b, bl); - memcpy(p + al + bl, c, cl); - memcpy(p + al + bl + cl, d, dl + 1); + memcpy(p + al + bl, c, cl + 1); return p; } @@ -76,14 +73,14 @@ parsePath(System* s, const char* path) return v; } -class MyClassFinder: public ClassFinder { +class MyFinder: public Finder { public: - MyClassFinder(System* system, const char* path): + MyFinder(System* system, const char* path): system(system), path(parsePath(system, path)) { } - class Data: public ClassFinder::Data { + class Data: public Finder::Data { public: Data(System* system, uint8_t* start, size_t length): system(system), @@ -111,11 +108,11 @@ class MyClassFinder: public ClassFinder { size_t length_; }; - virtual Data* find(const char* className) { + virtual Data* find(const char* name) { Data* d = new (system->allocate(sizeof(Data))) Data(system, 0, 0); for (const char** p = path; *p; ++p) { - const char* file = append(system, *p, "/", className, ".class"); + const char* file = append(system, *p, "/", name); int fd = open(file, O_RDONLY); system->free(file); @@ -137,6 +134,20 @@ class MyClassFinder: public ClassFinder { return 0; } + virtual bool exists(const char* name) { + for (const char** p = path; *p; ++p) { + const char* file = append(system, *p, "/", name); + struct stat s; + int r = stat(file, &s); + system->free(file); + if (r == 0) { + return true; + } + } + + return false; + } + virtual void dispose() { for (const char** p = path; *p; ++p) { system->free(*p); @@ -154,10 +165,10 @@ class MyClassFinder: public ClassFinder { namespace vm { -ClassFinder* -makeClassFinder(System* s, const char* path) +Finder* +makeFinder(System* s, const char* path) { - return new (s->allocate(sizeof(MyClassFinder))) MyClassFinder(s, path); + return new (s->allocate(sizeof(MyFinder))) MyFinder(s, path); } } // namespace vm diff --git a/src/class-finder.h b/src/finder.h similarity index 55% rename from src/class-finder.h rename to src/finder.h index 36f5d45eb9..02449a3a14 100644 --- a/src/class-finder.h +++ b/src/finder.h @@ -1,12 +1,12 @@ -#ifndef CLASS_FINDER_H -#define CLASS_FINDER_H +#ifndef FINDER_H +#define FINDER_H #include "common.h" #include "system.h" namespace vm { -class ClassFinder { +class Finder { public: class Data { public: @@ -16,14 +16,15 @@ class ClassFinder { virtual void dispose() = 0; }; - virtual ~ClassFinder() { } - virtual Data* find(const char* className) = 0; + virtual ~Finder() { } + virtual Data* find(const char* name) = 0; + virtual bool exists(const char* name) = 0; virtual void dispose() = 0; }; -ClassFinder* -makeClassFinder(System* s, const char* path); +Finder* +makeFinder(System* s, const char* path); } // namespace vm -#endif//CLASS_FINDER_H +#endif//FINDER_H diff --git a/src/machine.cpp b/src/machine.cpp index 91fb68bfaa..cdb651464b 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -1208,10 +1208,10 @@ removeString(Thread* t, object o) namespace vm { -Machine::Machine(System* system, Heap* heap, ClassFinder* classFinder): +Machine::Machine(System* system, Heap* heap, Finder* finder): system(system), heap(heap), - classFinder(classFinder), + finder(finder), rootThread(0), exclusive(0), activeCount(0), @@ -2034,7 +2034,7 @@ primitiveSize(Thread* t, unsigned code) } object -findClass(Thread* t, object spec) +findLoadedClass(Thread* t, object spec) { PROTECT(t, spec); ACQUIRE(t, t->vm->classLock); @@ -2128,8 +2128,11 @@ resolveClass(Thread* t, object spec) class_ = makeArrayClass(t, spec); } } else { - ClassFinder::Data* data = t->vm->classFinder->find - (reinterpret_cast(&byteArrayBody(t, spec, 0))); + char file[byteArrayLength(t, spec) + 6]; + memcpy(file, &byteArrayBody(t, spec, 0), byteArrayLength(t, spec) - 1); + memcpy(file + byteArrayLength(t, spec) - 1, ".class", 7); + + Finder::Data* data = t->vm->finder->find(file); if (data) { if (Verbose) { diff --git a/src/machine.h b/src/machine.h index 6a2da91c10..7573a96487 100644 --- a/src/machine.h +++ b/src/machine.h @@ -4,7 +4,7 @@ #include "common.h" #include "system.h" #include "heap.h" -#include "class-finder.h" +#include "finder.h" #define JNICALL @@ -1091,7 +1091,7 @@ class Machine { #include "type-enums.cpp" } Type; - Machine(System* system, Heap* heap, ClassFinder* classFinder); + Machine(System* system, Heap* heap, Finder* finder); ~Machine() { dispose(); @@ -1101,7 +1101,7 @@ class Machine { System* system; Heap* heap; - ClassFinder* classFinder; + Finder* finder; Thread* rootThread; Thread* exclusive; unsigned activeCount; @@ -2052,7 +2052,7 @@ fieldSize(Thread* t, object field) } object -findClass(Thread* t, object spec); +findLoadedClass(Thread* t, object spec); object parseClass(Thread* t, const uint8_t* data, unsigned length); diff --git a/src/main.cpp b/src/main.cpp index 8b2efc2168..caf3f65b09 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,7 @@ #include "common.h" #include "system.h" #include "heap.h" -#include "class-finder.h" +#include "finder.h" #include "run.h" using namespace vm; @@ -13,13 +13,13 @@ run(unsigned heapSize, const char* path, const char* class_, int argc, const char** argv) { System* s = makeSystem(heapSize); - ClassFinder* cf = makeClassFinder(s, path); + Finder* f = makeFinder(s, path); Heap* heap = makeHeap(s); - int exitCode = run(s, heap, cf, class_, argc, argv); + int exitCode = run(s, heap, f, class_, argc, argv); heap->dispose(); - cf->dispose(); + f->dispose(); s->dispose(); return exitCode; diff --git a/src/run.cpp b/src/run.cpp index 33d563de15..2a7b4df6a6 100644 --- a/src/run.cpp +++ b/src/run.cpp @@ -1,7 +1,7 @@ #include "common.h" #include "system.h" #include "heap.h" -#include "class-finder.h" +#include "finder.h" #include "constants.h" #include "run.h" #include "jnienv.h" @@ -2415,10 +2415,10 @@ run(Thread* t, const char* className, const char* methodName, } int -run(System* system, Heap* heap, ClassFinder* classFinder, +run(System* system, Heap* heap, Finder* finder, const char* className, int argc, const char** argv) { - Machine m(system, heap, classFinder); + Machine m(system, heap, finder); Thread* t = new (system->allocate(sizeof(Thread))) Thread(&m, 0, 0); enter(t, Thread::ActiveState); diff --git a/src/run.h b/src/run.h index eed6e8e7f1..837ec6a7aa 100644 --- a/src/run.h +++ b/src/run.h @@ -3,7 +3,7 @@ #include "system.h" #include "heap.h" -#include "class-finder.h" +#include "finder.h" #include "machine.h" namespace vm { @@ -19,7 +19,7 @@ run(Thread* t, const char* className, const char* methodName, const char* methodSpec, object this_, ...); int -run(System* sys, Heap* heap, ClassFinder* classFinder, +run(System* sys, Heap* heap, Finder* finder, const char* className, int argc, const char** argv); } // namespace vm