flesh out resource URL scheme implementation

This commit is contained in:
Joel Dice 2007-08-10 17:45:47 -06:00
parent 2e9b9fe8d4
commit d3931b4853
15 changed files with 267 additions and 90 deletions

View File

@ -63,11 +63,15 @@ public class PrintStream extends OutputStream {
if (autoFlush) flush(); if (autoFlush) flush();
} }
public void flush() throws IOException { public void flush() {
out.flush(); try {
out.flush();
} catch (IOException e) { }
} }
public void close() throws IOException { public void close() {
out.close(); try {
out.close();
} catch (IOException e) { }
} }
} }

View File

@ -66,11 +66,15 @@ public class PrintWriter extends Writer {
if (autoFlush) flush(); if (autoFlush) flush();
} }
public void flush() throws IOException { public void flush() {
out.flush(); try {
out.flush();
} catch (IOException e) { }
} }
public void close() throws IOException { public void close() {
out.close(); try {
out.close();
} catch (IOException e) { }
} }
} }

View File

@ -1,5 +1,9 @@
package java.lang; package java.lang;
import java.io.InputStream;
import java.io.IOException;
import java.net.URL;
public abstract class ClassLoader { public abstract class ClassLoader {
private final ClassLoader parent; private final ClassLoader parent;
@ -75,4 +79,38 @@ public abstract class ClassLoader {
private ClassLoader getParent() { private ClassLoader getParent() {
return parent; 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);
}
} }

View File

@ -1,9 +1,23 @@
package java.lang; package java.lang;
import java.net.URL;
import java.net.MalformedURLException;
public class SystemClassLoader extends ClassLoader { public class SystemClassLoader extends ClassLoader {
private Object map; private Object map;
protected native Class findClass(String name) throws ClassNotFoundException; protected native Class findClass(String name) throws ClassNotFoundException;
protected native Class findLoadedClass(String name); 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;
}
} }

View File

