1 #include <ejdb2.h>
2 #include <jni.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <stdlib.h>
6
7 #include "com_softmotions_ejdb2_EJDB2.h"
8 #include "com_softmotions_ejdb2_JQL.h"
9
10
11 #define JBN_JSON_FLUSH_BUFFER_SZ 4096
12
13 typedef struct JBN_STR {
14 const char *utf;
15 jstring str;
16 } JBN_STR;
17
18 typedef enum {
19 _JBN_ERROR_START = (IW_ERROR_START + 15000UL + 5000),
20 JBN_ERROR_INVALID_FIELD, /**< Failed to get class field (JBN_ERROR_INVALID_FIELD) */
21 JBN_ERROR_INVALID_METHOD, /**< Failed to get class method (JBN_ERROR_INVALID_METHOD) */
22 JBN_ERROR_INVALID_OPTIONS,
23 /**< Invalid com.softmotions.ejdb2.EJDB2Builder configuration provided
24 (JBN_ERROR_INVALID_OPTIONS) */
25 JBN_ERROR_INVALID_STATE, /**< Invalid com.softmotions.ejdb2.EJDB2 JNI state (JBN_ERROR_INVALID_STATE) */
26 JBN_ERROR_CREATION_OBJ, /**< Failed to create/allocate JNI object (JBN_ERROR_CREATION_OBJ) */
27 _JBN_ERROR_END,
28 } jbn_ecode_t;
29
30 static jclass k_EJDB2Exception_clazz;
31 static jmethodID k_EJDB2Exception_constructor; // EJDB2Exception(int code, String message)
32
33 static jclass k_EJDB2_clazz;
34 static jfieldID k_EJDB2_handle_fid;
35
36 static jclass k_JQL_clazz;
37 static jfieldID k_JQL_handle_fid;
38 static jfieldID k_JQL_db_fid;
39 static jfieldID k_JQL_query_fid;
40 static jfieldID k_JQL_collection_fid;
41 static jfieldID k_JQL_skip_fid;
42 static jfieldID k_JQL_limit_fid;
43
44 #define JBNFIELD(fid_, env_, clazz_, name_, type_) \
45 fid_ = (*(env_))->GetFieldID(env_, clazz_, name_, type_);
46
47 #define JBNFIELD2(fid_, env_, clazz_, name_, type_, label_) \
48 fid_ = (*(env_))->GetFieldID(env_, clazz_, name_, type_); \
49 if (!fid_) goto label_;
50
51 typedef struct JBN_JSPRINT_CTX {
52 int flush_buffer_sz;
53 IWXSTR *xstr;
54 iwrc (*flushFn)(struct JBN_JSPRINT_CTX *pctx);
55 JNIEnv *env;
56 jclass osClazz;
57 jobject osObj;
58 jmethodID write_mid;
59 } JBN_JSPRINT_CTX;
60
jbn_json_printer(const char * data,int size,char ch,int count,void * op)61 static iwrc jbn_json_printer(const char *data, int size, char ch, int count, void *op) {
62 JBN_JSPRINT_CTX *pctx = op;
63 IWXSTR *xstr = pctx->xstr;
64 if (!data) {
65 if (count) {
66 for (int i = 0; i < count; ++i) {
67 iwrc rc = iwxstr_cat(xstr, &ch, 1);
68 RCRET(rc);
69 }
70 }
71 } else {
72 if (size < 0) {
73 size = (int) strlen(data);
74 }
75 if (!count) {
76 count = 1;
77 }
78 for (int i = 0; i < count; ++i) {
79 iwrc rc = iwxstr_cat(xstr, data, size);
80 RCRET(rc);
81 }
82 }
83 if (iwxstr_size(xstr) >= pctx->flush_buffer_sz) {
84 iwrc rc = pctx->flushFn(pctx);
85 RCRET(rc);
86 }
87 return 0;
88 }
89
jbn_db(JNIEnv * env,jobject thisObj,EJDB * db)90 IW_INLINE iwrc jbn_db(JNIEnv *env, jobject thisObj, EJDB *db) {
91 *db = 0;
92 jlong ptr = (*env)->GetLongField(env, thisObj, k_EJDB2_handle_fid);
93 if (!ptr) {
94 return JBN_ERROR_INVALID_STATE;
95 }
96 *db = (void*) ptr;
97 return 0;
98 }
99
jbn_jql_q(JNIEnv * env,jobject thisObj,JQL * q)100 IW_INLINE iwrc jbn_jql_q(JNIEnv *env, jobject thisObj, JQL *q) {
101 *q = 0;
102 jlong ptr = (*env)->GetLongField(env, thisObj, k_JQL_handle_fid);
103 if (!ptr) {
104 return JBN_ERROR_INVALID_STATE;
105 }
106 *q = (void*) ptr;
107 return 0;
108 }
109
jbn_flush_to_stream(JBN_JSPRINT_CTX * pctx)110 static iwrc jbn_flush_to_stream(JBN_JSPRINT_CTX *pctx) {
111 JNIEnv *env = pctx->env;
112 IWXSTR *xstr = pctx->xstr;
113 size_t xsz = iwxstr_size(xstr);
114 if (xsz == 0) {
115 return 0;
116 }
117 jbyteArray arr = (*env)->NewByteArray(env, xsz);
118 if (!arr) {
119 return JBN_ERROR_CREATION_OBJ;
120 }
121 (*env)->SetByteArrayRegion(env, arr, 0, xsz, (void*) iwxstr_ptr(xstr));
122 iwxstr_clear(xstr);
123 (*env)->CallVoidMethod(env, pctx->osObj, pctx->write_mid, arr);
124 return 0;
125 }
126
jbn_init_pctx(JNIEnv * env,JBN_JSPRINT_CTX * pctx,jobject thisObj,jobject osObj)127 static iwrc jbn_init_pctx(JNIEnv *env, JBN_JSPRINT_CTX *pctx, jobject thisObj, jobject osObj) {
128 memset(pctx, 0, sizeof(*pctx));
129 iwrc rc = 0;
130 jclass osClazz = (*env)->GetObjectClass(env, osObj);
131 jmethodID writeMid = (*env)->GetMethodID(env, osClazz, "write", "([B)V");
132 IWXSTR *xstr = iwxstr_new();
133 if (!xstr) {
134 return iwrc_set_errno(rc, IW_ERROR_ALLOC);
135 }
136 pctx->xstr = xstr;
137 pctx->flush_buffer_sz = JBN_JSON_FLUSH_BUFFER_SZ;
138 pctx->env = env;
139 pctx->osClazz = osClazz;
140 pctx->osObj = osObj;
141 pctx->write_mid = writeMid;
142 pctx->flushFn = jbn_flush_to_stream;
143 return rc;
144 }
145
jbn_destroy_pctx(JBN_JSPRINT_CTX * pctx)146 static void jbn_destroy_pctx(JBN_JSPRINT_CTX *pctx) {
147 if (pctx->xstr) {
148 iwxstr_destroy(pctx->xstr);
149 pctx->xstr = 0;
150 }
151 }
152
jbn_throw_rc_exception(JNIEnv * env,iwrc rc,const char * msg_)153 static void jbn_throw_rc_exception(JNIEnv *env, iwrc rc, const char *msg_) {
154 const char *msg;
155 if (msg_) {
156 msg = msg_;
157 } else {
158 msg = iwlog_ecode_explained(rc);
159 if (!msg) {
160 msg = "Unknown iwrc error";
161 }
162 }
163 uint32_t eno = iwrc_strip_errno(&rc);
164 jstring msgStr = (*env)->NewStringUTF(env, msg);
165 jobject exObj = (*env)->NewObject(env, k_EJDB2Exception_clazz,
166 k_EJDB2Exception_constructor, (jlong) rc, (jlong) eno, msgStr);
167 if ((*env)->Throw(env, exObj) < 0) {
168 iwlog_error("Failed to throw exception for EJDB2Exception: %s", msg);
169 }
170 }
171
Java_com_softmotions_ejdb2_EJDB2__1open(JNIEnv * env,jobject thisObj,jobject optsObj)172 JNIEXPORT void JNICALL Java_com_softmotions_ejdb2_EJDB2__1open(
173 JNIEnv *env,
174 jobject thisObj,
175 jobject optsObj) {
176 iwrc rc = 0;
177 EJDB_OPTS opts = { 0 };
178 JNIEnv e = *env;
179 jfieldID fid;
180 jobject iwkv, http, wal;
181 jclass iwkvClazz, httpClazz, walClazz;
182 jclass optsClazz = e->GetObjectClass(env, optsObj);
183
184 int sc = 0;
185 EJDB db = 0;
186 JBN_STR strings[3] = { 0 };
187
188 // opts
189 JBNFIELD(fid, env, optsClazz, "no_wal", "Z");
190 opts.no_wal = e->GetBooleanField(env, optsObj, fid);
191
192 JBNFIELD(fid, env, optsClazz, "sort_buffer_sz", "I");
193 opts.sort_buffer_sz = (uint32_t) e->GetIntField(env, optsObj, fid);
194
195 JBNFIELD(fid, env, optsClazz, "document_buffer_sz", "I");
196 opts.document_buffer_sz = (uint32_t) e->GetIntField(env, optsObj, fid);
197
198 // iwkv
199 JBNFIELD(fid, env, optsClazz, "iwkv", "Lcom/softmotions/ejdb2/IWKVOptions;");
200 iwkv = e->GetObjectField(env, optsObj, fid);
201 if (!iwkv) {
202 jbn_throw_rc_exception(env, JBN_ERROR_INVALID_OPTIONS, 0);
203 return;
204 }
205 iwkvClazz = e->GetObjectClass(env, iwkv);
206
207 JBNFIELD(fid, env, iwkvClazz, "random_seed", "J");
208 opts.kv.random_seed = (uint32_t) e->GetLongField(env, iwkv, fid);
209
210 JBNFIELD(fid, env, iwkvClazz, "oflags", "J");
211 opts.kv.oflags = (iwkv_openflags) e->GetLongField(env, iwkv, fid);
212
213 JBNFIELD(fid, env, iwkvClazz, "file_lock_fail_fast", "Z");
214 opts.kv.file_lock_fail_fast = e->GetBooleanField(env, iwkv, fid);
215
216 JBNFIELD(fid, env, iwkvClazz, "path", "Ljava/lang/String;");
217 strings[sc].str = e->GetObjectField(env, iwkv, fid);
218 strings[sc].utf = strings[sc].str ? e->GetStringUTFChars(env, strings[sc].str, 0) : 0;
219 opts.kv.path = strings[sc++].utf;
220 if (!opts.kv.path) {
221 rc = JBN_ERROR_INVALID_OPTIONS;
222 goto finish;
223 }
224
225 // wal
226 JBNFIELD2(fid, env, iwkvClazz, "wal", "Lcom/softmotions/ejdb2/IWKVOptions$WALOptions;", finish);
227 wal = e->GetObjectField(env, iwkv, fid);
228 if (!wal) {
229 jbn_throw_rc_exception(env, JBN_ERROR_INVALID_OPTIONS, 0);
230 goto finish;
231 }
232 walClazz = e->GetObjectClass(env, wal);
233
234 JBNFIELD2(fid, env, walClazz, "check_crc_on_checkpoint", "Z", finish);
235 opts.kv.wal.check_crc_on_checkpoint = e->GetBooleanField(env, wal, fid);
236
237 JBNFIELD2(fid, env, walClazz, "savepoint_timeout_sec", "I", finish);
238 opts.kv.wal.savepoint_timeout_sec = (uint32_t) e->GetIntField(env, wal, fid);
239
240 JBNFIELD2(fid, env, walClazz, "checkpoint_timeout_sec", "I", finish);
241 opts.kv.wal.checkpoint_timeout_sec = (uint32_t) e->GetIntField(env, wal, fid);
242
243 JBNFIELD2(fid, env, walClazz, "buffer_sz", "J", finish);
244 opts.kv.wal.wal_buffer_sz = (uint64_t) e->GetLongField(env, wal, fid);
245
246 JBNFIELD2(fid, env, walClazz, "checkpoint_buffer_sz", "J", finish);
247 opts.kv.wal.checkpoint_buffer_sz = (uint64_t) e->GetLongField(env, wal, fid);
248
249
250 // http
251 JBNFIELD2(fid, env, optsClazz, "http", "Lcom/softmotions/ejdb2/EJDB2Builder$EJDB2HttpOptions;", finish);
252 http = e->GetObjectField(env, optsObj, fid);
253 httpClazz = e->GetObjectClass(env, http);
254
255 JBNFIELD2(fid, env, httpClazz, "enabled", "Z", finish);
256 opts.http.enabled = e->GetBooleanField(env, http, fid);
257
258 JBNFIELD2(fid, env, httpClazz, "port", "I", finish);
259 opts.http.port = e->GetIntField(env, http, fid);
260
261 JBNFIELD2(fid, env, httpClazz, "bind", "Ljava/lang/String;", finish);
262 strings[sc].str = e->GetObjectField(env, http, fid);
263 strings[sc].utf = strings[sc].str ? e->GetStringUTFChars(env, strings[sc].str, 0) : 0;
264 opts.http.bind = strings[sc++].utf;
265
266 JBNFIELD2(fid, env, httpClazz, "access_token", "Ljava/lang/String;", finish);
267 strings[sc].str = e->GetObjectField(env, http, fid);
268 strings[sc].utf = strings[sc].str ? e->GetStringUTFChars(env, strings[sc].str, 0) : 0;
269 opts.http.access_token = strings[sc++].utf;
270 opts.http.access_token_len = opts.http.access_token ? strlen(opts.http.access_token) : 0;
271
272 JBNFIELD2(fid, env, httpClazz, "read_anon", "Z", finish);
273 opts.http.read_anon = e->GetBooleanField(env, http, fid);
274
275 JBNFIELD2(fid, env, httpClazz, "max_body_size", "I", finish);
276 opts.http.max_body_size = (size_t) e->GetIntField(env, http, fid);
277
278 rc = ejdb_open(&opts, &db);
279 RCGO(rc, finish);
280
281 e->SetLongField(env, thisObj, k_EJDB2_handle_fid, (jlong) db);
282
283 finish:
284 for (int i = 0; i < (sizeof(strings) / sizeof(strings[0])); ++i) {
285 if (strings[i].str) {
286 e->ReleaseStringUTFChars(env, strings[i].str, strings[i].utf);
287 }
288 }
289 if (rc) {
290 jbn_throw_rc_exception(env, rc, 0);
291 }
292 }
293
294 // DISPOSE
Java_com_softmotions_ejdb2_EJDB2__1dispose(JNIEnv * env,jobject thisObj)295 JNIEXPORT void JNICALL Java_com_softmotions_ejdb2_EJDB2__1dispose(JNIEnv *env, jobject thisObj) {
296 jlong ptr = (*env)->GetLongField(env, thisObj, k_EJDB2_handle_fid);
297 if (ptr) {
298 (*env)->SetLongField(env, thisObj, k_EJDB2_handle_fid, 0);
299 EJDB db = (void*) ptr;
300 iwrc rc = ejdb_close(&db);
301 if (rc) {
302 jbn_throw_rc_exception(env, rc, 0);
303 }
304 }
305 }
306
307 // PUT
Java_com_softmotions_ejdb2_EJDB2__1put(JNIEnv * env,jobject thisObj,jstring coll_,jstring json_,jlong id)308 JNIEXPORT jlong JNICALL Java_com_softmotions_ejdb2_EJDB2__1put(
309 JNIEnv *env,
310 jobject thisObj,
311 jstring coll_,
312 jstring json_,
313 jlong id) {
314 iwrc rc;
315 EJDB db;
316 JBL jbl = 0;
317 jlong ret = id;
318
319 const char *coll = (*env)->GetStringUTFChars(env, coll_, 0);
320 const char *json = (*env)->GetStringUTFChars(env, json_, 0);
321 if (!coll || !json) {
322 rc = IW_ERROR_INVALID_ARGS;
323 goto finish;
324 }
325
326 rc = jbn_db(env, thisObj, &db);
327 RCGO(rc, finish);
328
329 rc = jbl_from_json(&jbl, json);
330 RCGO(rc, finish);
331
332 if (id > 0) {
333 rc = ejdb_put(db, coll, jbl, id);
334 } else {
335 rc = ejdb_put_new(db, coll, jbl, &ret);
336 }
337
338 finish:
339 if (jbl) {
340 jbl_destroy(&jbl);
341 }
342 if (coll) {
343 (*env)->ReleaseStringUTFChars(env, coll_, coll);
344 }
345 if (json) {
346 (*env)->ReleaseStringUTFChars(env, json_, json);
347 }
348 if (rc) {
349 jbn_throw_rc_exception(env, rc, 0);
350 }
351 return ret;
352 }
353
Java_com_softmotions_ejdb2_EJDB2__1online_1backup(JNIEnv * env,jobject thisObj,jstring target_)354 JNIEXPORT jlong JNICALL Java_com_softmotions_ejdb2_EJDB2__1online_1backup(
355 JNIEnv *env, jobject thisObj,
356 jstring target_) {
357 EJDB db;
358 uint64_t ts = 0;
359 const char *target = (*env)->GetStringUTFChars(env, target_, 0);
360
361 iwrc rc = jbn_db(env, thisObj, &db);
362 RCGO(rc, finish);
363
364 rc = ejdb_online_backup(db, &ts, target);
365
366 finish:
367 if (target) {
368 (*env)->ReleaseStringUTFChars(env, target_, target);
369 }
370 if (rc) {
371 jbn_throw_rc_exception(env, rc, 0);
372 }
373 return ts;
374 }
375
376 // GET
Java_com_softmotions_ejdb2_EJDB2__1get(JNIEnv * env,jobject thisObj,jstring coll_,jlong id,jobject osObj,jboolean pretty)377 JNIEXPORT void JNICALL Java_com_softmotions_ejdb2_EJDB2__1get(
378 JNIEnv *env,
379 jobject thisObj,
380 jstring coll_,
381 jlong id,
382 jobject osObj,
383 jboolean pretty) {
384 iwrc rc;
385 EJDB db;
386 JBL jbl = 0;
387 JBN_JSPRINT_CTX pctx;
388
389 const char *coll = (*env)->GetStringUTFChars(env, coll_, 0);
390 if (!coll) {
391 rc = IW_ERROR_INVALID_ARGS;
392 goto finish;
393 }
394
395 rc = jbn_db(env, thisObj, &db);
396 RCGO(rc, finish);
397
398 rc = jbn_init_pctx(env, &pctx, thisObj, osObj);
399 RCGO(rc, finish);
400
401 rc = ejdb_get(db, coll, (int64_t) id, &jbl);
402 RCGO(rc, finish);
403
404 rc = jbl_as_json(jbl, jbn_json_printer, &pctx, 0);
405 RCGO(rc, finish);
406
407 rc = pctx.flushFn(&pctx);
408
409 finish:
410 if (coll) {
411 (*env)->ReleaseStringUTFChars(env, coll_, coll);
412 }
413 if (jbl) {
414 jbl_destroy(&jbl);
415 }
416 jbn_destroy_pctx(&pctx);
417 if (rc) {
418 jbn_throw_rc_exception(env, rc, 0);
419 }
420 }
421
422 // INFO
Java_com_softmotions_ejdb2_EJDB2__1info(JNIEnv * env,jobject thisObj,jobject osObj)423 JNIEXPORT void JNICALL Java_com_softmotions_ejdb2_EJDB2__1info(
424 JNIEnv *env,
425 jobject thisObj,
426 jobject osObj) {
427 iwrc rc;
428 EJDB db;
429 JBL jbl = 0;
430 JBN_JSPRINT_CTX pctx;
431
432 rc = jbn_db(env, thisObj, &db);
433 RCGO(rc, finish);
434
435 rc = jbn_init_pctx(env, &pctx, thisObj, osObj);
436 RCGO(rc, finish);
437
438 rc = ejdb_get_meta(db, &jbl);
439 RCGO(rc, finish);
440
441 rc = jbl_as_json(jbl, jbn_json_printer, &pctx, 0);
442 RCGO(rc, finish);
443
444 rc = pctx.flushFn(&pctx);
445
446 finish:
447 if (jbl) {
448 jbl_destroy(&jbl);
449 }
450 jbn_destroy_pctx(&pctx);
451 if (rc) {
452 jbn_throw_rc_exception(env, rc, 0);
453 }
454 }
455
456 // DEL
Java_com_softmotions_ejdb2_EJDB2__1del(JNIEnv * env,jobject thisObj,jstring coll_,jlong id)457 JNIEXPORT void JNICALL Java_com_softmotions_ejdb2_EJDB2__1del(
458 JNIEnv *env,
459 jobject thisObj,
460 jstring coll_,
461 jlong id) {
462 iwrc rc;
463 EJDB db;
464 const char *coll = (*env)->GetStringUTFChars(env, coll_, 0);
465 if (!coll) {
466 rc = IW_ERROR_INVALID_ARGS;
467 goto finish;
468 }
469 rc = jbn_db(env, thisObj, &db);
470 RCGO(rc, finish);
471
472 rc = ejdb_del(db, coll, (int64_t) id);
473
474 finish:
475 if (coll) {
476 (*env)->ReleaseStringUTFChars(env, coll_, coll);
477 }
478 if (rc) {
479 jbn_throw_rc_exception(env, rc, 0);
480 }
481 }
482
483 // RENAME COLLECTION
Java_com_softmotions_ejdb2_EJDB2__1rename_1collection(JNIEnv * env,jobject thisObj,jstring oldColl_,jstring newColl_)484 JNIEXPORT void JNICALL Java_com_softmotions_ejdb2_EJDB2__1rename_1collection(
485 JNIEnv *env, jobject thisObj,
486 jstring oldColl_, jstring newColl_) {
487 iwrc rc;
488 EJDB db;
489 const char *newColl = 0;
490 const char *oldColl = (*env)->GetStringUTFChars(env, oldColl_, 0);
491 if (!oldColl) {
492 rc = IW_ERROR_INVALID_ARGS;
493 goto finish;
494 }
495 newColl = (*env)->GetStringUTFChars(env, newColl_, 0);
496 if (!newColl) {
497 rc = IW_ERROR_INVALID_ARGS;
498 goto finish;
499 }
500 rc = jbn_db(env, thisObj, &db);
501 RCGO(rc, finish);
502
503 rc = ejdb_rename_collection(db, oldColl, newColl);
504
505 finish:
506 if (oldColl) {
507 (*env)->ReleaseStringUTFChars(env, oldColl_, oldColl);
508 }
509 if (newColl) {
510 (*env)->ReleaseStringUTFChars(env, newColl_, newColl);
511 }
512 if (rc) {
513 jbn_throw_rc_exception(env, rc, 0);
514 }
515 }
516
517 // PATCH
Java_com_softmotions_ejdb2_EJDB2__1patch(JNIEnv * env,jobject thisObj,jstring coll_,jstring patch_,jlong id,jboolean upsert)518 JNIEXPORT void JNICALL Java_com_softmotions_ejdb2_EJDB2__1patch(
519 JNIEnv *env,
520 jobject thisObj,
521 jstring coll_,
522 jstring patch_,
523 jlong id,
524 jboolean upsert) {
525 iwrc rc;
526 EJDB db;
527 const char *coll = (*env)->GetStringUTFChars(env, coll_, 0);
528 const char *patch = (*env)->GetStringUTFChars(env, patch_, 0);
529 if (!coll || !patch) {
530 rc = IW_ERROR_INVALID_ARGS;
531 goto finish;
532 }
533 rc = jbn_db(env, thisObj, &db);
534 RCGO(rc, finish);
535
536 if (upsert) {
537 rc = ejdb_merge_or_put(db, coll, patch, (int64_t) id);
538 } else {
539 rc = ejdb_patch(db, coll, patch, (int64_t) id);
540 }
541
542 finish:
543 if (coll) {
544 (*env)->ReleaseStringUTFChars(env, coll_, coll);
545 }
546 if (patch_) {
547 (*env)->ReleaseStringUTFChars(env, patch_, patch);
548 }
549 if (rc) {
550 jbn_throw_rc_exception(env, rc, 0);
551 }
552 }
553
Java_com_softmotions_ejdb2_EJDB2__1remove_1collection(JNIEnv * env,jobject thisObj,jstring coll_)554 JNIEXPORT void JNICALL Java_com_softmotions_ejdb2_EJDB2__1remove_1collection(
555 JNIEnv *env,
556 jobject thisObj,
557 jstring coll_) {
558 iwrc rc;
559 EJDB db;
560 const char *coll = (*env)->GetStringUTFChars(env, coll_, 0);
561 if (!coll) {
562 rc = IW_ERROR_INVALID_ARGS;
563 goto finish;
564 }
565 rc = jbn_db(env, thisObj, &db);
566 RCGO(rc, finish);
567
568 rc = ejdb_remove_collection(db, coll);
569
570 finish:
571 if (coll) {
572 (*env)->ReleaseStringUTFChars(env, coll_, coll);
573 }
574 if (rc) {
575 jbn_throw_rc_exception(env, rc, 0);
576 }
577 }
578
Java_com_softmotions_ejdb2_EJDB2__1ensure_1index(JNIEnv * env,jobject thisObj,jstring coll_,jstring path_,jint mode)579 JNIEXPORT void JNICALL Java_com_softmotions_ejdb2_EJDB2__1ensure_1index(
580 JNIEnv *env,
581 jobject thisObj,
582 jstring coll_,
583 jstring path_,
584 jint mode) {
585
586 iwrc rc;
587 EJDB db;
588 const char *coll = (*env)->GetStringUTFChars(env, coll_, 0);
589 const char *path = (*env)->GetStringUTFChars(env, path_, 0);
590 if (!coll || !path) {
591 rc = IW_ERROR_INVALID_ARGS;
592 goto finish;
593 }
594 rc = jbn_db(env, thisObj, &db);
595 RCGO(rc, finish);
596
597 rc = ejdb_ensure_index(db, coll, path, (ejdb_idx_mode_t) mode);
598
599 finish:
600 if (coll) {
601 (*env)->ReleaseStringUTFChars(env, coll_, coll);
602 }
603 if (path) {
604 (*env)->ReleaseStringUTFChars(env, path_, path);
605 }
606 if (rc) {
607 jbn_throw_rc_exception(env, rc, 0);
608 }
609 }
610
Java_com_softmotions_ejdb2_EJDB2__1remove_1index(JNIEnv * env,jobject thisObj,jstring coll_,jstring path_,jint mode)611 JNIEXPORT void JNICALL Java_com_softmotions_ejdb2_EJDB2__1remove_1index(
612 JNIEnv *env,
613 jobject thisObj,
614 jstring coll_,
615 jstring path_,
616 jint mode) {
617 iwrc rc;
618 EJDB db;
619 const char *coll = (*env)->GetStringUTFChars(env, coll_, 0);
620 const char *path = (*env)->GetStringUTFChars(env, path_, 0);
621 if (!coll || !path) {
622 rc = IW_ERROR_INVALID_ARGS;
623 goto finish;
624 }
625 rc = jbn_db(env, thisObj, &db);
626 RCGO(rc, finish);
627
628 rc = ejdb_remove_index(db, coll, path, (ejdb_idx_mode_t) mode);
629
630 finish:
631 if (coll) {
632 (*env)->ReleaseStringUTFChars(env, coll_, coll);
633 }
634 if (path) {
635 (*env)->ReleaseStringUTFChars(env, path_, path);
636 }
637 if (rc) {
638 jbn_throw_rc_exception(env, rc, 0);
639 }
640 }
641
642 // JQL INIT
Java_com_softmotions_ejdb2_JQL__1init(JNIEnv * env,jobject thisObj,jobject dbObj,jstring queryStr,jstring collStr)643 JNIEXPORT void JNICALL Java_com_softmotions_ejdb2_JQL__1init(
644 JNIEnv *env,
645 jobject thisObj,
646 jobject dbObj,
647 jstring queryStr,
648 jstring collStr) {
649 EJDB db;
650 iwrc rc;
651 JQL q = 0;
652 const char *query = 0, *coll = 0;
653
654 if (!dbObj || !queryStr) {
655 rc = IW_ERROR_INVALID_ARGS;
656 goto finish;
657 }
658
659 rc = jbn_db(env, dbObj, &db);
660 RCGO(rc, finish);
661
662 query = (*env)->GetStringUTFChars(env, queryStr, 0);
663 if (!query) {
664 rc = IW_ERROR_INVALID_ARGS;
665 goto finish;
666 }
667
668 if (collStr) {
669 coll = (*env)->GetStringUTFChars(env, collStr, 0);
670 }
671 rc = jql_create2(&q, coll, query, JQL_KEEP_QUERY_ON_PARSE_ERROR | JQL_SILENT_ON_PARSE_ERROR);
672 RCGO(rc, finish);
673
674 (*env)->SetLongField(env, thisObj, k_JQL_handle_fid, (jlong) q);
675 if (!coll) {
676 collStr = (*env)->NewStringUTF(env, jql_collection(q));
677 (*env)->SetObjectField(env, thisObj, k_JQL_collection_fid, collStr);
678 }
679
680 finish:
681 if (query) {
682 (*env)->ReleaseStringUTFChars(env, queryStr, query);
683 }
684 if (coll) {
685 (*env)->ReleaseStringUTFChars(env, collStr, coll);
686 }
687 if (rc) {
688 if (q && (rc == JQL_ERROR_QUERY_PARSE)) {
689 jbn_throw_rc_exception(env, rc, jql_error(q));
690 } else {
691 jbn_throw_rc_exception(env, rc, 0);
692 }
693 if (q) {
694 jql_destroy(&q);
695 }
696 }
697 }
698
699 // JQL RESET
Java_com_softmotions_ejdb2_JQL__1reset(JNIEnv * env,jobject thisObj)700 JNIEXPORT void JNICALL Java_com_softmotions_ejdb2_JQL__1reset(JNIEnv *env, jobject thisObj) {
701 jlong ptr = (*env)->GetLongField(env, thisObj, k_JQL_handle_fid);
702 if (ptr) {
703 JQL q = (void*) ptr;
704 jql_reset(q, true, true);
705 }
706 }
707
708 // JQL DESTROY
Java_com_softmotions_ejdb2_JQL__1destroy(JNIEnv * env,jclass clazz,jlong handle)709 JNIEXPORT void JNICALL Java_com_softmotions_ejdb2_JQL__1destroy(JNIEnv *env, jclass clazz, jlong handle) {
710 if (handle) {
711 JQL q = (void*) handle;
712 jql_destroy(&q);
713 }
714 }
715
716 typedef struct JBN_EXEC_CTX {
717 JNIEnv *env;
718 jobject cbObj;
719 jclass cbClazz;
720 jmethodID cbMid;
721 } JBN_EXEC_CTX;
722
jbn_exec_visitor(struct _EJDB_EXEC * ux,EJDB_DOC doc,int64_t * step)723 static iwrc jbn_exec_visitor(struct _EJDB_EXEC *ux, EJDB_DOC doc, int64_t *step) {
724 iwrc rc = 0;
725 jstring json = 0;
726 JBN_EXEC_CTX *ectx = ux->opaque;
727 JNIEnv *env = ectx->env;
728 IWXSTR *xstr = iwxstr_new2(jbl_size(doc->raw) * 2);
729 if (!xstr) {
730 return iwrc_set_errno(IW_ERROR_ALLOC, errno);
731 }
732 if (doc->node) {
733 rc = jbn_as_json(doc->node, jbl_xstr_json_printer, xstr, 0);
734 } else {
735 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
736 }
737 RCGO(rc, finish);
738
739 json = (*env)->NewStringUTF(env, iwxstr_ptr(xstr));
740 if (!json) {
741 if (!(*env)->ExceptionOccurred(env)) {
742 rc = JBN_ERROR_CREATION_OBJ;
743 }
744 goto finish;
745 }
746 int64_t llv = (*env)->CallLongMethod(env, ectx->cbObj, ectx->cbMid, (jlong) doc->id, json);
747 if (llv < -2) {
748 *step = 0;
749 } else {
750 *step = llv;
751 }
752
753 finish:
754 if (json) {
755 (*env)->DeleteLocalRef(env, json);
756 }
757 iwxstr_destroy(xstr);
758 return rc;
759 }
760
761 // JQL EXECUTE
Java_com_softmotions_ejdb2_JQL__1execute(JNIEnv * env,jobject thisObj,jobject dbObj,jobject cbObj,jobject logStreamObj)762 JNIEXPORT void JNICALL Java_com_softmotions_ejdb2_JQL__1execute(
763 JNIEnv *env,
764 jobject thisObj,
765 jobject dbObj,
766 jobject cbObj,
767 jobject logStreamObj) {
768 iwrc rc;
769 EJDB db;
770 JQL q;
771 IWXSTR *log = 0;
772
773 if (!dbObj) {
774 jbn_throw_rc_exception(env, IW_ERROR_INVALID_ARGS, 0);
775 return;
776 }
777
778 rc = jbn_jql_q(env, thisObj, &q);
779 RCGO(rc, finish);
780
781 rc = jbn_db(env, dbObj, &db);
782 RCGO(rc, finish);
783
784 JBN_EXEC_CTX ectx = {
785 .env = env,
786 .cbObj = cbObj
787 };
788
789 if (cbObj) {
790 ectx.cbClazz = (*env)->GetObjectClass(env, cbObj);
791 ectx.cbMid = (*env)->GetMethodID(env, ectx.cbClazz, "onRecord", "(JLjava/lang/String;)J");
792 if (!ectx.cbMid) {
793 goto finish;
794 }
795 }
796
797 jlong skip = (*env)->GetLongField(env, thisObj, k_JQL_skip_fid);
798 jlong limit = (*env)->GetLongField(env, thisObj, k_JQL_limit_fid);
799 if (logStreamObj) {
800 log = iwxstr_new();
801 if (!log) {
802 rc = iwrc_set_errno(IW_ERROR_ALLOC, errno);
803 goto finish;
804 }
805 }
806
807 EJDB_EXEC ux = {
808 .db = db,
809 .q = q,
810 .skip = skip > 0 ? skip : 0,
811 .limit = limit > 0 ? limit : 0,
812 .opaque = &ectx,
813 .visitor = cbObj ? jbn_exec_visitor : 0,
814 .log = log
815 };
816
817 rc = ejdb_exec(&ux);
818 RCGO(rc, finish);
819
820 if (log) { // Send query execution log
821 size_t xsz = iwxstr_size(log);
822 jclass logStreamClazz = (*env)->GetObjectClass(env, logStreamObj);
823 jmethodID writeMid = (*env)->GetMethodID(env, logStreamClazz, "write", "([B)V");
824 if (!writeMid) {
825 goto finish;
826 }
827 jbyteArray arr = (*env)->NewByteArray(env, xsz);
828 if (!arr) {
829 goto finish;
830 }
831 (*env)->SetByteArrayRegion(env, arr, 0, xsz, (void*) iwxstr_ptr(log));
832 (*env)->CallVoidMethod(env, logStreamObj, writeMid, arr);
833 }
834
835 finish:
836 if (log) {
837 iwxstr_destroy(log);
838 }
839 if (rc) {
840 jbn_throw_rc_exception(env, rc, 0);
841 }
842 }
843
844 // JQL EXECUTE SCALAR LONG
Java_com_softmotions_ejdb2_JQL__1execute_1scalar_1long(JNIEnv * env,jobject thisObj,jobject dbObj,jobject logStreamObj)845 JNIEXPORT jlong JNICALL Java_com_softmotions_ejdb2_JQL__1execute_1scalar_1long(
846 JNIEnv *env,
847 jobject thisObj,
848 jobject dbObj,
849 jobject logStreamObj) {
850 iwrc rc;
851 EJDB db;
852 JQL q;
853 IWXSTR *log = 0;
854 jlong ret = 0;
855
856 if (!dbObj) {
857 jbn_throw_rc_exception(env, IW_ERROR_INVALID_ARGS, 0);
858 return 0;
859 }
860
861 rc = jbn_jql_q(env, thisObj, &q);
862 RCGO(rc, finish);
863
864 rc = jbn_db(env, dbObj, &db);
865 RCGO(rc, finish);
866
867 jlong skip = (*env)->GetLongField(env, thisObj, k_JQL_skip_fid);
868 jlong limit = (*env)->GetLongField(env, thisObj, k_JQL_limit_fid);
869 if (logStreamObj) {
870 log = iwxstr_new();
871 if (!log) {
872 rc = iwrc_set_errno(IW_ERROR_ALLOC, errno);
873 goto finish;
874 }
875 }
876
877 EJDB_EXEC ux = {
878 .db = db,
879 .q = q,
880 .skip = skip > 0 ? skip : 0,
881 .limit = limit > 0 ? limit : 0,
882 .log = log
883 };
884
885 rc = ejdb_exec(&ux);
886 RCGO(rc, finish);
887
888 if (log) { // Send query execution log
889 size_t xsz = iwxstr_size(log);
890 jclass logStreamClazz = (*env)->GetObjectClass(env, logStreamObj);
891 jmethodID writeMid = (*env)->GetMethodID(env, logStreamClazz, "write", "([B)V");
892 if (!writeMid) {
893 goto finish;
894 }
895 jbyteArray arr = (*env)->NewByteArray(env, xsz);
896 if (!arr) {
897 goto finish;
898 }
899 (*env)->SetByteArrayRegion(env, arr, 0, xsz, (void*) iwxstr_ptr(log));
900 (*env)->CallVoidMethod(env, logStreamObj, writeMid, arr);
901 }
902
903 ret = ux.cnt;
904
905 finish:
906 if (log) {
907 iwxstr_destroy(log);
908 }
909 if (rc) {
910 jbn_throw_rc_exception(env, rc, 0);
911 }
912 return ret;
913 }
914
jbn_free_json_node(void * ptr,void * op)915 static void jbn_free_json_node(void *ptr, void *op) {
916 IWPOOL *pool = op;
917 if (pool) {
918 iwpool_destroy(pool);
919 }
920 }
921
jbn_free_str(void * ptr,void * op)922 static void jbn_free_str(void *ptr, void *op) {
923 free(ptr);
924 }
925
Java_com_softmotions_ejdb2_JQL__1set_1string(JNIEnv * env,jobject thisObj,jint pos,jstring placeholder_,jstring val_,jint type)926 JNIEXPORT void JNICALL Java_com_softmotions_ejdb2_JQL__1set_1string(
927 JNIEnv *env,
928 jobject thisObj,
929 jint pos,
930 jstring placeholder_,
931 jstring val_,
932 jint type) {
933 JQL q;
934 iwrc rc;
935 const char *placeholder = 0, *val;
936
937 if (!val_) {
938 jbn_throw_rc_exception(env, IW_ERROR_INVALID_ARGS, 0);
939 return;
940 }
941 val = (*env)->GetStringUTFChars(env, val_, 0);
942
943 rc = jbn_jql_q(env, thisObj, &q);
944 RCGO(rc, finish);
945
946 if (placeholder_) {
947 placeholder = (*env)->GetStringUTFChars(env, placeholder_, 0);
948 }
949 if (type == 1) { // JSON
950 JBL_NODE node;
951 IWPOOL *pool = iwpool_create(1024);
952 if (!pool) {
953 rc = iwrc_set_errno(IW_ERROR_ALLOC, errno);
954 goto finish;
955 }
956 rc = jbn_from_json(val, &node, pool);
957 if (rc) {
958 iwpool_destroy(pool);
959 goto finish;
960 }
961 rc = jql_set_json2(q, placeholder, pos, node, jbn_free_json_node, pool);
962 if (rc) {
963 iwpool_destroy(pool);
964 goto finish;
965 }
966 } else if (type == 2) { // Regexp
967 char *str = strdup(val);
968 if (!str) {
969 rc = iwrc_set_errno(IW_ERROR_ALLOC, errno);
970 goto finish;
971 }
972 rc = jql_set_regexp2(q, placeholder, pos, str, jbn_free_str, 0);
973 if (rc) {
974 free(str);
975 goto finish;
976 }
977 } else { // All other cases
978 char *str = strdup(val);
979 if (!str) {
980 rc = iwrc_set_errno(IW_ERROR_ALLOC, errno);
981 goto finish;
982 }
983 rc = jql_set_str2(q, placeholder, pos, str, jbn_free_str, 0);
984 if (rc) {
985 free(str);
986 goto finish;
987 }
988 }
989
990 finish:
991 if (val) {
992 (*env)->ReleaseStringUTFChars(env, val_, val);
993 }
994 if (placeholder) {
995 (*env)->ReleaseStringUTFChars(env, placeholder_, placeholder);
996 }
997 if (rc) {
998 jbn_throw_rc_exception(env, rc, 0);
999 }
1000 }
1001
Java_com_softmotions_ejdb2_JQL__1set_1long(JNIEnv * env,jobject thisObj,jint pos,jstring placeholder_,jlong val)1002 JNIEXPORT void JNICALL Java_com_softmotions_ejdb2_JQL__1set_1long(
1003 JNIEnv *env,
1004 jobject thisObj,
1005 jint pos,
1006 jstring placeholder_,
1007 jlong val) {
1008
1009 JQL q;
1010 iwrc rc;
1011 const char *placeholder = 0;
1012
1013 rc = jbn_jql_q(env, thisObj, &q);
1014 RCGO(rc, finish);
1015
1016 if (placeholder_) {
1017 placeholder = (*env)->GetStringUTFChars(env, placeholder_, 0);
1018 }
1019
1020 rc = jql_set_i64(q, placeholder, pos, val);
1021
1022 finish:
1023 if (placeholder) {
1024 (*env)->ReleaseStringUTFChars(env, placeholder_, placeholder);
1025 }
1026 if (rc) {
1027 jbn_throw_rc_exception(env, rc, 0);
1028 }
1029 }
1030
Java_com_softmotions_ejdb2_JQL__1set_1double(JNIEnv * env,jobject thisObj,jint pos,jstring placeholder_,jdouble val)1031 JNIEXPORT void JNICALL Java_com_softmotions_ejdb2_JQL__1set_1double(
1032 JNIEnv *env,
1033 jobject thisObj,
1034 jint pos,
1035 jstring placeholder_,
1036 jdouble val) {
1037 JQL q;
1038 iwrc rc;
1039 const char *placeholder = 0;
1040
1041 rc = jbn_jql_q(env, thisObj, &q);
1042 RCGO(rc, finish);
1043
1044 if (placeholder_) {
1045 placeholder = (*env)->GetStringUTFChars(env, placeholder_, 0);
1046 }
1047
1048 rc = jql_set_f64(q, placeholder, pos, val);
1049
1050 finish:
1051 if (placeholder) {
1052 (*env)->ReleaseStringUTFChars(env, placeholder_, placeholder);
1053 }
1054 if (rc) {
1055 jbn_throw_rc_exception(env, rc, 0);
1056 }
1057 }
1058
Java_com_softmotions_ejdb2_JQL__1set_1boolean(JNIEnv * env,jobject thisObj,jint pos,jstring placeholder_,jboolean val)1059 JNIEXPORT void JNICALL Java_com_softmotions_ejdb2_JQL__1set_1boolean(
1060 JNIEnv *env,
1061 jobject thisObj,
1062 jint pos,
1063 jstring placeholder_,
1064 jboolean val) {
1065 JQL q;
1066 iwrc rc;
1067 const char *placeholder = 0;
1068
1069 rc = jbn_jql_q(env, thisObj, &q);
1070 RCGO(rc, finish);
1071
1072 if (placeholder_) {
1073 placeholder = (*env)->GetStringUTFChars(env, placeholder_, 0);
1074 }
1075
1076 rc = jql_set_bool(q, placeholder, pos, val);
1077
1078 finish:
1079 if (placeholder) {
1080 (*env)->ReleaseStringUTFChars(env, placeholder_, placeholder);
1081 }
1082 if (rc) {
1083 jbn_throw_rc_exception(env, rc, 0);
1084 }
1085 }
1086
Java_com_softmotions_ejdb2_JQL__1set_1null(JNIEnv * env,jobject thisObj,jint pos,jstring placeholder_)1087 JNIEXPORT void JNICALL Java_com_softmotions_ejdb2_JQL__1set_1null(
1088 JNIEnv *env,
1089 jobject thisObj,
1090 jint pos,
1091 jstring placeholder_) {
1092 JQL q;
1093 iwrc rc;
1094 const char *placeholder = 0;
1095
1096 rc = jbn_jql_q(env, thisObj, &q);
1097 RCGO(rc, finish);
1098
1099 if (placeholder_) {
1100 placeholder = (*env)->GetStringUTFChars(env, placeholder_, 0);
1101 }
1102
1103 rc = jql_set_null(q, placeholder, pos);
1104
1105 finish:
1106 if (placeholder) {
1107 (*env)->ReleaseStringUTFChars(env, placeholder_, placeholder);
1108 }
1109 if (rc) {
1110 jbn_throw_rc_exception(env, rc, 0);
1111 }
1112 }
1113
Java_com_softmotions_ejdb2_JQL__1get_1limit(JNIEnv * env,jobject thisObj)1114 JNIEXPORT jlong JNICALL Java_com_softmotions_ejdb2_JQL__1get_1limit(JNIEnv *env, jobject thisObj) {
1115 JQL q;
1116 int64_t limit = 0;
1117 iwrc rc = jbn_jql_q(env, thisObj, &q);
1118 RCGO(rc, finish);
1119 rc = jql_get_limit(q, &limit);
1120
1121 finish:
1122 if (rc) {
1123 jbn_throw_rc_exception(env, rc, 0);
1124 }
1125 return (jlong) limit;
1126 }
1127
Java_com_softmotions_ejdb2_JQL__1get_1skip(JNIEnv * env,jobject thisObj)1128 JNIEXPORT jlong JNICALL Java_com_softmotions_ejdb2_JQL__1get_1skip(JNIEnv *env, jobject thisObj) {
1129 JQL q;
1130 int64_t skip = 0;
1131 iwrc rc = jbn_jql_q(env, thisObj, &q);
1132 RCGO(rc, finish);
1133 rc = jql_get_skip(q, &skip);
1134
1135 finish:
1136 if (rc) {
1137 jbn_throw_rc_exception(env, rc, 0);
1138 }
1139 return (jlong) skip;
1140 }
1141
jbn_ecodefn(locale_t locale,uint32_t ecode)1142 static const char *jbn_ecodefn(locale_t locale, uint32_t ecode) {
1143 if (!((ecode > _JBN_ERROR_START) && (ecode < _JBN_ERROR_END))) {
1144 return 0;
1145 }
1146 switch (ecode) {
1147 case JBN_ERROR_INVALID_FIELD:
1148 return "Failed to get class field (JBN_ERROR_INVALID_FIELD)";
1149 case JBN_ERROR_INVALID_METHOD:
1150 return "Failed to get class method (JBN_ERROR_INVALID_METHOD)";
1151 case JBN_ERROR_INVALID_OPTIONS:
1152 return "Invalid com.softmotions.ejdb2.EJDB2Builder configuration provided (JBN_ERROR_INVALID_OPTIONS)";
1153 case JBN_ERROR_INVALID_STATE:
1154 return "Invalid com.softmotions.ejdb2.EJDB2 JNI state. Database closed? (JBN_ERROR_INVALID_STATE)";
1155 case JBN_ERROR_CREATION_OBJ:
1156 return "Failed to create/allocate JNI object (JBN_ERROR_CREATION_OBJ)";
1157 }
1158 return 0;
1159 }
1160
JNI_OnLoad(JavaVM * vm,void * reserved)1161 JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
1162 JNIEnv *env;
1163 if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_6) != JNI_OK) {
1164 return -1;
1165 }
1166 static volatile int jbn_ecodefn_initialized = 0;
1167 if (__sync_bool_compare_and_swap(&jbn_ecodefn_initialized, 0, 1)) {
1168 iwrc rc = ejdb_init();
1169 if (rc) {
1170 iwlog_ecode_error3(rc);
1171 return JNI_ERR;
1172 }
1173 iwlog_register_ecodefn(jbn_ecodefn);
1174 }
1175
1176 jclass clazz = (*env)->FindClass(env, "com/softmotions/ejdb2/EJDB2");
1177 if (!clazz) {
1178 iwlog_error2("Cannot find com.softmotions.ejdb2.EJDB2 class");
1179 return -1;
1180 }
1181 k_EJDB2_clazz = (*env)->NewGlobalRef(env, clazz);
1182 k_EJDB2_handle_fid = (*env)->GetFieldID(env, k_EJDB2_clazz, "_handle", "J");
1183
1184
1185 clazz = (*env)->FindClass(env, "com/softmotions/ejdb2/EJDB2Exception");
1186 if (!clazz) {
1187 iwlog_error2("Cannot find com.softmotions.ejdb2.EJDB2Exception class");
1188 return -1;
1189 }
1190 k_EJDB2Exception_clazz = (*env)->NewGlobalRef(env, clazz);
1191 k_EJDB2Exception_constructor = (*env)->GetMethodID(env, k_EJDB2Exception_clazz,
1192 "<init>", "(JJLjava/lang/String;)V");
1193 if (!k_EJDB2Exception_constructor) {
1194 iwlog_error2("Cannot find com.softmotions.ejdb2.EJDB2Exception#<init>(long,String)");
1195 return -1;
1196 }
1197
1198 clazz = (*env)->FindClass(env, "com/softmotions/ejdb2/JQL");
1199 if (!clazz) {
1200 iwlog_error2("Cannot find com.softmotions.ejdb2.JQL class");
1201 return -1;
1202 }
1203 k_JQL_clazz = (*env)->NewGlobalRef(env, clazz);
1204 k_JQL_handle_fid = (*env)->GetFieldID(env, k_JQL_clazz, "_handle", "J");
1205 k_JQL_db_fid = (*env)->GetFieldID(env, k_JQL_clazz, "db", "Lcom/softmotions/ejdb2/EJDB2;");
1206 k_JQL_query_fid = (*env)->GetFieldID(env, k_JQL_clazz, "query", "Ljava/lang/String;");
1207 k_JQL_collection_fid = (*env)->GetFieldID(env, k_JQL_clazz, "collection", "Ljava/lang/String;");
1208 k_JQL_skip_fid = (*env)->GetFieldID(env, k_JQL_clazz, "skip", "J");
1209 k_JQL_limit_fid = (*env)->GetFieldID(env, k_JQL_clazz, "limit", "J");
1210
1211 return JNI_VERSION_1_6;
1212 }
1213
JNI_OnUnload(JavaVM * vm,void * reserved)1214 JNIEXPORT void JNI_OnUnload(JavaVM *vm, void *reserved) { // Not really useless
1215 JNIEnv *env;
1216 if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_6) != JNI_OK) {
1217 return;
1218 }
1219 if (k_EJDB2_clazz) {
1220 (*env)->DeleteGlobalRef(env, k_EJDB2_clazz);
1221 }
1222 if (k_JQL_clazz) {
1223 (*env)->DeleteGlobalRef(env, k_JQL_clazz);
1224 }
1225 if (k_EJDB2Exception_clazz) {
1226 (*env)->DeleteGlobalRef(env, k_EJDB2Exception_clazz);
1227 }
1228 }
1229