include yslt.yml2 include yslt.yml2 tstylesheet { include ./textutils.ysl2 include ./types_c.ysl2 template "/namespace[@name='pEp']" { apply "struct", 0; document("../../build/marker/gen_cpp_Message.marker", "text") > "" } template "struct" { const "jname" call "CamelCase" with "text", "@name"; document("../cxx/foundation_pEp_jniadapter_{$jname}.cc", "text") { || #include #include #include #include #include #include "jniutils.hh" #include "throw_pEp_exception.hh" #include "foundation_pEp_jniadapter_«$jname».h" using namespace std; namespace pEp { namespace JNIAdapter { static ::«@name» *«@name»_ptr(JNIEnv *env, jobject me) { jfieldID handle; handle = getFieldID(env, "foundation/pEp/jniadapter/«$jname»", "handle", "J"); if(!handle) { throw runtime_error("field not found: handle"); } long handle_val = static_cast(env->GetLongField(me, handle)); if(!handle_val) { throw runtime_error("invalid handle (0)"); } return reinterpret_cast<::«@name» *>(handle_val); } }; }; extern "C" { using namespace pEp::JNIAdapter; JNIEXPORT jlong JNICALL Java_foundation_pEp_jniadapter_«$jname»_init(JNIEnv *env, jobject obj) { pEpLog("called"); ::«@name» * _obj = ::new_«@name»(PEP_dir_incoming); if (!_obj) { outOfMemory(env); return 0; } return reinterpret_cast(_obj); } JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_«$jname»_release(JNIEnv *env, jobject obj, jlong value) { pEpLog("called"); if (value) { ::«@name» *_obj = reinterpret_cast<::«@name» *>(value); ::free_«@name»(_obj); } } JNIEXPORT jlong JNICALL Java_foundation_pEp_jniadapter_«$jname»__1«$jname»(JNIEnv *env, jobject msg, jbyteArray mime_text) { pEpLog("called"); char *_mime_text = to_string(env, mime_text); size_t _size = env->GetArrayLength(mime_text); ::«@name» *_msg = nullptr; PEP_STATUS status = mime_decode_«@name»(_mime_text, _size, &_msg, NULL); if (status) { throw_pEp_Exception(env, status); } return reinterpret_cast(_msg); } JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter_«$jname»__1encodeMIME(JNIEnv *env, jobject obj) { pEpLog("called"); «@name»* _obj = nullptr; try { _obj = «@name»_ptr(env, obj); } catch(...) { jclass ex = env->FindClass("java/lang/IllegalStateException"); assert(ex); env->ThrowNew(ex, nullptr); return static_cast(NULL); } char *mime_text = nullptr; PEP_STATUS status = ::mime_encode_«@name»(_obj, false, &mime_text, false); if (status) { throw_pEp_Exception(env, status); } jbyteArray result = from_string(env, mime_text); free(mime_text); return result; } JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter_Message__1encodeASN1XER(JNIEnv *env, jclass clazz, jobject _msg) { pEpLog("called"); message* msg = nullptr; try { msg = message_ptr(env, _msg); } catch(...) { jclass ex = env->FindClass("java/lang/IllegalStateException"); assert(ex); env->ThrowNew(ex, nullptr); return NULL; } // create ASN1Message ASN1Message_t *msg_asn1 = ::ASN1Message_from_message(msg, NULL, true, 0); if (msg_asn1 == nullptr) { jclass ex = env->FindClass("java/lang/IllegalStateException"); assert(ex); env->ThrowNew(ex, nullptr); return NULL; } // encode PER char *msg_per = nullptr; size_t data_size_per = 0; PEP_STATUS status = ::encode_ASN1Message_message(msg_asn1, &msg_per, &data_size_per); free(msg_asn1); if (status) { throw_pEp_Exception(env, status); return NULL; } if (msg_per == nullptr) { jclass ex = env->FindClass("java/lang/IllegalStateException"); assert(ex); env->ThrowNew(ex, nullptr); return NULL; } // encode PER to XER char *msg_xer = nullptr; status = ::PER_to_XER_ASN1Message_msg(msg_per, data_size_per, &msg_xer); free(msg_per); if (status) { throw_pEp_Exception(env, status); return NULL; } if (msg_xer == nullptr) { jclass ex = env->FindClass("java/lang/IllegalStateException"); assert(ex); env->ThrowNew(ex, nullptr); return NULL; } jbyteArray result = from_string(env, msg_xer); return result; } JNIEXPORT jobject JNICALL Java_foundation_pEp_jniadapter_Message__1decodeASN1XER(JNIEnv *env, jclass clazz, jbyteArray _msg_xer) { pEpLog("called"); char *msg_xer = nullptr; if(_msg_xer) { msg_xer = to_string(env, _msg_xer); } // validate param msg_xer if (msg_xer == nullptr) { jclass ex = env->FindClass("java/lang/IllegalStateException"); assert(ex); env->ThrowNew(ex, nullptr); return NULL; } // convert XER to PER char *msg_per = nullptr; size_t msg_per_size = 0; PEP_STATUS status = ::XER_to_PER_ASN1Message_msg(msg_xer, &msg_per, &msg_per_size); free(msg_xer); if (status) { throw_pEp_Exception(env, status); return NULL; } if (msg_per == nullptr) { jclass ex = env->FindClass("java/lang/IllegalStateException"); assert(ex); env->ThrowNew(ex, nullptr); return NULL; } // decode PER to ASN1Message ASN1Message *msg_asn1 = nullptr; status = ::decode_ASN1Message_message(msg_per, msg_per_size, &msg_asn1); free(msg_per); if (status) { throw_pEp_Exception(env, status); return NULL; } if (msg_asn1 == nullptr) { jclass ex = env->FindClass("java/lang/IllegalStateException"); assert(ex); env->ThrowNew(ex, nullptr); return NULL; } // convert ASN1Message to message message *msg_out = nullptr; msg_out = ::ASN1Message_to_message(msg_asn1, NULL, false, 0); // msg_asn1 gets moved, so dont free it if (msg_out == nullptr) { jclass ex = env->FindClass("java/lang/IllegalStateException"); assert(ex); env->ThrowNew(ex, nullptr); return NULL; } // Convert message to java class Message jobject msg_ = nullptr; jclass clazz_dst_ = findClass(env, "foundation/pEp/jniadapter/Message"); assert(clazz_dst_); jmethodID constructor_dst_ = env->GetMethodID(clazz_dst_, "", "(J)V"); assert(constructor_dst_); msg_ = env->NewObject(clazz_dst_, constructor_dst_, reinterpret_cast(msg_out)); // msg_ will point to msg_out, so dont free it if (msg_ == nullptr) { jclass ex = env->FindClass("java/lang/IllegalStateException"); assert(ex); env->ThrowNew(ex, nullptr); return NULL; } return msg_; } || apply "*[name(.)!='enum']", 0, mode=entry { with "name", "@name"; with "class" call "CamelCase" with "text", "@name"; } || } // extern "C" || } } function "mangle" { param "type"; param "name"; param "classname" call "CamelCase" with "text", "../@name"; > «concat('Java_foundation_pEp_jniadapter_', $classname, '__1', str:replace($name, '_', '_1'))» } template "*", mode=entry { param "name"; param "class"; const "ctype" call "toC" with "type", "name(.)"; const "jname" call "CamelCase" with "text", "name(*[1])"; const "cname" call "lcase" with "text", "name(*[1])"; const "type", "name(.)"; const "getname" call "mangle" { with "type", "$type"; with "name", "concat('get', $jname)"; } const "setname" call "mangle" { with "type", "$type"; with "name", "concat('set', $jname)"; } const "type_ret" call "jni_type" with "type", "name(.)"; || // CodeGen: Getter JNIEXPORT «$type_ret» JNICALL «$getname»(JNIEnv *env, jobject obj) { pEpLog("called"); «$name»* _obj = nullptr; try { _obj = «$name»_ptr(env, obj); } catch(...) { jclass ex = env->FindClass("java/lang/IllegalStateException"); assert(ex); env->ThrowNew(ex, nullptr); return static_cast<«$type_ret»>(NULL); } || choose { when "../enum[@name=$type]" |> return _obj->«$cname»; otherwise |> return from_«$type»(env, _obj->«$cname»); } || } // CodeGen: Setter JNIEXPORT void JNICALL «$setname»(JNIEnv *env, jobject obj, `call "jni_type" with "type", "name(.)"` value) { pEpLog("called"); «$name»* _obj = nullptr; try { _obj = «$name»_ptr(env, obj); } catch(...) { jclass ex = env->FindClass("java/lang/IllegalStateException"); assert(ex); env->ThrowNew(ex, nullptr); return; } || choose { when "../enum[@name=$type]" |> _obj->«$cname» = static_cast<«$ctype»>(value); otherwise { choose { when "$type = 'string'" { |> free(_obj->«$cname»); } otherwise { const "free" choose { when "$ctype = 'pEp_identity'" > identity when "contains($ctype, '_t')" value "substring-before($ctype, '_t')"; otherwise value "$ctype"; } |> free_«$free»(_obj->«$cname»); } } |> if(value) { choose { when "$type = 'string'" { |>> _obj->«$cname» = to_«$type»(env, value); } otherwise { |>> _obj->«$cname» = to_«$type»(env, value); } } |> } else { |> _obj->«$cname» = NULL; |> } } } || } || } }