@ -50,14 +50,14 @@ public class Throwable {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
printStackTrace(sb, System.getProperty("line.separator")); printStackTrace(sb, System.getProperty("line.separator"));
out.print(sb.toString()); out.print(sb.toString());
try { out.flush(); } catch (IOException e) { } out.flush();
} }
public void printStackTrace(PrintWriter out) { public void printStackTrace(PrintWriter out) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
printStackTrace(sb, System.getProperty("line.separator")); printStackTrace(sb, System.getProperty("line.separator"));
out.print(sb.toString()); out.print(sb.toString());
try { out.flush(); } catch (IOException e) { } out.flush();
} }
public void printStackTrace() { public void printStackTrace() {

View File

@ -1,6 +1,7 @@
package java.net; package java.net;
import java.io.IOException; import java.io.IOException;
import java.io.FileNotFoundException;
import java.io.InputStream; import java.io.InputStream;
public final class URL { public final class URL {
@ -46,8 +47,12 @@ public final class URL {
return handler.openConnection(this); return handler.openConnection(this);
} }
public InputStream openStream() throws IOException {
return openConnection().getInputStream();
}
public Object getContent() throws IOException { public Object getContent() throws IOException {
return openConnection().getContent(); return openStream();
} }
private static URLStreamHandler findHandler(String protocol) private static URLStreamHandler findHandler(String protocol)
@ -88,39 +93,62 @@ public final class URL {
private static class ResourceInputStream extends InputStream { private static class ResourceInputStream extends InputStream {
private long peer; private long peer;
private int position;
public ResourceInputStream(String path) throws IOException { public ResourceInputStream(String path) throws IOException {
peer = open(path); peer = open(path);
if (peer == 0) {
throw new FileNotFoundException(path);
}
} }
private static native long open(String path) throws IOException; 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; throws IOException;
public static native void close(long peer) throws IOException; public static native void close(long peer) throws IOException;
public int read() 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 { public int read(byte[] b, int offset, int length) throws IOException {
if (b == null) { if (peer != 0) {
throw new NullPointerException(); if (b == null) {
} throw new NullPointerException();
}
if (offset < 0 || offset + length > b.length) { if (offset < 0 || offset + length > b.length) {
throw new ArrayIndexOutOfBoundsException(); 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 { public void close() throws IOException {
close(peer); if (peer != 0) {
peer = 0; close(peer);
peer = 0;
}
} }
} }
} }

View File

@ -72,7 +72,7 @@ interpreter-depends = \
$(src)/common.h \ $(src)/common.h \
$(src)/system.h \ $(src)/system.h \
$(src)/heap.h \ $(src)/heap.h \
$(src)/class-finder.h \ $(src)/finder.h \
$(src)/stream.h \ $(src)/stream.h \
$(src)/constants.h \ $(src)/constants.h \
$(src)/run.h \ $(src)/run.h \
@ -82,7 +82,7 @@ interpreter-depends = \
interpreter-sources = \ interpreter-sources = \
$(src)/system.cpp \ $(src)/system.cpp \
$(src)/class-finder.cpp \ $(src)/finder.cpp \
$(src)/machine.cpp \ $(src)/machine.cpp \
$(src)/heap.cpp \ $(src)/heap.cpp \
$(src)/run.cpp \ $(src)/run.cpp \

View File

@ -58,28 +58,6 @@ Object_notifyAll(Thread* t, jobject this_)
vm::notifyAll(t, *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<char*>(&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 jclass
ClassLoader_defineClass(Thread* t, jclass, jbyteArray b, jint offset, ClassLoader_defineClass(Thread* t, jclass, jbyteArray b, jint offset,
jint length) jint length)
@ -91,16 +69,54 @@ ClassLoader_defineClass(Thread* t, jclass, jbyteArray b, jint offset,
return pushReference(t, c); 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<char*>(&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 jclass
SystemClassLoader_findLoadedClass(Thread* t, jclass, jstring name) SystemClassLoader_findLoadedClass(Thread* t, jclass, jstring name)
{ {
return search(t, name, findClass); return search(t, name, findLoadedClass, true);
} }
jclass jclass
SystemClassLoader_findClass(Thread* t, jclass, jstring name) 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 jclass
@ -665,6 +681,53 @@ Thread_interrupt(Thread* t, jclass, jlong peer)
interrupt(t, reinterpret_cast<Thread*>(peer)); interrupt(t, reinterpret_cast<Thread*>(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<jlong>(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<Finder::Data*>(peer);
if (position >= static_cast<jint>(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<Finder::Data*>(peer);
if (length > static_cast<jint>(d->length()) - position) {
length = static_cast<jint>(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<Finder::Data*>(peer)->dispose();
}
} // namespace } // namespace
namespace vm { namespace vm {
@ -693,6 +756,8 @@ populateBuiltinMap(Thread* t, object map)
reinterpret_cast<void*>(::SystemClassLoader_findClass) }, reinterpret_cast<void*>(::SystemClassLoader_findClass) },
{ "Java_java_lang_SystemClassLoader_findLoadedClass", { "Java_java_lang_SystemClassLoader_findLoadedClass",
reinterpret_cast<void*>(::SystemClassLoader_findLoadedClass) }, reinterpret_cast<void*>(::SystemClassLoader_findLoadedClass) },
{ "Java_java_lang_SystemClassLoader_resourceExists",
reinterpret_cast<void*>(::SystemClassLoader_resourceExists) },
{ "Java_java_lang_Runtime_loadLibrary", { "Java_java_lang_Runtime_loadLibrary",
reinterpret_cast<void*>(::Runtime_loadLibrary) }, reinterpret_cast<void*>(::Runtime_loadLibrary) },
@ -749,6 +814,15 @@ populateBuiltinMap(Thread* t, object map)
{ "Java_java_lang_reflect_Method_invoke", { "Java_java_lang_reflect_Method_invoke",
reinterpret_cast<void*>(::Method_invoke) }, reinterpret_cast<void*>(::Method_invoke) },
{ "Java_java_net_URL_00024ResourceInputStream_open",
reinterpret_cast<void*>(::ResourceInputStream_open) },
{ "Java_java_net_URL_00024ResourceInputStream_read_JI",
reinterpret_cast<void*>(::ResourceInputStream_read) },
{ "Java_java_net_URL_00024ResourceInputStream_read_JI_3BII",
reinterpret_cast<void*>(::ResourceInputStream_read2) },
{ "Java_java_net_URL_00024ResourceInputStream_close",
reinterpret_cast<void*>(::ResourceInputStream_close) },
{ 0, 0 } { 0, 0 }
}; };

View File

@ -4,25 +4,22 @@
#include "fcntl.h" #include "fcntl.h"
#include "system.h" #include "system.h"
#include "class-finder.h" #include "finder.h"
using namespace vm; using namespace vm;
namespace { namespace {
const char* const char*
append(System* s, const char* a, const char* b, const char* c, append(System* s, const char* a, const char* b, const char* c)
const char* d)
{ {
unsigned al = strlen(a); unsigned al = strlen(a);
unsigned bl = strlen(b); unsigned bl = strlen(b);
unsigned cl = strlen(c); unsigned cl = strlen(c);
unsigned dl = strlen(d); char* p = static_cast<char*>(s->allocate(al + bl + cl + 1));
char* p = static_cast<char*>(s->allocate(al + bl + cl + dl + 1));
memcpy(p, a, al); memcpy(p, a, al);
memcpy(p + al, b, bl); memcpy(p + al, b, bl);
memcpy(p + al + bl, c, cl); memcpy(p + al + bl, c, cl + 1);
memcpy(p + al + bl + cl, d, dl + 1);
return p; return p;
} }
@ -76,14 +73,14 @@ parsePath(System* s, const char* path)
return v; return v;
} }
class MyClassFinder: public ClassFinder { class MyFinder: public Finder {
public: public:
MyClassFinder(System* system, const char* path): MyFinder(System* system, const char* path):
system(system), system(system),
path(parsePath(system, path)) path(parsePath(system, path))
{ } { }
class Data: public ClassFinder::Data { class Data: public Finder::Data {
public: public:
Data(System* system, uint8_t* start, size_t length): Data(System* system, uint8_t* start, size_t length):
system(system), system(system),
@ -111,11 +108,11 @@ class MyClassFinder: public ClassFinder {
size_t length_; 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); Data* d = new (system->allocate(sizeof(Data))) Data(system, 0, 0);
for (const char** p = path; *p; ++p) { 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); int fd = open(file, O_RDONLY);
system->free(file); system->free(file);
@ -137,6 +134,20 @@ class MyClassFinder: public ClassFinder {
return 0; 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() { virtual void dispose() {
for (const char** p = path; *p; ++p) { for (const char** p = path; *p; ++p) {
system->free(*p); system->free(*p);
@ -154,10 +165,10 @@ class MyClassFinder: public ClassFinder {
namespace vm { namespace vm {
ClassFinder* Finder*
makeClassFinder(System* s, const char* path) 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 } // namespace vm

View File

@ -1,12 +1,12 @@
#ifndef CLASS_FINDER_H #ifndef FINDER_H
#define CLASS_FINDER_H #define FINDER_H
#include "common.h" #include "common.h"
#include "system.h" #include "system.h"
namespace vm { namespace vm {
class ClassFinder { class Finder {
public: public:
class Data { class Data {
public: public:
@ -16,14 +16,15 @@ class ClassFinder {
virtual void dispose() = 0; virtual void dispose() = 0;
}; };
virtual ~ClassFinder() { } virtual ~Finder() { }
virtual Data* find(const char* className) = 0; virtual Data* find(const char* name) = 0;
virtual bool exists(const char* name) = 0;
virtual void dispose() = 0; virtual void dispose() = 0;
}; };
ClassFinder* Finder*
makeClassFinder(System* s, const char* path); makeFinder(System* s, const char* path);
} // namespace vm } // namespace vm
#endif//CLASS_FINDER_H #endif//FINDER_H

View File

@ -1208,10 +1208,10 @@ removeString(Thread* t, object o)
namespace vm { namespace vm {
Machine::Machine(System* system, Heap* heap, ClassFinder* classFinder): Machine::Machine(System* system, Heap* heap, Finder* finder):
system(system), system(system),
heap(heap), heap(heap),
classFinder(classFinder), finder(finder),
rootThread(0), rootThread(0),
exclusive(0), exclusive(0),
activeCount(0), activeCount(0),
@ -2034,7 +2034,7 @@ primitiveSize(Thread* t, unsigned code)
} }
object object
findClass(Thread* t, object spec) findLoadedClass(Thread* t, object spec)
{ {
PROTECT(t, spec); PROTECT(t, spec);
ACQUIRE(t, t->vm->classLock); ACQUIRE(t, t->vm->classLock);
@ -2128,8 +2128,11 @@ resolveClass(Thread* t, object spec)
class_ = makeArrayClass(t, spec); class_ = makeArrayClass(t, spec);
} }
} else { } else {
ClassFinder::Data* data = t->vm->classFinder->find char file[byteArrayLength(t, spec) + 6];
(reinterpret_cast<const char*>(&byteArrayBody(t, spec, 0))); 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 (data) {
if (Verbose) { if (Verbose) {

View File

@ -4,7 +4,7 @@
#include "common.h" #include "common.h"
#include "system.h" #include "system.h"
#include "heap.h" #include "heap.h"
#include "class-finder.h" #include "finder.h"
#define JNICALL #define JNICALL
@ -1091,7 +1091,7 @@ class Machine {
#include "type-enums.cpp" #include "type-enums.cpp"
} Type; } Type;
Machine(System* system, Heap* heap, ClassFinder* classFinder); Machine(System* system, Heap* heap, Finder* finder);
~Machine() { ~Machine() {
dispose(); dispose();
@ -1101,7 +1101,7 @@ class Machine {
System* system; System* system;
Heap* heap; Heap* heap;
ClassFinder* classFinder; Finder* finder;
Thread* rootThread; Thread* rootThread;
Thread* exclusive; Thread* exclusive;
unsigned activeCount; unsigned activeCount;
@ -2052,7 +2052,7 @@ fieldSize(Thread* t, object field)
} }
object object
findClass(Thread* t, object spec); findLoadedClass(Thread* t, object spec);
object object
parseClass(Thread* t, const uint8_t* data, unsigned length); parseClass(Thread* t, const uint8_t* data, unsigned length);

View File

@ -1,7 +1,7 @@
#include "common.h" #include "common.h"
#include "system.h" #include "system.h"
#include "heap.h" #include "heap.h"
#include "class-finder.h" #include "finder.h"
#include "run.h" #include "run.h"
using namespace vm; using namespace vm;
@ -13,13 +13,13 @@ run(unsigned heapSize, const char* path, const char* class_, int argc,
const char** argv) const char** argv)
{ {
System* s = makeSystem(heapSize); System* s = makeSystem(heapSize);
ClassFinder* cf = makeClassFinder(s, path); Finder* f = makeFinder(s, path);
Heap* heap = makeHeap(s); Heap* heap = makeHeap(s);
int exitCode = run(s, heap, cf, class_, argc, argv); int exitCode = run(s, heap, f, class_, argc, argv);
heap->dispose(); heap->dispose();
cf->dispose(); f->dispose();
s->dispose(); s->dispose();
return exitCode; return exitCode;

View File

@ -1,7 +1,7 @@
#include "common.h" #include "common.h"
#include "system.h" #include "system.h"
#include "heap.h" #include "heap.h"
#include "class-finder.h" #include "finder.h"
#include "constants.h" #include "constants.h"
#include "run.h" #include "run.h"
#include "jnienv.h" #include "jnienv.h"
@ -2415,10 +2415,10 @@ run(Thread* t, const char* className, const char* methodName,
} }
int int
run(System* system, Heap* heap, ClassFinder* classFinder, run(System* system, Heap* heap, Finder* finder,
const char* className, int argc, const char** argv) 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); Thread* t = new (system->allocate(sizeof(Thread))) Thread(&m, 0, 0);
enter(t, Thread::ActiveState); enter(t, Thread::ActiveState);

View File

@ -3,7 +3,7 @@
#include "system.h" #include "system.h"
#include "heap.h" #include "heap.h"
#include "class-finder.h" #include "finder.h"
#include "machine.h" #include "machine.h"
namespace vm { namespace vm {
@ -19,7 +19,7 @@ run(Thread* t, const char* className, const char* methodName,
const char* methodSpec, object this_, ...); const char* methodSpec, object this_, ...);
int int
run(System* sys, Heap* heap, ClassFinder* classFinder, run(System* sys, Heap* heap, Finder* finder,
const char* className, int argc, const char** argv); const char* className, int argc, const char** argv);
} // namespace vm } // namespace vm