#include <string.h> #include <jni.h> #include "org_clearsilver_HDF.h" #include "cs_config.h" #include "util/neo_err.h" #include "util/neo_misc.h" #include "util/neo_str.h" #include "util/neo_hdf.h" #include "cgi/cgi.h" #include "cgi/cgiwrap.h" #include "cgi/date.h" #include "cgi/html.h" #include "j_neo_util.h" void throwException(JNIEnv *env, const char* class_name, const char *message) { jclass ex_class = (*env)->FindClass(env, class_name); if (ex_class == NULL) { // Unable to find proper class! return; } (*env)->ThrowNew(env, ex_class, message); } void throwNullPointerException(JNIEnv *env, const char *message) { throwException(env, "java/lang/NullPointerException", message); } void throwRuntimeException(JNIEnv *env, const char *message) { throwException(env, "java/lang/RuntimeException", message); } void throwIOException(JNIEnv *env, const char *message) { throwException(env, "java/io/IOException", message); } void throwFileNotFoundException(JNIEnv *env, const char *message) { throwException(env, "java/io/FileNotFoundException", message); } void throwOutOfMemoryError(JNIEnv *env, const char *message) { throwException(env, "java/lang/OutOfMemoryError", message); } // Throws a runtime exception back to the Java VM appropriate for the type of // error and frees the NEOERR that is passed in. // TODO: throw more specific exceptions for errors like NERR_IO and NERR_NOMEM int jNeoErr(JNIEnv *env, NEOERR *err) { STRING str; string_init(&str); if (nerr_match(err, NERR_PARSE)) { nerr_error_string(err, &str); throwRuntimeException(env, str.buf); } else if (nerr_match(err, NERR_IO)) { nerr_error_string(err, &str); throwIOException(env, str.buf); } else if (nerr_match(err, NERR_NOMEM)) { nerr_error_string(err, &str); throwOutOfMemoryError(env, str.buf); } else { nerr_error_traceback(err, &str); throwRuntimeException(env, str.buf); } nerr_ignore(&err); // free err, otherwise it would leak string_clear(&str); return 0; } JNIEXPORT jlong JNICALL Java_org_clearsilver_HDF__1init( JNIEnv *env, jclass objClass) { HDF *hdf = NULL; NEOERR *err; err = hdf_init(&hdf); if (err != STATUS_OK) { return jNeoErr(env, err); } return (jlong) hdf; } JNIEXPORT void JNICALL Java_org_clearsilver_HDF__1dealloc( JNIEnv *env, jclass objClass, jlong hdf_obj_ptr) { HDF *hdf = (HDF *)hdf_obj_ptr; hdf_destroy(&hdf); } JNIEXPORT jint JNICALL Java_org_clearsilver_HDF__1getIntValue( JNIEnv *env, jclass objClass, jlong hdf_obj_ptr, jstring j_hdfname, jint default_value) { HDF *hdf = (HDF *)hdf_obj_ptr; int r; const char *hdfname; if (!j_hdfname) { throwNullPointerException(env, "hdfname argument was null"); return 0; } hdfname = (*env)->GetStringUTFChars(env,j_hdfname, 0); r = hdf_get_int_value(hdf, hdfname, default_value); (*env)->ReleaseStringUTFChars(env,j_hdfname,hdfname); return r; } JNIEXPORT jstring JNICALL Java_org_clearsilver_HDF__1getValue( JNIEnv *env, jclass objClass, jlong hdf_obj_ptr, jstring j_hdfname, jstring j_default_value) { HDF *hdf = (HDF *)hdf_obj_ptr; const char *r; const char *hdfname; const char *default_value; jstring retval; if (!j_hdfname) { throwNullPointerException(env, "hdfname argument was null"); return 0; } hdfname = (*env)->GetStringUTFChars(env,j_hdfname,0); if (!j_default_value) { default_value = NULL; } else { default_value = (*env)->GetStringUTFChars(env, j_default_value, 0); } r = hdf_get_value(hdf, hdfname, default_value); (*env)->ReleaseStringUTFChars(env, j_hdfname, hdfname); retval = (r ? (*env)->NewStringUTF(env, r) : 0); if (default_value) { (*env)->ReleaseStringUTFChars(env, j_default_value, default_value); } return retval; } JNIEXPORT void JNICALL Java_org_clearsilver_HDF__1setValue( JNIEnv *env, jclass objClass, jlong hdf_obj_ptr, jstring j_hdfname, jstring j_value) { HDF *hdf = (HDF *)hdf_obj_ptr; NEOERR *err; const char *hdfname; const char *value; if (!j_hdfname) { throwNullPointerException(env, "hdfname argument was null"); return; } hdfname = (*env)->GetStringUTFChars(env, j_hdfname, 0); if (j_value) { value = (*env)->GetStringUTFChars(env, j_value, 0); } else { value = NULL; } err = hdf_set_value(hdf, hdfname, value); (*env)->ReleaseStringUTFChars(env, j_hdfname, hdfname); if (value) { (*env)->ReleaseStringUTFChars(env, j_value, value); } if (err != STATUS_OK) { // Throw an exception jNeoErr(env, err); } } JNIEXPORT void JNICALL Java_org_clearsilver_HDF__1removeTree( JNIEnv *env, jclass objClass, jlong hdf_obj_ptr, jstring j_hdfname) { HDF *hdf = (HDF *)hdf_obj_ptr; NEOERR *err; const char *hdfname; if (!j_hdfname) { throwNullPointerException(env, "hdfname argument was null"); return; } hdfname = (*env)->GetStringUTFChars(env, j_hdfname, 0); err = hdf_remove_tree(hdf, hdfname); (*env)->ReleaseStringUTFChars(env, j_hdfname, hdfname); if (err != STATUS_OK) { // Throw an exception jNeoErr(env, err); } } JNIEXPORT void JNICALL Java_org_clearsilver_HDF__1setSymLink( JNIEnv *env, jclass objClass, jlong hdf_obj_ptr, jstring j_hdf_name_src, jstring j_hdf_name_dest) { HDF *hdf = (HDF *)hdf_obj_ptr; NEOERR *err; const char *hdf_name_src; const char *hdf_name_dest; if (!j_hdf_name_src) { throwNullPointerException(env, "hdf_name_src argument was null"); return; } hdf_name_src = (*env)->GetStringUTFChars(env, j_hdf_name_src, 0); if (!j_hdf_name_dest) { throwNullPointerException(env, "hdf_name_dest argument was null"); return; } hdf_name_dest = (*env)->GetStringUTFChars(env, j_hdf_name_dest, 0); err = hdf_set_symlink(hdf, hdf_name_src, hdf_name_dest); (*env)->ReleaseStringUTFChars(env, j_hdf_name_src, hdf_name_src); (*env)->ReleaseStringUTFChars(env, j_hdf_name_dest, hdf_name_dest); if (err != STATUS_OK) { // Throw an exception jNeoErr(env, err); } } JNIEXPORT jstring JNICALL Java_org_clearsilver_HDF__1dump( JNIEnv *env, jclass objClass, jlong hdf_obj_ptr) { HDF *hdf = (HDF *)hdf_obj_ptr; NEOERR *err; STRING str; jstring retval; string_init(&str); err = hdf_dump_str(hdf, NULL, 0, &str); if (err != STATUS_OK) { // Throw an exception jNeoErr(env, err); retval = NULL; } else { retval = (*env)->NewStringUTF(env,str.buf); } string_clear(&str); return retval; } NEOERR *jni_fileload_cb(void *ctx, HDF *hdf, const char *filename, char **contents) { FILELOAD_INFO *info = (FILELOAD_INFO *)ctx; jstring filename_str; jstring loaded_string; const char *c_loaded_string; // We assume that the hdf passed back is actually the hdf we already // have... if (hdf != info->hdf) return nerr_raise(NERR_ASSERT, "jni_fileload_cb: passed HDF pointer doesn't match hdf_obj_ptr"); filename_str = (*info->env)->NewStringUTF(info->env, filename); (*info->env)->NewLocalRef(info->env, filename_str); loaded_string = (*info->env)->CallObjectMethod(info->env, info->fl_obj, info->fl_method, filename_str); if ((*info->env)->ExceptionCheck(info->env)) { (*info->env)->ExceptionDescribe(info->env); (*info->env)->ExceptionClear(info->env); return nerr_raise(NERR_ASSERT, "jni_fileload_cb: HDF.fileLoad returned exception, see STDERR"); } c_loaded_string = (*info->env)->GetStringUTFChars(info->env, loaded_string, 0); if (c_loaded_string) { *contents = strdup(c_loaded_string); } (*info->env)->ReleaseStringUTFChars(info->env, loaded_string, c_loaded_string); return STATUS_OK; } JNIEXPORT jboolean JNICALL Java_org_clearsilver_HDF__1readFile( JNIEnv *env, jobject objClass, jlong hdf_obj_ptr, jstring j_filename, jboolean use_cb) { HDF *hdf = (HDF *)hdf_obj_ptr; NEOERR *err; const char *filename; jboolean retval; FILELOAD_INFO fl_info; if (use_cb == JNI_TRUE) { jclass hdfClass; fl_info.env = env; fl_info.fl_obj = objClass; fl_info.hdf = hdf; hdfClass = (*env)->GetObjectClass(env, objClass); if (hdfClass == NULL) return JNI_FALSE; fl_info.fl_method = (*env)->GetMethodID(env, hdfClass, "fileLoad", "(Ljava/lang/String;)Ljava/lang/String;"); if (fl_info.fl_method == NULL) return JNI_FALSE; hdf_register_fileload(hdf, &fl_info, jni_fileload_cb); } filename = (*env)->GetStringUTFChars(env, j_filename, 0); err = hdf_read_file(hdf, filename); (*env)->ReleaseStringUTFChars(env, j_filename, filename); if (use_cb == JNI_TRUE) hdf_register_fileload(hdf, NULL, NULL); if (err != STATUS_OK) { // Throw an exception. jNeoErr handles all types of errors other than // NOT_FOUND, since that can mean different things in different contexts. // In this context, it means "file not found". if (nerr_match(err, NERR_NOT_FOUND)) { STRING str; string_init(&str); nerr_error_string(err, &str); throwFileNotFoundException(env, str.buf); string_clear(&str); } else { jNeoErr(env, err); } } retval = (err == STATUS_OK); return retval; } JNIEXPORT jboolean JNICALL Java_org_clearsilver_HDF__1writeFile( JNIEnv *env, jobject objClass, jlong hdf_obj_ptr, jstring j_filename) { HDF *hdf = (HDF *)hdf_obj_ptr; NEOERR *err; const char *filename; jboolean retval; filename = (*env)->GetStringUTFChars(env, j_filename, 0); err = hdf_write_file(hdf, filename); (*env)->ReleaseStringUTFChars(env, j_filename, filename); if (err != STATUS_OK) { jNeoErr(env, err); } retval = (err == STATUS_OK); return retval; } JNIEXPORT jboolean JNICALL Java_org_clearsilver_HDF__1writeFileAtomic( JNIEnv *env, jobject objClass, jlong hdf_obj_ptr, jstring j_filename) { HDF *hdf = (HDF *)hdf_obj_ptr; NEOERR *err; const char *filename; jboolean retval; filename = (*env)->GetStringUTFChars(env, j_filename, 0); err = hdf_write_file_atomic(hdf, filename); (*env)->ReleaseStringUTFChars(env, j_filename, filename); if (err != STATUS_OK) { jNeoErr(env, err); } retval = (err == STATUS_OK); return retval; } JNIEXPORT jboolean JNICALL Java_org_clearsilver_HDF__1readString( JNIEnv *env, jobject objClass, jlong hdf_obj_ptr, jstring j_data) { HDF *hdf = (HDF *)hdf_obj_ptr; NEOERR *err; const char *data; jboolean retval; data = (*env)->GetStringUTFChars(env, j_data, 0); err = hdf_read_string(hdf, data); (*env)->ReleaseStringUTFChars(env, j_data, data); if (err != STATUS_OK) { jNeoErr(env, err); } retval = (err == STATUS_OK); return retval; } JNIEXPORT jstring JNICALL Java_org_clearsilver_HDF__1writeString( JNIEnv *env, jclass objClass, jlong hdf_obj_ptr) { HDF *hdf = (HDF *)hdf_obj_ptr; NEOERR *err; char *output = NULL; jstring retval = NULL; err = hdf_write_string(hdf, &output); if (err != STATUS_OK) { jNeoErr(env, err); } else if (output) { retval = (*env)->NewStringUTF(env, output); free(output); } return retval; } JNIEXPORT jlong JNICALL Java_org_clearsilver_HDF__1getObj( JNIEnv *env, jclass objClass, jlong hdf_obj_ptr, jstring j_hdf_path) { HDF *hdf = (HDF *)hdf_obj_ptr; HDF *obj_hdf = NULL; const char *hdf_path; hdf_path = (*env)->GetStringUTFChars(env, j_hdf_path, 0); obj_hdf = hdf_get_obj(hdf, (char*)hdf_path); (*env)->ReleaseStringUTFChars(env, j_hdf_path, hdf_path); return (jlong)obj_hdf; } JNIEXPORT jlong JNICALL Java_org_clearsilver_HDF__1getChild( JNIEnv *env, jclass objClass, jlong hdf_obj_ptr, jstring j_hdf_path) { HDF *hdf = (HDF *)hdf_obj_ptr; HDF *obj_hdf = NULL; const char *hdf_path; hdf_path = (*env)->GetStringUTFChars(env, j_hdf_path, 0); obj_hdf = hdf_get_child(hdf, (char*)hdf_path); (*env)->ReleaseStringUTFChars(env, j_hdf_path, hdf_path); return (jlong)obj_hdf; } JNIEXPORT jlong JNICALL Java_org_clearsilver_HDF__1objChild( JNIEnv *env, jclass objClass, jlong hdf_obj_ptr) { HDF *hdf = (HDF *)hdf_obj_ptr; HDF *child_hdf = NULL; child_hdf = hdf_obj_child(hdf); return (jlong)child_hdf; } JNIEXPORT jlong JNICALL Java_org_clearsilver_HDF__1objNext( JNIEnv *env, jclass objClass, jlong hdf_obj_ptr) { HDF *hdf = (HDF *)hdf_obj_ptr; HDF *next_hdf = NULL; next_hdf = hdf_obj_next(hdf); return (jlong)next_hdf; } JNIEXPORT jstring JNICALL Java_org_clearsilver_HDF__1objName( JNIEnv *env, jclass objClass, jlong hdf_obj_ptr) { HDF *hdf = (HDF *)hdf_obj_ptr; char *name; jstring retval = NULL; name = hdf_obj_name(hdf); if (name != NULL) { retval = (*env)->NewStringUTF(env, name); } return retval; } JNIEXPORT jstring JNICALL Java_org_clearsilver_HDF__1objValue( JNIEnv *env, jclass objClass, jlong hdf_obj_ptr) { HDF *hdf = (HDF *)hdf_obj_ptr; char *name; jstring retval = NULL; name = hdf_obj_value(hdf); if (name != NULL) { retval = (*env)->NewStringUTF(env, name); } return retval; } JNIEXPORT void JNICALL Java_org_clearsilver_HDF__1copy (JNIEnv *env, jclass objClass, jlong hdf_dest_ptr, jstring j_hdf_path, jlong hdf_src_ptr) { HDF *dest = (HDF *)hdf_dest_ptr; HDF *src = (HDF *)hdf_src_ptr; const char *hdf_path; hdf_path = (*env)->GetStringUTFChars(env, j_hdf_path, 0); hdf_copy(dest, hdf_path, src); (*env)->ReleaseStringUTFChars(env, j_hdf_path, hdf_path); }