diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index 8bc85a8e05..bfda2cb730 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -21,6 +21,7 @@ # define STRUCT_STAT struct _stat # define MKDIR(path, mode) _mkdir(path) # define CREAT _creat +# define UNLINK _unlink # define OPEN_MASK O_BINARY #else # include @@ -32,6 +33,7 @@ # define STRUCT_STAT struct stat # define MKDIR mkdir # define CREAT creat +# define UNLINK unlink # define OPEN_MASK 0 #endif @@ -150,6 +152,18 @@ Java_java_io_File_createNewFile(JNIEnv* e, jclass, jstring path) } } +extern "C" JNIEXPORT jboolean JNICALL +Java_java_io_File_delete(JNIEnv* e, jclass, jstring path) +{ + const char* chars = e->GetStringUTFChars(path, 0); + int r = -1; + if (chars) { + r = UNLINK(chars); + e->ReleaseStringUTFChars(path, chars); + } + return r == 0; +} + extern "C" JNIEXPORT jboolean JNICALL Java_java_io_File_exists(JNIEnv* e, jclass, jstring path) { diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index fd819c08f8..32bd0dec13 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -2,6 +2,7 @@ #include "time.h" #include "time.h" #include "string.h" +#include "stdio.h" #include "jni.h" #include "jni-util.h" @@ -37,3 +38,20 @@ Java_java_lang_System_currentTimeMillis(JNIEnv*, jclass) return (static_cast(tv.tv_sec) * 1000) + (static_cast(tv.tv_usec) / 1000); } + +extern "C" JNIEXPORT jstring JNICALL +Java_java_lang_System_doMapLibraryName(JNIEnv* e, jclass, jstring name) +{ + jstring r = 0; + const char* chars = e->GetStringUTFChars(name, 0); + if (chars) { + unsigned nameLength = strlen(chars); + unsigned size = nameLength + 7; + char buffer[size]; + snprintf(buffer, size, "lib%s.so", chars); + r = e->NewStringUTF(buffer); + + e->ReleaseStringUTFChars(name, chars); + } + return r; +} diff --git a/classpath/java/io/File.java b/classpath/java/io/File.java index eb6b2707e3..e850c7d832 100644 --- a/classpath/java/io/File.java +++ b/classpath/java/io/File.java @@ -86,4 +86,10 @@ public class File { public void createNewFile() { createNewFile(path); } + + public static native boolean delete(String path); + + public boolean delete() { + return delete(path); + } } diff --git a/classpath/java/io/UnsupportedEncodingException.java b/classpath/java/io/UnsupportedEncodingException.java new file mode 100644 index 0000000000..75cc82a29b --- /dev/null +++ b/classpath/java/io/UnsupportedEncodingException.java @@ -0,0 +1,11 @@ +package java.io; + +public class UnsupportedEncodingException extends IOException { + public UnsupportedEncodingException(String message) { + super(message); + } + + public UnsupportedEncodingException() { + this(null); + } +} diff --git a/classpath/java/lang/Character.java b/classpath/java/lang/Character.java index 765f005042..859600ca2f 100644 --- a/classpath/java/lang/Character.java +++ b/classpath/java/lang/Character.java @@ -57,6 +57,10 @@ public final class Character { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } + public static boolean isLetterOrDigit(char c) { + return isDigit(c) || isLetter(c); + } + public static boolean isLowerCase(char c) { return (c >= 'a' && c <= 'z'); } @@ -68,4 +72,8 @@ public final class Character { public static boolean isWhitespace(char c) { return c == ' ' || c == '\t' || c == '\n'; } + + public static boolean isSpaceChar(char c) { + return isWhitespace(c); + } } diff --git a/classpath/java/lang/Class.java b/classpath/java/lang/Class.java index a040853222..e2856e5ea3 100644 --- a/classpath/java/lang/Class.java +++ b/classpath/java/lang/Class.java @@ -5,6 +5,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.lang.reflect.InvocationTargetException; +import java.io.InputStream; public final class Class { private static final int PrimitiveFlag = 1 << 4; @@ -353,4 +354,11 @@ public final class Class { public boolean isPrimitive() { return (vmFlags & PrimitiveFlag) != 0; } + + public InputStream getResourceAsStream(String path) { + if (! path.startsWith("/")) { + path = new String(name, 0, name.length - 1, false) + "/" + path; + } + return getClassLoader().getResourceAsStream(path); + } } diff --git a/classpath/java/lang/Float.java b/classpath/java/lang/Float.java index 1c0779de09..b563a69bf4 100644 --- a/classpath/java/lang/Float.java +++ b/classpath/java/lang/Float.java @@ -53,6 +53,11 @@ public final class Float extends Number { return (double) value; } + public static float parseFloat(String s) { + // todo + throw new NumberFormatException(s); + } + public static native int floatToRawIntBits(float value); public static native float intBitsToFloat(int bits); diff --git a/classpath/java/lang/Math.java b/classpath/java/lang/Math.java index 51a74cdb32..ab753441c1 100644 --- a/classpath/java/lang/Math.java +++ b/classpath/java/lang/Math.java @@ -1,6 +1,9 @@ package java.lang; public final class Math { + public static final double E = 2.718281828459045; + public static final double PI = 3.141592653589793; + private Math() { } public static double max(double a, double b) { diff --git a/classpath/java/lang/Runtime.java b/classpath/java/lang/Runtime.java index 0becbacf05..8854949f68 100644 --- a/classpath/java/lang/Runtime.java +++ b/classpath/java/lang/Runtime.java @@ -9,7 +9,23 @@ public class Runtime { return instance; } - public native void loadLibrary(String name); + public void load(String path) { + if (path != null) { + load(path, false); + } else { + throw new NullPointerException(); + } + } + + public void loadLibrary(String path) { + if (path != null) { + load(path, true); + } else { + throw new NullPointerException(); + } + } + + private static native void load(String name, boolean mapName); public native void gc(); diff --git a/classpath/java/lang/String.java b/classpath/java/lang/String.java index db4d669a20..54950aa1fe 100644 --- a/classpath/java/lang/String.java +++ b/classpath/java/lang/String.java @@ -294,6 +294,10 @@ public final class String implements Comparable { return b; } + public byte[] getBytes(String format) { + return getBytes(); + } + public void getChars(int srcOffset, int srcLength, char[] dst, int dstOffset) { diff --git a/classpath/java/lang/System.java b/classpath/java/lang/System.java index 80d0367639..ef0ff78435 100644 --- a/classpath/java/lang/System.java +++ b/classpath/java/lang/System.java @@ -13,8 +13,9 @@ public abstract class System { private static final int JavaClassPath = 1; private static final int LineSeparator = 100; private static final int OsName = 101; - + private static Property properties; + static { loadLibrary("natives"); } @@ -32,6 +33,12 @@ public abstract class System { int dstOffset, int length); public static String getProperty(String name) { + for (Property p = properties; p != null; p = p.next) { + if (p.name.equals(name)) { + return p.value; + } + } + int code = Unknown; if (name.equals("java.class.path")) { code = JavaClassPath; @@ -50,6 +57,17 @@ public abstract class System { } } + public static void setProperty(String name, String value) { + for (Property p = properties; p != null; p = p.next) { + if (p.name.equals(name)) { + p.value = value; + return; + } + } + + properties = new Property(name, value, properties); + } + private static native String getProperty(int code); private static native String getVMProperty(int code); @@ -58,6 +76,20 @@ public abstract class System { public static native int identityHashCode(Object o); + public static String mapLibraryName(String name) { + if (name != null) { + return doMapLibraryName(name); + } else { + throw new NullPointerException(); + } + } + + private static native String doMapLibraryName(String name); + + public static void load(String path) { + Runtime.getRuntime().load(path); + } + public static void loadLibrary(String name) { Runtime.getRuntime().loadLibrary(name); } @@ -69,4 +101,16 @@ public abstract class System { public static void exit(int code) { Runtime.getRuntime().exit(code); } + + private static class Property { + public final String name; + public String value; + public final Property next; + + public Property(String name, String value, Property next) { + this.name = name; + this.value = value; + this.next = next; + } + } } diff --git a/classpath/java/text/DateFormatSymbols.java b/classpath/java/text/DateFormatSymbols.java new file mode 100644 index 0000000000..05408757f5 --- /dev/null +++ b/classpath/java/text/DateFormatSymbols.java @@ -0,0 +1,5 @@ +package java.text; + +public class DateFormatSymbols { + +} diff --git a/classpath/java/text/FieldPosition.java b/classpath/java/text/FieldPosition.java new file mode 100644 index 0000000000..ecbcbe493f --- /dev/null +++ b/classpath/java/text/FieldPosition.java @@ -0,0 +1,5 @@ +package java.text; + +public class FieldPosition { + public FieldPosition(int field) { } +} diff --git a/classpath/java/text/Format.java b/classpath/java/text/Format.java new file mode 100644 index 0000000000..43c8b859e3 --- /dev/null +++ b/classpath/java/text/Format.java @@ -0,0 +1,10 @@ +package java.text; + +public abstract class Format { + public final String format(Object o) { + return format(o, new StringBuffer(), new FieldPosition(0)).toString(); + } + + public abstract StringBuffer format(Object o, StringBuffer target, + FieldPosition p); +} diff --git a/classpath/java/text/MessageFormat.java b/classpath/java/text/MessageFormat.java new file mode 100644 index 0000000000..0a2147a596 --- /dev/null +++ b/classpath/java/text/MessageFormat.java @@ -0,0 +1,22 @@ +package java.text; + +import java.util.Locale; + +public class MessageFormat extends Format { + private final String pattern; + private final Locale locale; + + public MessageFormat(String pattern, Locale locale) { + this.pattern = pattern; + this.locale = locale; + } + + public MessageFormat(String pattern) { + this(pattern, Locale.getDefault()); + } + + public StringBuffer format(Object o, StringBuffer target, FieldPosition p) { + // todo + return target.append(pattern); + } +} diff --git a/classpath/java/util/Calendar.java b/classpath/java/util/Calendar.java new file mode 100644 index 0000000000..66f3145f22 --- /dev/null +++ b/classpath/java/util/Calendar.java @@ -0,0 +1,14 @@ +package java.util; + +public abstract class Calendar { + public static final int AM = 0; + public static final int AM_PM = 9; + public static final int DAY_OF_MONTH = 5; + public static final int HOUR = 10; + public static final int HOUR_OF_DAY = 11; + public static final int MINUTE = 12; + public static final int MONTH = 2; + public static final int PM = 1; + public static final int SECOND = 13; + public static final int YEAR = 1; +} diff --git a/classpath/java/util/EventListener.java b/classpath/java/util/EventListener.java new file mode 100644 index 0000000000..cf6d580b9b --- /dev/null +++ b/classpath/java/util/EventListener.java @@ -0,0 +1,5 @@ +package java.util; + +public interface EventListener { + +} diff --git a/classpath/java/util/EventObject.java b/classpath/java/util/EventObject.java new file mode 100644 index 0000000000..be9a8d03d3 --- /dev/null +++ b/classpath/java/util/EventObject.java @@ -0,0 +1,13 @@ +package java.util; + +public class EventObject { + protected Object source; + + public EventObject(Object source) { + this.source = source; + } + + public Object getSource() { + return source; + } +} diff --git a/classpath/java/util/Locale.java b/classpath/java/util/Locale.java new file mode 100644 index 0000000000..4ff08dea6b --- /dev/null +++ b/classpath/java/util/Locale.java @@ -0,0 +1,39 @@ +package java.util; + +public class Locale { + public static final Locale ENGLISH = new Locale("en"); + + private final String language; + private final String country; + private final String variant; + + public Locale(String language, String country, String variant) { + this.language = language; + this.country = country; + this.variant = variant; + } + + public Locale(String language, String country) { + this(language, country, null); + } + + public Locale(String language) { + this(language, null); + } + + public String getLanguage() { + return language; + } + + public String getCountry() { + return country; + } + + public String getVariant() { + return variant; + } + + public static Locale getDefault() { + return ENGLISH; + } +} diff --git a/classpath/java/util/MissingResourceException.java b/classpath/java/util/MissingResourceException.java new file mode 100644 index 0000000000..59df882915 --- /dev/null +++ b/classpath/java/util/MissingResourceException.java @@ -0,0 +1,20 @@ +package java.util; + +public class MissingResourceException extends RuntimeException { + private final String class_; + private final String key; + + public MissingResourceException(String message, String class_, String key) { + super(message); + this.class_ = class_; + this.key = key; + } + + public String getClassName() { + return class_; + } + + public String getKey() { + return key; + } +} diff --git a/classpath/java/util/ResourceBundle.java b/classpath/java/util/ResourceBundle.java new file mode 100644 index 0000000000..6a20ee9446 --- /dev/null +++ b/classpath/java/util/ResourceBundle.java @@ -0,0 +1,5 @@ +package java.util; + +public abstract class ResourceBundle { + +} diff --git a/classpath/java/util/zip/InflaterInputStream.java b/classpath/java/util/zip/InflaterInputStream.java new file mode 100644 index 0000000000..5288fa2596 --- /dev/null +++ b/classpath/java/util/zip/InflaterInputStream.java @@ -0,0 +1,20 @@ +package java.util.zip; + +import java.io.InputStream; +import java.io.IOException; + +public class InflaterInputStream extends InputStream { + private final InputStream in; + + public InflaterInputStream(InputStream in) { + this.in = in; + } + + public int read() throws IOException { + throw new IOException("not implemented"); + } + + public void close() throws IOException { + in.close(); + } +} diff --git a/src/builtin.cpp b/src/builtin.cpp index 1f0bcfc301..50630651bc 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -400,30 +400,26 @@ System_identityHashCode(Thread* t, jclass, jobject o) } void JNICALL -Runtime_loadLibrary(Thread* t, jobject, jstring name) +Runtime_load(Thread* t, jclass, jstring name, jboolean mapName) { - if (LIKELY(name)) { - char n[stringLength(t, *name) + 1]; - stringChars(t, *name, n); + char n[stringLength(t, *name) + 1]; + stringChars(t, *name, n); - for (System::Library* lib = t->vm->libraries; lib; lib = lib->next()) { - if (::strcmp(lib->name(), n) == 0) { - // already loaded - return; - } + for (System::Library* lib = t->vm->libraries; lib; lib = lib->next()) { + if (lib->matches(n, mapName)) { + // already loaded + return; } + } - System::Library* lib; - if (LIKELY(t->vm->system->success - (t->vm->system->load(&lib, n, t->vm->libraries)))) - { - t->vm->libraries = lib; - } else { - object message = makeString(t, "library not found: %s", n); - t->exception = makeRuntimeException(t, message); - } + System::Library* lib; + if (LIKELY(t->vm->system->success + (t->vm->system->load(&lib, n, mapName, t->vm->libraries)))) + { + t->vm->libraries = lib; } else { - t->exception = makeNullPointerException(t); + object message = makeString(t, "library not found: %s", n); + t->exception = makeRuntimeException(t, message); } } @@ -613,8 +609,8 @@ populateBuiltinMap(Thread* t, object map) { "Java_java_lang_SystemClassLoader_resourceExists", reinterpret_cast(::SystemClassLoader_resourceExists) }, - { "Java_java_lang_Runtime_loadLibrary", - reinterpret_cast(::Runtime_loadLibrary) }, + { "Java_java_lang_Runtime_load", + reinterpret_cast(::Runtime_load) }, { "Java_java_lang_Runtime_gc", reinterpret_cast(::Runtime_gc) }, { "Java_java_lang_Runtime_exit", diff --git a/src/system.cpp b/src/system.cpp index 17b70720e6..99cd06d576 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -378,10 +378,12 @@ class MySystem: public System { class Library: public System::Library { public: - Library(System* s, void* p, const char* name, System::Library* next): + Library(System* s, void* p, const char* name, bool mapName, + System::Library* next): s(s), p(p), - name_(name), + name(name), + mapName(mapName), next_(next) { } @@ -389,8 +391,9 @@ class MySystem: public System { return dlsym(p, function); } - virtual const char* name() { - return name_; + virtual bool matches(const char* name, bool mapName) { + return strcmp(this->name, name) == 0 + and this->mapName == mapName; } virtual System::Library* next() { @@ -408,13 +411,14 @@ class MySystem: public System { next_->dispose(); } - s->free(name_); + s->free(name); s->free(this); } System* s; void* p; - const char* name_; + const char* name; + bool mapName; System::Library* next_; }; @@ -515,22 +519,29 @@ class MySystem: public System { virtual Status load(System::Library** lib, const char* name, + bool mapName, System::Library* next) { + void* p; unsigned nameLength = strlen(name); - unsigned size = nameLength + 7; - char buffer[size]; - snprintf(buffer, size, "lib%s.so", name); + if (mapName) { + unsigned size = nameLength + 7; + char buffer[size]; + snprintf(buffer, size, "lib%s.so", name); + p = dlopen(buffer, RTLD_LAZY); + } else { + p = dlopen(name, RTLD_LAZY); + } - void* p = dlopen(buffer, RTLD_LAZY); if (p) { if (Verbose) { - fprintf(stderr, "open %s as %p\n", buffer, p); + fprintf(stderr, "open %s as %p\n", name, p); } char* n = static_cast(System::allocate(nameLength + 1)); memcpy(n, name, nameLength + 1); - *lib = new (System::allocate(sizeof(Library))) Library(this, p, n, next); + *lib = new (System::allocate(sizeof(Library))) + Library(this, p, n, mapName, next); return 0; } else { return 1; diff --git a/src/system.h b/src/system.h index f449538697..9002d772b4 100644 --- a/src/system.h +++ b/src/system.h @@ -59,7 +59,7 @@ class System: public Allocator { public: virtual ~Library() { } virtual void* resolve(const char* function) = 0; - virtual const char* name() = 0; + virtual bool matches(const char* name, bool mapName) = 0; virtual Library* next() = 0; virtual void dispose() = 0; }; @@ -74,7 +74,8 @@ class System: public Allocator { virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types, unsigned count, unsigned size, unsigned returnType) = 0; - virtual Status load(Library**, const char* name, Library* next) = 0; + virtual Status load(Library**, const char* name, bool mapName, Library* next) + = 0; virtual void exit(int code) = 0; virtual int64_t now() = 0; virtual void abort() = 0;