Home | History | Annotate | Download | only in java-jni
      1 #include <string.h>
      2 #include <jni.h>
      3 #include "org_clearsilver_HDF.h"
      4 
      5 #include "cs_config.h"
      6 #include "util/neo_err.h"
      7 #include "util/neo_misc.h"
      8 #include "util/neo_str.h"
      9 #include "util/neo_hdf.h"
     10 #include "cgi/cgi.h"
     11 #include "cgi/cgiwrap.h"
     12 #include "cgi/date.h"
     13 #include "cgi/html.h"
     14 
     15 #include "j_neo_util.h"
     16 
     17 void throwException(JNIEnv *env, const char* class_name, const char *message) {
     18   jclass ex_class = (*env)->FindClass(env, class_name);
     19   if (ex_class == NULL) {
     20     // Unable to find proper class!
     21     return;
     22   }
     23   (*env)->ThrowNew(env, ex_class, message);
     24 }
     25 
     26 void throwNullPointerException(JNIEnv *env, const char *message) {
     27   throwException(env, "java/lang/NullPointerException", message);
     28 }
     29 
     30 void throwRuntimeException(JNIEnv *env, const char *message) {
     31   throwException(env, "java/lang/RuntimeException", message);
     32 }
     33 
     34 void throwIOException(JNIEnv *env, const char *message) {
     35   throwException(env, "java/io/IOException", message);
     36 }
     37 
     38 void throwFileNotFoundException(JNIEnv *env, const char *message) {
     39   throwException(env, "java/io/FileNotFoundException", message);
     40 }
     41 
     42 void throwOutOfMemoryError(JNIEnv *env, const char *message) {
     43   throwException(env, "java/lang/OutOfMemoryError", message);
     44 }
     45 
     46 // Throws a runtime exception back to the Java VM appropriate for the type of
     47 // error and frees the NEOERR that is passed in.
     48 // TODO: throw more specific exceptions for errors like NERR_IO and NERR_NOMEM
     49 int jNeoErr(JNIEnv *env, NEOERR *err) {
     50   STRING str;
     51 
     52   string_init(&str);
     53   if (nerr_match(err, NERR_PARSE)) {
     54     nerr_error_string(err, &str);
     55     throwRuntimeException(env, str.buf);
     56   } else if (nerr_match(err, NERR_IO)) {
     57     nerr_error_string(err, &str);
     58     throwIOException(env, str.buf);
     59   } else if (nerr_match(err, NERR_NOMEM)) {
     60     nerr_error_string(err, &str);
     61     throwOutOfMemoryError(env, str.buf);
     62   } else {
     63     nerr_error_traceback(err, &str);
     64     throwRuntimeException(env, str.buf);
     65   }
     66 
     67   nerr_ignore(&err);  // free err, otherwise it would leak
     68   string_clear(&str);
     69 
     70   return 0;
     71 }
     72 
     73 JNIEXPORT jlong JNICALL Java_org_clearsilver_HDF__1init(
     74     JNIEnv *env, jclass objClass) {
     75   HDF *hdf = NULL;
     76   NEOERR *err;
     77 
     78   err = hdf_init(&hdf);
     79   if (err != STATUS_OK) {
     80     return jNeoErr(env, err);
     81   }
     82   return (jlong) hdf;
     83 }
     84 
     85 JNIEXPORT void JNICALL Java_org_clearsilver_HDF__1dealloc(
     86     JNIEnv *env, jclass objClass, jlong hdf_obj_ptr) {
     87   HDF *hdf = (HDF *)hdf_obj_ptr;
     88   hdf_destroy(&hdf);
     89 }
     90 
     91 JNIEXPORT jint JNICALL Java_org_clearsilver_HDF__1getIntValue(
     92     JNIEnv *env, jclass objClass, jlong hdf_obj_ptr, jstring j_hdfname,
     93      jint default_value) {
     94   HDF *hdf = (HDF *)hdf_obj_ptr;
     95   int r;
     96   const char *hdfname;
     97 
     98   if (!j_hdfname) {
     99     throwNullPointerException(env, "hdfname argument was null");
    100     return 0;
    101   }
    102 
    103   hdfname = (*env)->GetStringUTFChars(env,j_hdfname, 0);
    104 
    105   r = hdf_get_int_value(hdf, hdfname, default_value);
    106 
    107   (*env)->ReleaseStringUTFChars(env,j_hdfname,hdfname);
    108   return r;
    109 }
    110 
    111 JNIEXPORT jstring JNICALL Java_org_clearsilver_HDF__1getValue(
    112     JNIEnv *env, jclass objClass, jlong hdf_obj_ptr, jstring j_hdfname,
    113     jstring j_default_value) {
    114   HDF *hdf = (HDF *)hdf_obj_ptr;
    115   const char *r;
    116   const char *hdfname;
    117   const char *default_value;
    118   jstring retval;
    119 
    120   if (!j_hdfname) {
    121     throwNullPointerException(env, "hdfname argument was null");
    122     return 0;
    123   }
    124   hdfname = (*env)->GetStringUTFChars(env,j_hdfname,0);
    125   if (!j_default_value) {
    126     default_value = NULL;
    127   } else {
    128     default_value = (*env)->GetStringUTFChars(env, j_default_value, 0);
    129   }
    130 
    131   r = hdf_get_value(hdf, hdfname, default_value);
    132 
    133   (*env)->ReleaseStringUTFChars(env, j_hdfname, hdfname);
    134   retval = (r ? (*env)->NewStringUTF(env, r) : 0);
    135   if (default_value) {
    136     (*env)->ReleaseStringUTFChars(env, j_default_value, default_value);
    137   }
    138   return retval;
    139 }
    140 
    141 JNIEXPORT void JNICALL Java_org_clearsilver_HDF__1setValue(
    142     JNIEnv *env, jclass objClass,
    143     jlong hdf_obj_ptr, jstring j_hdfname, jstring j_value) {
    144   HDF *hdf = (HDF *)hdf_obj_ptr;
    145   NEOERR *err;
    146   const char *hdfname;
    147   const char *value;
    148 
    149   if (!j_hdfname) {
    150     throwNullPointerException(env, "hdfname argument was null");
    151     return;
    152   }
    153   hdfname = (*env)->GetStringUTFChars(env, j_hdfname, 0);
    154   if (j_value) {
    155     value = (*env)->GetStringUTFChars(env, j_value, 0);
    156   } else {
    157     value = NULL;
    158   }
    159   err = hdf_set_value(hdf, hdfname, value);
    160 
    161   (*env)->ReleaseStringUTFChars(env, j_hdfname, hdfname);
    162   if (value) {
    163     (*env)->ReleaseStringUTFChars(env, j_value, value);
    164   }
    165 
    166   if (err != STATUS_OK) {
    167     // Throw an exception
    168     jNeoErr(env, err);
    169   }
    170 }
    171 
    172 JNIEXPORT void JNICALL Java_org_clearsilver_HDF__1removeTree(
    173     JNIEnv *env, jclass objClass,
    174     jlong hdf_obj_ptr, jstring j_hdfname) {
    175   HDF *hdf = (HDF *)hdf_obj_ptr;
    176   NEOERR *err;
    177   const char *hdfname;
    178 
    179   if (!j_hdfname) {
    180     throwNullPointerException(env, "hdfname argument was null");
    181     return;
    182   }
    183   hdfname = (*env)->GetStringUTFChars(env, j_hdfname, 0);
    184   err = hdf_remove_tree(hdf, hdfname);
    185 
    186   (*env)->ReleaseStringUTFChars(env, j_hdfname, hdfname);
    187 
    188   if (err != STATUS_OK) {
    189     // Throw an exception
    190     jNeoErr(env, err);
    191   }
    192 }
    193 
    194 JNIEXPORT void JNICALL Java_org_clearsilver_HDF__1setSymLink(
    195     JNIEnv *env, jclass objClass,
    196     jlong hdf_obj_ptr, jstring j_hdf_name_src, jstring j_hdf_name_dest) {
    197   HDF *hdf = (HDF *)hdf_obj_ptr;
    198   NEOERR *err;
    199   const char *hdf_name_src;
    200   const char *hdf_name_dest;
    201 
    202   if (!j_hdf_name_src) {
    203     throwNullPointerException(env, "hdf_name_src argument was null");
    204     return;
    205   }
    206   hdf_name_src = (*env)->GetStringUTFChars(env, j_hdf_name_src, 0);
    207 
    208   if (!j_hdf_name_dest) {
    209     throwNullPointerException(env, "hdf_name_dest argument was null");
    210     return;
    211   }
    212   hdf_name_dest = (*env)->GetStringUTFChars(env, j_hdf_name_dest, 0);
    213 
    214   err = hdf_set_symlink(hdf, hdf_name_src, hdf_name_dest);
    215 
    216   (*env)->ReleaseStringUTFChars(env, j_hdf_name_src, hdf_name_src);
    217   (*env)->ReleaseStringUTFChars(env, j_hdf_name_dest, hdf_name_dest);
    218 
    219   if (err != STATUS_OK) {
    220     // Throw an exception
    221     jNeoErr(env, err);
    222   }
    223 }
    224 
    225 JNIEXPORT jstring JNICALL Java_org_clearsilver_HDF__1dump(
    226     JNIEnv *env, jclass objClass,
    227     jlong hdf_obj_ptr) {
    228   HDF *hdf = (HDF *)hdf_obj_ptr;
    229   NEOERR *err;
    230   STRING str;
    231   jstring retval;
    232 
    233   string_init(&str);
    234   err = hdf_dump_str(hdf, NULL, 0, &str);
    235   if (err != STATUS_OK) {
    236     // Throw an exception
    237     jNeoErr(env, err);
    238     retval = NULL;
    239   } else {
    240     retval =  (*env)->NewStringUTF(env,str.buf);
    241   }
    242   string_clear(&str);
    243 
    244   return retval;
    245 }
    246 
    247 NEOERR *jni_fileload_cb(void *ctx, HDF *hdf, const char *filename,
    248     char **contents) {
    249   FILELOAD_INFO *info = (FILELOAD_INFO *)ctx;
    250   jstring filename_str;
    251   jstring loaded_string;
    252   const char *c_loaded_string;
    253 
    254   // We assume that the hdf passed back is actually the hdf we already
    255   // have...
    256   if (hdf != info->hdf)
    257     return nerr_raise(NERR_ASSERT,
    258         "jni_fileload_cb: passed HDF pointer doesn't match hdf_obj_ptr");
    259 
    260   filename_str = (*info->env)->NewStringUTF(info->env, filename);
    261   (*info->env)->NewLocalRef(info->env, filename_str);
    262 
    263   loaded_string = (*info->env)->CallObjectMethod(info->env, info->fl_obj,
    264       info->fl_method, filename_str);
    265   if ((*info->env)->ExceptionCheck(info->env)) {
    266     (*info->env)->ExceptionDescribe(info->env);
    267     (*info->env)->ExceptionClear(info->env);
    268     return nerr_raise(NERR_ASSERT,
    269         "jni_fileload_cb: HDF.fileLoad returned exception, see STDERR");
    270   }
    271   c_loaded_string = (*info->env)->GetStringUTFChars(info->env, loaded_string,
    272       0);
    273   if (c_loaded_string) {
    274     *contents = strdup(c_loaded_string);
    275   }
    276   (*info->env)->ReleaseStringUTFChars(info->env, loaded_string,
    277                                       c_loaded_string);
    278 
    279   return STATUS_OK;
    280 }
    281 
    282 JNIEXPORT jboolean JNICALL Java_org_clearsilver_HDF__1readFile(
    283     JNIEnv *env, jobject objClass, jlong hdf_obj_ptr, jstring j_filename,
    284     jboolean use_cb) {
    285   HDF *hdf = (HDF *)hdf_obj_ptr;
    286   NEOERR *err;
    287   const char *filename;
    288   jboolean retval;
    289   FILELOAD_INFO fl_info;
    290 
    291   if (use_cb == JNI_TRUE) {
    292     jclass hdfClass;
    293 
    294     fl_info.env = env;
    295     fl_info.fl_obj = objClass;
    296     fl_info.hdf = hdf;
    297 
    298     hdfClass = (*env)->GetObjectClass(env, objClass);
    299     if (hdfClass == NULL) return JNI_FALSE;
    300 
    301     fl_info.fl_method = (*env)->GetMethodID(env, hdfClass,
    302         "fileLoad", "(Ljava/lang/String;)Ljava/lang/String;");
    303     if (fl_info.fl_method == NULL) return JNI_FALSE;
    304 
    305     hdf_register_fileload(hdf, &fl_info, jni_fileload_cb);
    306   }
    307 
    308   filename = (*env)->GetStringUTFChars(env, j_filename, 0);
    309   err = hdf_read_file(hdf, filename);
    310   (*env)->ReleaseStringUTFChars(env, j_filename, filename);
    311   if (use_cb == JNI_TRUE) hdf_register_fileload(hdf, NULL, NULL);
    312   if (err != STATUS_OK) {
    313     // Throw an exception.  jNeoErr handles all types of errors other than
    314     // NOT_FOUND, since that can mean different things in different contexts.
    315     // In this context, it means "file not found".
    316     if (nerr_match(err, NERR_NOT_FOUND)) {
    317       STRING str;
    318       string_init(&str);
    319       nerr_error_string(err, &str);
    320       throwFileNotFoundException(env, str.buf);
    321       string_clear(&str);
    322     } else {
    323       jNeoErr(env, err);
    324     }
    325   }
    326   retval = (err == STATUS_OK);
    327   return retval;
    328 }
    329 
    330 JNIEXPORT jboolean JNICALL Java_org_clearsilver_HDF__1writeFile(
    331     JNIEnv *env, jobject objClass, jlong hdf_obj_ptr, jstring j_filename) {
    332   HDF *hdf = (HDF *)hdf_obj_ptr;
    333   NEOERR *err;
    334   const char *filename;
    335   jboolean retval;
    336 
    337   filename = (*env)->GetStringUTFChars(env, j_filename, 0);
    338   err = hdf_write_file(hdf, filename);
    339   (*env)->ReleaseStringUTFChars(env, j_filename, filename);
    340   if (err != STATUS_OK) {
    341     jNeoErr(env, err);
    342   }
    343   retval = (err == STATUS_OK);
    344   return retval;
    345 }
    346 
    347 JNIEXPORT jboolean JNICALL Java_org_clearsilver_HDF__1writeFileAtomic(
    348     JNIEnv *env, jobject objClass, jlong hdf_obj_ptr, jstring j_filename) {
    349   HDF *hdf = (HDF *)hdf_obj_ptr;
    350   NEOERR *err;
    351   const char *filename;
    352   jboolean retval;
    353 
    354   filename = (*env)->GetStringUTFChars(env, j_filename, 0);
    355   err = hdf_write_file_atomic(hdf, filename);
    356   (*env)->ReleaseStringUTFChars(env, j_filename, filename);
    357   if (err != STATUS_OK) {
    358     jNeoErr(env, err);
    359   }
    360   retval = (err == STATUS_OK);
    361   return retval;
    362 }
    363 
    364 JNIEXPORT jboolean JNICALL Java_org_clearsilver_HDF__1readString(
    365     JNIEnv *env, jobject objClass, jlong hdf_obj_ptr, jstring j_data) {
    366   HDF *hdf = (HDF *)hdf_obj_ptr;
    367   NEOERR *err;
    368   const char *data;
    369   jboolean retval;
    370 
    371   data = (*env)->GetStringUTFChars(env, j_data, 0);
    372   err = hdf_read_string(hdf, data);
    373   (*env)->ReleaseStringUTFChars(env, j_data, data);
    374   if (err != STATUS_OK) {
    375     jNeoErr(env, err);
    376   }
    377   retval = (err == STATUS_OK);
    378   return retval;
    379 }
    380 
    381 JNIEXPORT jstring JNICALL Java_org_clearsilver_HDF__1writeString(
    382     JNIEnv *env, jclass objClass, jlong hdf_obj_ptr) {
    383   HDF *hdf = (HDF *)hdf_obj_ptr;
    384   NEOERR *err;
    385   char *output = NULL;
    386   jstring retval = NULL;
    387 
    388   err = hdf_write_string(hdf, &output);
    389   if (err != STATUS_OK) {
    390     jNeoErr(env, err);
    391   } else if (output) {
    392     retval = (*env)->NewStringUTF(env, output);
    393     free(output);
    394   }
    395   return retval;
    396 }
    397 
    398 JNIEXPORT jlong JNICALL Java_org_clearsilver_HDF__1getObj(
    399     JNIEnv *env, jclass objClass, jlong hdf_obj_ptr, jstring j_hdf_path) {
    400   HDF *hdf = (HDF *)hdf_obj_ptr;
    401   HDF *obj_hdf = NULL;
    402   const char *hdf_path;
    403 
    404   hdf_path = (*env)->GetStringUTFChars(env, j_hdf_path, 0);
    405   obj_hdf = hdf_get_obj(hdf, (char*)hdf_path);
    406   (*env)->ReleaseStringUTFChars(env, j_hdf_path, hdf_path);
    407   return (jlong)obj_hdf;
    408 }
    409 
    410 JNIEXPORT jlong JNICALL Java_org_clearsilver_HDF__1getChild(
    411     JNIEnv *env, jclass objClass, jlong hdf_obj_ptr, jstring j_hdf_path) {
    412   HDF *hdf = (HDF *)hdf_obj_ptr;
    413   HDF *obj_hdf = NULL;
    414   const char *hdf_path;
    415 
    416   hdf_path = (*env)->GetStringUTFChars(env, j_hdf_path, 0);
    417   obj_hdf = hdf_get_child(hdf, (char*)hdf_path);
    418   (*env)->ReleaseStringUTFChars(env, j_hdf_path, hdf_path);
    419   return (jlong)obj_hdf;
    420 }
    421 
    422 JNIEXPORT jlong JNICALL Java_org_clearsilver_HDF__1objChild(
    423     JNIEnv *env, jclass objClass, jlong hdf_obj_ptr) {
    424   HDF *hdf = (HDF *)hdf_obj_ptr;
    425   HDF *child_hdf = NULL;
    426 
    427   child_hdf = hdf_obj_child(hdf);
    428   return (jlong)child_hdf;
    429 }
    430 
    431 JNIEXPORT jlong JNICALL Java_org_clearsilver_HDF__1objNext(
    432     JNIEnv *env, jclass objClass, jlong hdf_obj_ptr) {
    433   HDF *hdf = (HDF *)hdf_obj_ptr;
    434   HDF *next_hdf = NULL;
    435 
    436   next_hdf = hdf_obj_next(hdf);
    437   return (jlong)next_hdf;
    438 }
    439 
    440 JNIEXPORT jstring JNICALL Java_org_clearsilver_HDF__1objName(
    441     JNIEnv *env, jclass objClass, jlong hdf_obj_ptr) {
    442   HDF *hdf = (HDF *)hdf_obj_ptr;
    443   char *name;
    444   jstring retval = NULL;
    445 
    446   name = hdf_obj_name(hdf);
    447   if (name != NULL) {
    448     retval =  (*env)->NewStringUTF(env, name);
    449   }
    450   return retval;
    451 }
    452 
    453 JNIEXPORT jstring JNICALL Java_org_clearsilver_HDF__1objValue(
    454     JNIEnv *env, jclass objClass, jlong hdf_obj_ptr) {
    455   HDF *hdf = (HDF *)hdf_obj_ptr;
    456   char *name;
    457   jstring retval = NULL;
    458 
    459   name = hdf_obj_value(hdf);
    460   if (name != NULL) {
    461     retval =  (*env)->NewStringUTF(env, name);
    462   }
    463   return retval;
    464 }
    465 
    466 JNIEXPORT void JNICALL Java_org_clearsilver_HDF__1copy
    467   (JNIEnv *env, jclass objClass, jlong hdf_dest_ptr, jstring j_hdf_path,
    468    jlong hdf_src_ptr) {
    469   HDF *dest = (HDF *)hdf_dest_ptr;
    470   HDF *src = (HDF *)hdf_src_ptr;
    471   const char *hdf_path;
    472 
    473   hdf_path = (*env)->GetStringUTFChars(env, j_hdf_path, 0);
    474   hdf_copy(dest, hdf_path, src);
    475   (*env)->ReleaseStringUTFChars(env, j_hdf_path, hdf_path);
    476 }
    477 
    478