diff --git a/src/jniutils.cc b/src/jniutils.cc index 5113bbf..ea16935 100644 --- a/src/jniutils.cc +++ b/src/jniutils.cc @@ -44,6 +44,25 @@ namespace pEp { return field; } + jint callIntMethod( + JNIEnv *env, + jobject obj, + const char *methodname + ) + { + jclass clazz = env->GetObjectClass(obj); + assert(clazz); + + jmethodID method = env->GetMethodID(clazz, methodname, "()I"); + if (method == NULL) { + jclass ex = env->FindClass("java/lang/NoSuchMethodError"); + assert(ex); + env->ThrowNew(ex, methodname); + throw std::invalid_argument(std::string(methodname)); + } + + return env->CallIntMethod(obj, method); + } jlong callLongMethod( JNIEnv *env, jobject obj, @@ -64,6 +83,50 @@ namespace pEp { return env->CallLongMethod(obj, method); } + jobject callObjectMethod( + JNIEnv *env, + jobject obj, + const char *methodname, + jint index + ) + { + jclass clazz = env->GetObjectClass(obj); + assert(clazz); + + jmethodID method = env->GetMethodID(clazz, methodname, + "(I)Ljava/lang/Object;"); + if (method == NULL) { + jclass ex = env->FindClass("java/lang/NoSuchMethodError"); + assert(ex); + env->ThrowNew(ex, methodname); + throw std::invalid_argument(std::string(methodname)); + } + + return env->CallObjectMethod(obj, method, index); + } + + jboolean callBooleanMethod( + JNIEnv *env, + jobject obj, + const char *methodname, + jobject o + ) + { + jclass clazz = env->GetObjectClass(obj); + assert(clazz); + + jmethodID method = env->GetMethodID(clazz, methodname, + "(Ljava/lang/Object;)Z"); + if (method == NULL) { + jclass ex = env->FindClass("java/lang/NoSuchMethodError"); + assert(ex); + env->ThrowNew(ex, methodname); + throw std::invalid_argument(std::string(methodname)); + } + + return env->CallLongMethod(obj, method, o); + } + jint outOfMemory(JNIEnv *env) { jclass ex; @@ -77,27 +140,127 @@ namespace pEp { jbyteArray from_string(JNIEnv *env, const char *str) { if (str && str[0]) { - bool isCopy; - jbyteArray _str = NewByteArray(env, strlen(str)); - jbyte *b = GetByteArrayElements(env, str, &isCopy); + jboolean isCopy; + jbyteArray _str = env->NewByteArray(strlen(str)); + jbyte *b = env->GetByteArrayElements(_str, &isCopy); strcpy((char *)b, str); - ReleaseByteArrayElements(env, str, b, 0); + env->ReleaseByteArrayElements(_str, b, 0); return _str; } else { - return NewByteArray(env, 0); + return env->NewByteArray(0); } } char *to_string(JNIEnv *env, jbyteArray str) { - bool isCopy; - jbyte *b = GetByteArrayElements(env, str, &isCopy); - char *_str = strndup((char *)b, (size_t)GetArrayLength(env, str)); - ReleaseByteArrayElements(env, str, b, JNI_ABORT); + jboolean isCopy; + jbyte *b = env->GetByteArrayElements(str, &isCopy); + char *_str = strndup((char *)b, (size_t)env->GetArrayLength(str)); + env->ReleaseByteArrayElements(str, b, JNI_ABORT); return _str; } + jobject from_stringlist(JNIEnv *env, stringlist_t *sl) + { + jclass clazz = findClass(env, "java/util/ArrayList"); + jmethodID constructor = env->GetMethodID(clazz, "", "()V"); + assert(constructor); + jobject obj = env->NewObject(clazz, constructor); + assert(obj); + + stringlist_t *_sl; + for (_sl = sl; _sl && _sl->value; _sl = _sl->next) { + jobject o = from_string(env, _sl->value); + callBooleanMethod(env, obj, "add", o); + } + + return obj; + } + + stringlist_t *to_stringlist(JNIEnv *env, jobject obj) + { + jint size = callIntMethod(env, obj, "size"); + if (size == 0) + return NULL; + + stringlist_t *sl = new_stringlist(NULL); + stringlist_t *_sl; + jint i; + for (_sl = sl, i = 0; i < (int) size; i++) { + jobject o = callObjectMethod(env, obj, "get", i); + jbyteArray a = reinterpret_cast(o); + char * str = to_string(env, a); + _sl = stringlist_add(_sl, str); + free(str); + } + + return sl; + } + + jobject from_stringpairlist(JNIEnv *env, stringpair_list_t *sl) + { + jclass clazz = findClass(env, "java/util/Vector"); + jclass clazz_pair = findClass(env, "org/pEp/jniadapter/Pair"); + jmethodID constructor = env->GetMethodID(clazz, "", "()V"); + assert(constructor); + jmethodID constructor_pair = env->GetMethodID(clazz_pair, "", + "([B[B)V"); + assert(constructor_pair); + + jobject obj = env->NewObject(clazz, constructor); + assert(obj); + + stringpair_list_t *_sl; + for (_sl = sl; _sl && _sl->value; _sl = _sl->next) { + assert(_sl->value->key); + assert(_sl->value->value); + + jbyteArray first = from_string(env, _sl->value->key); + jbyteArray second = from_string(env, _sl->value->value); + jobject pair = env->NewObject(clazz_pair, constructor_pair, + first, second); + callBooleanMethod(env, obj, "add", pair); + } + + return obj; + } + + stringpair_list_t *to_stringpairlist(JNIEnv *env, jobject obj) + { + jint size = callIntMethod(env, obj, "size"); + if (size == 0) + return NULL; + + jfieldID first_id = getFieldID(env, "org/pEp/jniadapter/Pair", + "first", "Ljava/lang/Object"); + jfieldID second_id = getFieldID(env, "org/pEp/jniadapter/Pair", + "second", "Ljava/lang/Object"); + + stringpair_list_t *sl = new_stringpair_list(NULL); + stringpair_list_t *_sl; + jint i; + for (_sl = sl, i = 0; i < (int) size; i++) { + jobject pair = callObjectMethod(env, obj, "get", i); + jbyteArray first = + reinterpret_cast(env->GetObjectField(pair, + first_id)); + jbyteArray second = + reinterpret_cast(env->GetObjectField(pair, + second_id)); + + char *first_str = to_string(env, first); + char *second_str = to_string(env, second); + stringpair_t *sp = new_stringpair(first_str, second_str); + free(first_str); + free(second_str); + + _sl = stringpair_list_add(_sl, sp); + } + + return sl; + } + jobject from_timestamp(JNIEnv *env, timestamp *ts) { time_t t = timegm(ts); diff --git a/src/jniutils.hh b/src/jniutils.hh index a672c8d..929e5eb 100644 --- a/src/jniutils.hh +++ b/src/jniutils.hh @@ -1,6 +1,9 @@ #pragma once #include +#include +#include +#include namespace pEp { namespace JNIAdapter { @@ -13,22 +16,42 @@ namespace pEp { const char *signature ); + jint callIntMethod( + JNIEnv *env, + jobject obj, + const char *methodname + ); + jlong callLongMethod( JNIEnv *env, jobject obj, const char *methodname ); + jobject callObjectMethod( + JNIEnv *env, + jobject obj, + const char *methodname, + jint index + ); + + jboolean callBooleanMethod( + JNIEnv *env, + jobject obj, + const char *methodname, + jobject o + ); + jint outOfMemory(JNIEnv *env); jbyteArray from_string(JNIEnv *env, const char *str); char *to_string(JNIEnv *env, jbyteArray str); jobject from_stringlist(JNIEnv *env, stringlist_t *sl); - stringlist_t *to_stringlist(JNIEnv *env, jobject sl); + stringlist_t *to_stringlist(JNIEnv *env, jobject obj); jobject from_stringpairlist(JNIEnv *env, stringpair_list_t *sl); - stringpair_list_t *to_stringpairlist(JNIEnv *env, jobject sl); + stringpair_list_t *to_stringpairlist(JNIEnv *env, jobject obj); jobject from_timestamp(JNIEnv *env, timestamp *ts); timestamp *to_timestamp(JNIEnv *env, jobject date); @@ -37,10 +60,10 @@ namespace pEp { pEp_identity *to_identity(JNIEnv *env, jobject ident); jobject from_identitylist(JNIEnv *env, identity_list *il); - identity_list *to_identitylist(JNIEnv *env, jobject il); + identity_list *to_identitylist(JNIEnv *env, jobject obj); jobject from_bloblist(JNIEnv *env, bloblist_t *bl); - bloblist_t *to_bloblist(JNIEnv *env, jobject bl); + bloblist_t *to_bloblist(JNIEnv *env, jobject obj); }; }; diff --git a/src/org/pEp/jniadapter/Pair.java b/src/org/pEp/jniadapter/Pair.java index 4cddbc0..421475d 100644 --- a/src/org/pEp/jniadapter/Pair.java +++ b/src/org/pEp/jniadapter/Pair.java @@ -3,5 +3,12 @@ package org.pEp.jniadapter; public class Pair { public F first; public S second; + + Pair() { } + + Pair(F f, S s) { + first = f; + second = s; + } }