From 5bcc2741fe07251a706f07cf600f1bf9722b1b93 Mon Sep 17 00:00:00 2001 From: krasimir Date: Thu, 3 Sep 2015 13:52:32 +0000 Subject: [PATCH] Java API for opening/closing SG databases --- src/runtime/java/Makefile | 2 +- src/runtime/java/jni_utils.c | 94 +++++++++++++++++++ src/runtime/java/jni_utils.h | 28 ++++++ src/runtime/java/jpgf.c | 91 +----------------- src/runtime/java/jsg.c | 79 ++++++++++++++++ .../java/org/grammaticalframework/sg/SG.java | 22 +++++ .../org/grammaticalframework/sg/SGError.java | 9 ++ .../grammaticalframework/sg/TripleResult.java | 25 +++++ 8 files changed, 259 insertions(+), 91 deletions(-) create mode 100644 src/runtime/java/jni_utils.c create mode 100644 src/runtime/java/jni_utils.h create mode 100644 src/runtime/java/jsg.c create mode 100644 src/runtime/java/org/grammaticalframework/sg/SG.java create mode 100644 src/runtime/java/org/grammaticalframework/sg/SGError.java create mode 100644 src/runtime/java/org/grammaticalframework/sg/TripleResult.java diff --git a/src/runtime/java/Makefile b/src/runtime/java/Makefile index cb8000fd2..ccbd901e1 100644 --- a/src/runtime/java/Makefile +++ b/src/runtime/java/Makefile @@ -1,4 +1,4 @@ -C_SOURCES = jpgf.c jsg.c +C_SOURCES = jpgf.c jsg.c jni_utils.c JAVA_SOURCES = $(wildcard org/grammaticalframework/pgf/*.java) \ $(wildcard org/grammaticalframework/sg/*.java) diff --git a/src/runtime/java/jni_utils.c b/src/runtime/java/jni_utils.c new file mode 100644 index 000000000..64352e157 --- /dev/null +++ b/src/runtime/java/jni_utils.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include "jni_utils.h" +#ifndef __MINGW32__ +#include +#else +#include +#endif + +#define l2p(x) ((void*) (intptr_t) (x)) +#define p2l(x) ((jlong) (intptr_t) (x)) + +jstring +gu2j_string(JNIEnv *env, GuString s) { + const char* utf8 = s; + size_t len = strlen(s); + + jchar* utf16 = alloca(len*sizeof(jchar)); + jchar* dst = utf16; + while (s-utf8 < len) { + GuUCS ucs = gu_utf8_decode((const uint8_t**) &s); + + if (ucs <= 0xFFFF) { + *dst++ = ucs; + } else { + ucs -= 0x10000; + *dst++ = 0xD800+((ucs >> 10) & 0x3FF); + *dst++ = 0xDC00+(ucs & 0x3FF); + } + } + + return (*env)->NewString(env, utf16, dst-utf16); +} + +GuString +j2gu_string(JNIEnv *env, jstring s, GuPool* pool) { + GuString str = (*env)->GetStringUTFChars(env, s, 0); + GuString copy = gu_string_copy(str, pool); + (*env)->ReleaseStringUTFChars(env, s, str); + return copy; +} + +size_t +gu2j_string_offset(GuString s, size_t offset) { + const char* utf8 = s; + size_t joffset = 0; + while (utf8-s < offset) { + gu_utf8_decode((const uint8_t**) &utf8); + joffset++; + } + return joffset; +} + +size_t +j2gu_string_offset(GuString s, size_t joffset) { + const char* utf8 = s; + while (joffset > 0) { + gu_utf8_decode((const uint8_t**) &utf8); + joffset--; + } + return utf8-s; +} + +void* +get_ref(JNIEnv *env, jobject self) { + jfieldID refId = (*env)->GetFieldID(env, (*env)->GetObjectClass(env, self), "ref", "J"); + return l2p((*env)->GetLongField(env, self, refId)); +} + +void +throw_jstring_exception(JNIEnv *env, const char* class_name, jstring msg) +{ + jclass exception_class = (*env)->FindClass(env, class_name); + if (!exception_class) + return; + jmethodID constrId = (*env)->GetMethodID(env, exception_class, "", "(Ljava/lang/String;)V"); + if (!constrId) + return; + jobject exception = (*env)->NewObject(env, exception_class, constrId, msg); + if (!exception) + return; + (*env)->Throw(env, exception); +} + +void +throw_string_exception(JNIEnv *env, const char* class_name, const char* msg) +{ + jstring jmsg = (*env)->NewStringUTF(env, msg); + if (!jmsg) + return; + throw_jstring_exception(env, class_name, jmsg); +} + diff --git a/src/runtime/java/jni_utils.h b/src/runtime/java/jni_utils.h new file mode 100644 index 000000000..c587346bc --- /dev/null +++ b/src/runtime/java/jni_utils.h @@ -0,0 +1,28 @@ +#ifndef JNI_UTILS +#define JNI_UTILS + +#define l2p(x) ((void*) (intptr_t) (x)) +#define p2l(x) ((jlong) (intptr_t) (x)) + +jstring +gu2j_string(JNIEnv *env, GuString s); + +GuString +j2gu_string(JNIEnv *env, jstring s, GuPool* pool); + +size_t +gu2j_string_offset(GuString s, size_t offset); + +size_t +j2gu_string_offset(GuString s, size_t joffset); + +void* +get_ref(JNIEnv *env, jobject self); + +void +throw_jstring_exception(JNIEnv *env, const char* class_name, jstring msg); + +void +throw_string_exception(JNIEnv *env, const char* class_name, const char* msg); + +#endif diff --git a/src/runtime/java/jpgf.c b/src/runtime/java/jpgf.c index 875f41e80..db7765551 100644 --- a/src/runtime/java/jpgf.c +++ b/src/runtime/java/jpgf.c @@ -2,98 +2,9 @@ #include #include #include -#include #include #include -#ifndef __MINGW32__ -#include -#else -#include -#endif - -#define l2p(x) ((void*) (intptr_t) (x)) -#define p2l(x) ((jlong) (intptr_t) (x)) - -static jstring -gu2j_string(JNIEnv *env, GuString s) { - const char* utf8 = s; - size_t len = strlen(s); - - jchar* utf16 = alloca(len*sizeof(jchar)); - jchar* dst = utf16; - while (s-utf8 < len) { - GuUCS ucs = gu_utf8_decode((const uint8_t**) &s); - - if (ucs <= 0xFFFF) { - *dst++ = ucs; - } else { - ucs -= 0x10000; - *dst++ = 0xD800+((ucs >> 10) & 0x3FF); - *dst++ = 0xDC00+(ucs & 0x3FF); - } - } - - return (*env)->NewString(env, utf16, dst-utf16); -} - -static GuString -j2gu_string(JNIEnv *env, jstring s, GuPool* pool) { - GuString str = (*env)->GetStringUTFChars(env, s, 0); - GuString copy = gu_string_copy(str, pool); - (*env)->ReleaseStringUTFChars(env, s, str); - return copy; -} - -static size_t -gu2j_string_offset(GuString s, size_t offset) { - const char* utf8 = s; - size_t joffset = 0; - while (utf8-s < offset) { - gu_utf8_decode((const uint8_t**) &utf8); - joffset++; - } - return joffset; -} - -static size_t -j2gu_string_offset(GuString s, size_t joffset) { - const char* utf8 = s; - while (joffset > 0) { - gu_utf8_decode((const uint8_t**) &utf8); - joffset--; - } - return utf8-s; -} - -static void* -get_ref(JNIEnv *env, jobject self) { - jfieldID refId = (*env)->GetFieldID(env, (*env)->GetObjectClass(env, self), "ref", "J"); - return l2p((*env)->GetLongField(env, self, refId)); -} - -static void -throw_jstring_exception(JNIEnv *env, const char* class_name, jstring msg) -{ - jclass exception_class = (*env)->FindClass(env, class_name); - if (!exception_class) - return; - jmethodID constrId = (*env)->GetMethodID(env, exception_class, "", "(Ljava/lang/String;)V"); - if (!constrId) - return; - jobject exception = (*env)->NewObject(env, exception_class, constrId, msg); - if (!exception) - return; - (*env)->Throw(env, exception); -} - -static void -throw_string_exception(JNIEnv *env, const char* class_name, const char* msg) -{ - jstring jmsg = (*env)->NewStringUTF(env, msg); - if (!jmsg) - return; - throw_jstring_exception(env, class_name, jmsg); -} +#include "jni_utils.h" static JavaVM* cachedJVM; diff --git a/src/runtime/java/jsg.c b/src/runtime/java/jsg.c new file mode 100644 index 000000000..8f790505e --- /dev/null +++ b/src/runtime/java/jsg.c @@ -0,0 +1,79 @@ +#include +#include +#include "jni_utils.h" + +JNIEXPORT jobject JNICALL +Java_org_grammaticalframework_sg_SG_openSG(JNIEnv *env, jclass cls, jstring path) +{ + GuPool* tmp_pool = gu_local_pool(); + + // Create an exception frame that catches all errors. + GuExn* err = gu_exn(tmp_pool); + + const char *fpath = (*env)->GetStringUTFChars(env, path, 0); + + // Read the PGF grammar. + SgSG* sg = sg_open(fpath, err); + + (*env)->ReleaseStringUTFChars(env, path, fpath); + + if (!gu_ok(err)) { + GuString msg; + if (gu_exn_caught(err, SgError)) { + msg = (GuString) gu_exn_caught_data(err); + } else { + msg = "The database cannot be opened"; + } + throw_string_exception(env, "org/grammaticalframework/sg/SGError", msg); + gu_pool_free(tmp_pool); + return NULL; + } + + gu_pool_free(tmp_pool); + + jmethodID constrId = (*env)->GetMethodID(env, cls, "", "(J)V"); + return (*env)->NewObject(env, cls, constrId, p2l(sg)); +} + +JNIEXPORT void JNICALL +Java_org_grammaticalframework_sg_SG_close(JNIEnv *env, jobject self) +{ + GuPool* tmp_pool = gu_local_pool(); + + // Create an exception frame that catches all errors. + GuExn* err = gu_exn(tmp_pool); + + sg_close(get_ref(env, self), err); + if (!gu_ok(err)) { + GuString msg; + if (gu_exn_caught(err, SgError)) { + msg = (GuString) gu_exn_caught_data(err); + } else { + msg = "The database cannot be closed"; + } + throw_string_exception(env, "org/grammaticalframework/sg/SGError", msg); + gu_pool_free(tmp_pool); + return; + } + + gu_pool_free(tmp_pool); +} + +JNIEXPORT jobject JNICALL +Java_org_grammaticalframework_sg_SG_queryTriple(JNIEnv *env, jobject self, + jobject subj, + jobject pred, + jobject obj) +{ + return NULL; +} + +JNIEXPORT jboolean JNICALL +Java_org_grammaticalframework_sg_TripleResult_hasNext(JNIEnv *env, jobject self) +{ +} + +JNIEXPORT void JNICALL +Java_org_grammaticalframework_sg_TripleResult_close(JNIEnv *env, jobject self) +{ +} diff --git a/src/runtime/java/org/grammaticalframework/sg/SG.java b/src/runtime/java/org/grammaticalframework/sg/SG.java new file mode 100644 index 000000000..631b38ff7 --- /dev/null +++ b/src/runtime/java/org/grammaticalframework/sg/SG.java @@ -0,0 +1,22 @@ +package org.grammaticalframework.sg; + +import java.io.Closeable; +import org.grammaticalframework.pgf.Expr; + +public class SG implements Closeable { + public static native SG openSG(String path); + public native void close(); + public native TripleResult queryTriple(Expr subj, Expr pred, Expr obj); + + ////////////////////////////////////////////////////////////////// + // private stuff + private long ref; + + private SG(long ref) { + this.ref = ref; + } + + static { + System.loadLibrary("jpgf"); + } +} diff --git a/src/runtime/java/org/grammaticalframework/sg/SGError.java b/src/runtime/java/org/grammaticalframework/sg/SGError.java new file mode 100644 index 000000000..0de876bd4 --- /dev/null +++ b/src/runtime/java/org/grammaticalframework/sg/SGError.java @@ -0,0 +1,9 @@ +package org.grammaticalframework.sg; + +public class SGError extends RuntimeException { + private static final long serialVersionUID = -6098784400143861939L; + + public SGError(String message) { + super(message); + } +} diff --git a/src/runtime/java/org/grammaticalframework/sg/TripleResult.java b/src/runtime/java/org/grammaticalframework/sg/TripleResult.java new file mode 100644 index 000000000..59a0ddb81 --- /dev/null +++ b/src/runtime/java/org/grammaticalframework/sg/TripleResult.java @@ -0,0 +1,25 @@ +package org.grammaticalframework.sg; + +import java.io.Closeable; +import org.grammaticalframework.pgf.Expr; + +public class TripleResult implements Closeable { + private Expr subj; + private Expr pred; + private Expr obj; + + public native boolean hasNext(); + public native void close(); + + public Expr getSubject() { + return subj; + } + + public Expr getPredicate() { + return pred; + } + + public Expr getObject() { + return obj; + } +}