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();
}
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) { }
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<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
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<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
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<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 vm {
@ -693,6 +756,8 @@ populateBuiltinMap(Thread* t, object map)
reinterpret_cast<void*>(::SystemClassLoader_findClass) },
{ "Java_java_lang_SystemClassLoader_findLoadedClass",
reinterpret_cast<void*>(::SystemClassLoader_findLoadedClass) },
{ "Java_java_lang_SystemClassLoader_resourceExists",
reinterpret_cast<void*>(::SystemClassLoader_resourceExists) },
{ "Java_java_lang_Runtime_loadLibrary",
reinterpret_cast<void*>(::Runtime_loadLibrary) },
@ -749,6 +814,15 @@ populateBuiltinMap(Thread* t, object map)
{ "Java_java_lang_reflect_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 }
};

View File

@ -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<char*>(s->allocate(al + bl + cl + dl + 1));
char* p = static_cast<char*>(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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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