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