diff --git a/build/android/Android.mk b/build/android/Android.mk index b46664b61..7fb75d0a4 100755 --- a/build/android/Android.mk +++ b/build/android/Android.mk @@ -21,7 +21,6 @@ LOCAL_PATH:= $(call my-dir)/../../coreapi - include $(CLEAR_VARS) include $(linphone-root-dir)/submodules/linphone/build/android/common.mk @@ -39,3 +38,11 @@ LOCAL_MODULE := liblinphone include $(BUILD_SHARED_LIBRARY) $(call import-module,android/cpufeatures) + + +ifeq ($(BUILD_REMOTE_PROVISIONING),1) + +include $(linphone-root-dir)/submodules/linphone/build/android/xml2lpc.mk +include $(linphone-root-dir)/submodules/linphone/build/android/lpc2xml.mk + +endif diff --git a/build/android/lpc2xml.mk b/build/android/lpc2xml.mk new file mode 100644 index 000000000..f7858f94d --- /dev/null +++ b/build/android/lpc2xml.mk @@ -0,0 +1,47 @@ +## +## Android.mk -Android build script- +## +## +## Copyright (C) 2013 Belledonne Communications, Grenoble, France +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +## + +LOCAL_PATH:= $(call my-dir)/../../tools + +include $(CLEAR_VARS) + +LOCAL_CPP_EXTENSION := .cc + +LOCAL_SRC_FILES := \ + lpc2xml.c \ + lpc2xml_jni.cc \ + +LOCAL_CFLAGS += -DIN_LINPHONE + +LOCAL_C_INCLUDES = \ + $(LOCAL_PATH)/../coreapi \ + $(LOCAL_PATH)/../oRTP/include \ + $(LOCAL_PATH)/../mediastreamer2/include \ + $(LOCAL_PATH)/../../externals/libxml2/include \ + $(LOCAL_PATH)/../../externals/build/libxml2 \ + +LOCAL_SHARED_LIBRARIES = \ + libxml2 \ + liblinphone \ + +LOCAL_MODULE := liblpc2xml + +include $(BUILD_SHARED_LIBRARY) diff --git a/build/android/xml2lpc.mk b/build/android/xml2lpc.mk new file mode 100644 index 000000000..32bfb38c3 --- /dev/null +++ b/build/android/xml2lpc.mk @@ -0,0 +1,47 @@ +## +## Android.mk -Android build script- +## +## +## Copyright (C) 2013 Belledonne Communications, Grenoble, France +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +## + +LOCAL_PATH:= $(call my-dir)/../../tools + +include $(CLEAR_VARS) + +LOCAL_CPP_EXTENSION := .cc + +LOCAL_SRC_FILES := \ + xml2lpc.c \ + xml2lpc_jni.cc \ + +LOCAL_CFLAGS += -DIN_LINPHONE + +LOCAL_C_INCLUDES = \ + $(LOCAL_PATH)/../coreapi \ + $(LOCAL_PATH)/../oRTP/include \ + $(LOCAL_PATH)/../mediastreamer2/include \ + $(LOCAL_PATH)/../../externals/libxml2/include \ + $(LOCAL_PATH)/../../externals/build/libxml2 \ + +LOCAL_SHARED_LIBRARIES = \ + libxml2 \ + liblinphone \ + +LOCAL_MODULE := libxml2lpc + +include $(BUILD_SHARED_LIBRARY) diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index 8b2d2b519..9629688c7 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -2239,6 +2239,18 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_getConfig(JNIEnv *env, return (jlong) linphone_core_get_config((LinphoneCore *)lc); } +extern "C" jlong Java_org_linphone_core_LpConfigImpl_newLpConfigImpl(JNIEnv *env, jobject thiz, jstring file) { + const char *cfile = env->GetStringUTFChars(file, NULL); + LpConfig *lp = lp_config_new(cfile); + env->ReleaseStringUTFChars(file, cfile); + return (jlong) lp; +} + +extern "C" void Java_org_linphone_core_LpConfigImpl_delete(JNIEnv *env, jobject thiz, jlong lpc) { + LpConfig *lp = (LpConfig *)lpc; + lp_config_destroy(lp); +} + extern "C" void Java_org_linphone_core_LpConfigImpl_setInt(JNIEnv *env, jobject thiz, jlong lpc, jstring section, jstring key, jint value) { const char *csection = env->GetStringUTFChars(section, NULL); diff --git a/java/common/org/linphone/core/LinphoneCoreFactory.java b/java/common/org/linphone/core/LinphoneCoreFactory.java index 100794016..399b9ec8d 100644 --- a/java/common/org/linphone/core/LinphoneCoreFactory.java +++ b/java/common/org/linphone/core/LinphoneCoreFactory.java @@ -67,6 +67,7 @@ abstract public class LinphoneCoreFactory { * @return */ abstract public LinphoneAddress createLinphoneAddress(String address); + abstract public LpConfig createLpConfig(String file); abstract public LinphoneProxyConfig createProxyConfig(String identity, String proxy,String route,boolean enableRegister) throws LinphoneCoreException; /** diff --git a/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java b/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java index 04b6af1cf..2e5c4cf59 100644 --- a/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java +++ b/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java @@ -105,6 +105,11 @@ public class LinphoneCoreFactoryImpl extends LinphoneCoreFactory { public LinphoneAddress createLinphoneAddress(String identity) { return new LinphoneAddressImpl(identity); } + + @Override + public LpConfig createLpConfig(String file) { + return new LpConfigImpl(file); + } @Override public LinphoneCore createLinphoneCore(LinphoneCoreListener listener, diff --git a/java/impl/org/linphone/core/LpConfigImpl.java b/java/impl/org/linphone/core/LpConfigImpl.java index 1cb705ec2..27bd63d13 100644 --- a/java/impl/org/linphone/core/LpConfigImpl.java +++ b/java/impl/org/linphone/core/LpConfigImpl.java @@ -27,6 +27,15 @@ class LpConfigImpl implements LpConfig { public LpConfigImpl(long ptr) { nativePtr=ptr; } + + private native long newLpConfigImpl(String file); + private native void delete(long ptr); + public LpConfigImpl(String file) { + nativePtr = newLpConfigImpl(file); + } + protected void finalize() throws Throwable { + delete(nativePtr); + } private native void setInt(long ptr, String section, String key, int value); public void setInt(String section, String key, int value) { diff --git a/java/impl/org/linphone/tools/Lpc2Xml.java b/java/impl/org/linphone/tools/Lpc2Xml.java new file mode 100644 index 000000000..97ef99637 --- /dev/null +++ b/java/impl/org/linphone/tools/Lpc2Xml.java @@ -0,0 +1,68 @@ +package org.linphone.tools; + +import org.linphone.core.LpConfig; +import org.linphone.mediastream.Log; + +public class Lpc2Xml { + + private enum LogLevel { + DEBUG, + MESSAGE, + WARNING, + ERROR, + } + + private static boolean mAvailable; + + private long internalPtr = 0; + + private native void init(); + private native void destroy(); + + public Lpc2Xml() { + init(); + } + + public void finalize() { + destroy(); + } + + public native int setLpc(LpConfig lpc); + + public native int convertFile(String file); + public native int convertString(StringBuffer content); + + public void printLog(int level, String message) { + if(level > 0 && level < LogLevel.values().length) { + switch(LogLevel.values()[level]) { + case DEBUG: + Log.d(message); + break; + case MESSAGE: + Log.i(message); + break; + case WARNING: + Log.w(message); + break; + case ERROR: + Log.e(message); + break; + } + } + } + + static boolean isAvailable() { + return mAvailable; + } + + // Load library + static { + try { + System.loadLibrary("xml2"); + System.loadLibrary("lpc2xml"); + mAvailable = true; + } catch (Throwable e) { + mAvailable = false; + } + } +} diff --git a/java/impl/org/linphone/tools/Xml2Lpc.java b/java/impl/org/linphone/tools/Xml2Lpc.java new file mode 100644 index 000000000..9f6cb0f27 --- /dev/null +++ b/java/impl/org/linphone/tools/Xml2Lpc.java @@ -0,0 +1,72 @@ +package org.linphone.tools; + +import org.linphone.core.LpConfig; +import org.linphone.mediastream.Log; + +public class Xml2Lpc { + + private enum LogLevel { + DEBUG, + MESSAGE, + WARNING, + ERROR + } + + private static boolean mAvailable; + + private long internalPtr = 0; + + private native void init(); + private native void destroy(); + + public Xml2Lpc() { + init(); + } + + public void finalize() { + destroy(); + } + + public native int setXmlFile(String filename); + public native int setXmlString(String content); + + public native int setXsdFile(String filename); + public native int setXsdString(String content); + + public native int validate(); + public native int convert(LpConfig config); + + public void printLog(int level, String message) { + if(level > 0 && level < LogLevel.values().length) { + switch(LogLevel.values()[level]) { + case DEBUG: + Log.d(message); + break; + case MESSAGE: + Log.i(message); + break; + case WARNING: + Log.w(message); + break; + case ERROR: + Log.e(message); + break; + } + } + } + + public static boolean isAvailable() { + return mAvailable; + } + + // Load library + static { + try { + System.loadLibrary("xml2"); + System.loadLibrary("xml2lpc"); + mAvailable = true; + } catch (Throwable e) { + mAvailable = false; + } + } +} diff --git a/tools/Makefile.am b/tools/Makefile.am index ffb469214..a93d809f1 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -11,6 +11,8 @@ COMMON_CFLAGS=\ $(STRICT_OPTIONS) \ $(LIBXML2_CFLAGS) +EXTRA_DIST=xml2lpc_jni.cc lpc2xml_jni.cc + if BUILD_TOOLS lib_LTLIBRARIES=libxml2lpc.la liblpc2xml.la diff --git a/tools/lpc2xml.c b/tools/lpc2xml.c index feabdde2e..97262861c 100644 --- a/tools/lpc2xml.c +++ b/tools/lpc2xml.c @@ -57,11 +57,11 @@ void lpc2xml_context_destroy(lpc2xml_context *ctx) { } free(ctx); } -/* + static void lpc2xml_context_clear_logs(lpc2xml_context *ctx) { ctx->errorBuffer[0]='\0'; ctx->warningBuffer[0]='\0'; -}*/ +} static void lpc2xml_log(lpc2xml_context *xmlCtx, int level, const char *fmt, ...) { va_list args; @@ -72,6 +72,24 @@ static void lpc2xml_log(lpc2xml_context *xmlCtx, int level, const char *fmt, ... va_end(args); } +static void lpc2xml_genericxml_error(void *ctx, const char *fmt, ...) { + lpc2xml_context *xmlCtx = (lpc2xml_context *)ctx; + int sl = strlen(xmlCtx->errorBuffer); + va_list args; + va_start(args, fmt); + vsnprintf(xmlCtx->errorBuffer + sl, LPC2XML_BZ-sl, fmt, args); + va_end(args); +} + +static void lpc2xml_genericxml_warning(void *ctx, const char *fmt, ...) { + lpc2xml_context *xmlCtx = (lpc2xml_context *)ctx; + int sl = strlen(xmlCtx->warningBuffer); + va_list args; + va_start(args, fmt); + vsnprintf(xmlCtx->warningBuffer + sl, LPC2XML_BZ-sl, fmt, args); + va_end(args); +} + static int processEntry(const char *section, const char *entry, xmlNode *node, lpc2xml_context *ctx) { const char *content = lp_config_get_string(ctx->lpc, section, entry, NULL); if(content == NULL) { @@ -195,36 +213,69 @@ int lpc2xml_set_lpc(lpc2xml_context* context, const LpConfig *lpc) { } int lpc2xml_convert_file(lpc2xml_context* context, const char *filename) { - int ret = 0; + int ret = -1; + lpc2xml_context_clear_logs(context); + xmlSetGenericErrorFunc(context, lpc2xml_genericxml_error); xmlSaveCtxtPtr save_ctx = xmlSaveToFilename(filename, "UTF-8", XML_SAVE_FORMAT); - ret = internal_convert_lpc2xml(context); - if(ret == 0) { - ret = xmlSaveDoc(save_ctx, context->doc); + if(save_ctx != NULL) { + ret = internal_convert_lpc2xml(context); + if(ret == 0) { + ret = xmlSaveDoc(save_ctx, context->doc); + if(ret != 0) { + lpc2xml_log(context, LPC2XML_ERROR, "Can't save document"); + lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer); + } + } + xmlSaveClose(save_ctx); + } else { + lpc2xml_log(context, LPC2XML_ERROR, "Can't open file:%s", filename); + lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer); } - xmlSaveClose(save_ctx); return ret; } int lpc2xml_convert_fd(lpc2xml_context* context, int fd) { - int ret = 0; + int ret = -1; + lpc2xml_context_clear_logs(context); + xmlSetGenericErrorFunc(context, lpc2xml_genericxml_error); xmlSaveCtxtPtr save_ctx = xmlSaveToFd(fd, "UTF-8", XML_SAVE_FORMAT); - ret = internal_convert_lpc2xml(context); - if(ret == 0) { - ret = xmlSaveDoc(save_ctx, context->doc); + if(save_ctx != NULL) { + ret = internal_convert_lpc2xml(context); + if(ret == 0) { + ret = xmlSaveDoc(save_ctx, context->doc); + if(ret != 0) { + lpc2xml_log(context, LPC2XML_ERROR, "Can't save document"); + lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer); + } + } + xmlSaveClose(save_ctx); + } else { + lpc2xml_log(context, LPC2XML_ERROR, "Can't open fd:%d", fd); + lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer); } - xmlSaveClose(save_ctx); return ret; } int lpc2xml_convert_string(lpc2xml_context* context, char **content) { - int ret = 0; + int ret = -1; xmlBufferPtr buffer = xmlBufferCreate(); + lpc2xml_context_clear_logs(context); + xmlSetGenericErrorFunc(context, lpc2xml_genericxml_error); xmlSaveCtxtPtr save_ctx = xmlSaveToBuffer(buffer, "UTF-8", XML_SAVE_FORMAT); - internal_convert_lpc2xml(context); - if(ret == 0) { - ret = xmlSaveDoc(save_ctx, context->doc); + if(save_ctx != NULL) { + ret = internal_convert_lpc2xml(context); + if(ret == 0) { + ret = xmlSaveDoc(save_ctx, context->doc); + if(ret != 0) { + lpc2xml_log(context, LPC2XML_ERROR, "Can't save document"); + lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer); + } + } + xmlSaveClose(save_ctx); + } else { + lpc2xml_log(context, LPC2XML_ERROR, "Can't initialize internal buffer"); + lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer); } - xmlSaveClose(save_ctx); if(ret == 0) { #if LIBXML_VERSION >= 20800 *content = (char *)xmlBufferDetach(buffer); diff --git a/tools/lpc2xml_jni.cc b/tools/lpc2xml_jni.cc new file mode 100644 index 000000000..c0971cbd5 --- /dev/null +++ b/tools/lpc2xml_jni.cc @@ -0,0 +1,123 @@ +/* +xml2lpc_jni.cc +Copyright (C) 2013 Belledonne Communications, Grenoble, France + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "my_jni.h" +extern "C" { +#include "lpc2xml.h" +} +#ifdef USE_JAVAH +#include "lpc2xml_jni.h" +#endif + +#include + +struct jni_lpc2xml_ctx { + JNIEnv *env; + jobject obj; + lpc2xml_context *ctx; +}; + +static bool update_and_check_context(jni_lpc2xml_ctx *jni_ctx, JNIEnv *env, jobject obj) { + if(jni_ctx != NULL && jni_ctx->ctx != NULL) { + jni_ctx->env = env; + jni_ctx->obj = obj; + return true; + } + return false; +} + +#define LPC2XML_CALLBACK_BUFFER_SIZE 1024 + +extern "C" void Java_org_linphone_tools_Lpc2Xml_callback (void *ctx, lpc2xml_log_level level, const char *fmt, va_list list) { + jni_lpc2xml_ctx *jni_ctx = (jni_lpc2xml_ctx *)ctx; + if(jni_ctx->ctx != NULL) { + JNIEnv *env = jni_ctx->env; + jobject obj = jni_ctx->obj; + + char buffer[LPC2XML_CALLBACK_BUFFER_SIZE]; + vsnprintf(buffer, LPC2XML_CALLBACK_BUFFER_SIZE, fmt, list); + jstring javaString = env->NewStringUTF(buffer); + jint javaLevel = level; + my_jni::callVoidMethod(env, obj, "Lpc2Xml", "printLog", "(ILjava/lang/String;)V", javaLevel, javaString); + } +} + +extern "C" void Java_org_linphone_tools_Lpc2Xml_init(JNIEnv *env, jobject obj) { + jni_lpc2xml_ctx *jni_ctx = new jni_lpc2xml_ctx(); + jni_ctx->env = env; + jni_ctx->obj = obj; + jni_ctx->ctx = lpc2xml_context_new(Java_org_linphone_tools_Lpc2Xml_callback, obj); + bool result = my_jni::setLongField(env, obj, "Lpc2Xml", "internalPtr", jni_ctx); + if(!result) { + lpc2xml_context_destroy(jni_ctx->ctx); + delete jni_ctx; + } +} + +extern "C" void Java_org_linphone_tools_Lpc2Xml_destroy(JNIEnv *env, jobject obj) { + jni_lpc2xml_ctx *jni_ctx = my_jni::getLongField(env, obj, "Lpc2Xml", "internalPtr"); + if(jni_ctx != NULL) { + jni_ctx->env = env; + jni_ctx->obj = obj; + + if(jni_ctx->ctx != NULL) { + lpc2xml_context_destroy(jni_ctx->ctx); + } + delete jni_ctx; + my_jni::setLongField(env, obj, "Lpc2Xml", "internalPtr", NULL); + } +} + +extern "C" jint Java_org_linphone_tools_Lpc2Xml_setLpc(JNIEnv *env, jobject obj, jobject javaLpc) { + jni_lpc2xml_ctx *jni_ctx = my_jni::getLongField(env, obj, "Lpc2Xml", "internalPtr"); + jint ret = -666; + if(update_and_check_context(jni_ctx, env, obj)) { + LpConfig *lpc = my_jni::getLongField(env, javaLpc, "LpConfigImpl", "nativePtr"); + if(lpc != NULL) { + lpc2xml_set_lpc(jni_ctx->ctx, lpc); + } + } + return ret; +} + +extern "C" jint Java_org_linphone_tools_Lpc2Xml_convertFile(JNIEnv *env, jobject obj, jstring javaFile) { + jni_lpc2xml_ctx *jni_ctx = my_jni::getLongField(env, obj, "Lpc2Xml", "internalPtr"); + jint ret = -666; + if(update_and_check_context(jni_ctx, env, obj)) { + const char *file = env->GetStringUTFChars(javaFile, 0); + ret = lpc2xml_convert_file(jni_ctx->ctx, file); + env->ReleaseStringChars(javaFile, (jchar *)file); + } + return ret; +} + +extern "C" jint Java_org_linphone_tools_Lpc2Xml_convertString(JNIEnv *env, jobject obj, jobject javaStringBuffer) { + jni_lpc2xml_ctx *jni_ctx = my_jni::getLongField(env, obj, "Lpc2Xml", "internalPtr"); + jint ret = -666; + if(update_and_check_context(jni_ctx, env, obj)) { + char *string = NULL; + ret = lpc2xml_convert_string(jni_ctx->ctx, &string); + if(string != NULL) { + jstring javaString = env->NewStringUTF(string); + my_jni::callObjectMethod(env, obj, "StringBuffer", "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;", javaString); + env->ReleaseStringChars(javaString, (jchar *)string); + } + } + return ret; +} diff --git a/tools/my_jni.h b/tools/my_jni.h new file mode 100644 index 000000000..ce56829ec --- /dev/null +++ b/tools/my_jni.h @@ -0,0 +1,108 @@ +/* +my_jni.cc +Copyright (C) 2013 Belledonne Communications, Grenoble, France + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __MY_JNI__H +#define __MY_JNI__H +#include +extern "C" { +#include "linphonecore_utils.h" +} + +#define defCallMethod(Type) \ +template \ +static ReturnType call##Type##Method(JNIEnv *env, jobject obj, const char *className, const char *methodName, \ + const char *methodSignature, ...) { \ + jclass my_class = env->GetObjectClass(obj); \ + if(my_class == 0) { \ + ms_error("Can't get %s JNI class", className); \ + return NULL; \ + } \ + jmethodID my_method = env->GetMethodID(my_class, methodName, methodSignature); \ + if(my_method == 0) { \ + ms_error("Can't get %s %s %s method", className, methodSignature); \ + return NULL; \ + } \ + va_list vl; \ + va_start(vl, methodSignature); \ + ReturnType ret = env->Call##Type##MethodV(obj, my_method, vl); \ + va_end(vl); \ + return ret; \ +} \ + +#define defGetterTypeField(Type, JavaType, JavaStringType) \ +template \ +static ValueType get##Type##Field(JNIEnv *env, jobject obj, const char *className, const char *fieldName) { \ + jclass my_class = env->GetObjectClass(obj); \ + if(my_class == 0) { \ + ms_error("Can't get %s JNI class", className); \ + return NULL; \ + } \ + jfieldID my_field = env->GetFieldID(my_class, fieldName, JavaStringType); \ + if(my_field == 0) { \ + ms_error("Can't get %s %s field", className, fieldName); \ + return NULL; \ + } \ + return (ValueType) env->Get##Type##Field(obj, my_field); \ +} \ + +#define defSetterTypeField(Type, JavaType, JavaStringType) \ +template \ +static bool set##Type##Field(JNIEnv *env, jobject obj, const char *className, const char *fieldName, ValueType val) { \ + jclass my_class = env->GetObjectClass(obj); \ + if(my_class == 0) { \ + ms_error("Can't get %s JNI class", className); \ + return false; \ + } \ + jfieldID my_field = env->GetFieldID(my_class, fieldName, JavaStringType); \ + if(my_field == 0) { \ + ms_error("Can't get %s %s field", className, fieldName); \ + return false; \ + } \ + env->Set##Type##Field(obj, my_field, (JavaType) val); \ + return true; \ +} \ + +#define defGetterAndSetterTypeField(Type, JavaType, JavaStringType) \ + defGetterTypeField(Type, JavaType, JavaStringType) \ + defSetterTypeField(Type, JavaType, JavaStringType) \ + +namespace my_jni { + template + static void callVoidMethod(JNIEnv *env, jobject obj, const char *className, const char *methodName, + const char *methodSignature, ...) { + jclass my_class = env->GetObjectClass(obj); + if(my_class == 0) { + ms_error("Can't get %s JNI class", className); + return; + } + jmethodID my_method = env->GetMethodID(my_class, methodName, methodSignature); + if(my_method == 0) { + ms_error("Can't get %s %s %s method", className, methodName, methodSignature); + return; + } + va_list vl; + va_start(vl, methodSignature); + env->CallVoidMethodV(obj, my_method, vl); + va_end(vl); + } + defCallMethod(Object) + defGetterAndSetterTypeField(Long, jlong, "J") +} + +#endif //__MY_JNI__H diff --git a/tools/xml2lpc_jni.cc b/tools/xml2lpc_jni.cc new file mode 100644 index 000000000..fd72c6895 --- /dev/null +++ b/tools/xml2lpc_jni.cc @@ -0,0 +1,149 @@ +/* +xml2lpc_jni.cc +Copyright (C) 2013 Belledonne Communications, Grenoble, France + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "my_jni.h" +extern "C" { +#include "xml2lpc.h" +} +#ifdef USE_JAVAH +#include "xml2lpc_jni.h" +#endif + +#include + +struct jni_xml2lpc_ctx { + JNIEnv *env; + jobject obj; + xml2lpc_context *ctx; +}; + +static bool update_and_check_context(jni_xml2lpc_ctx *jni_ctx, JNIEnv *env, jobject obj) { + if(jni_ctx != NULL && jni_ctx->ctx != NULL) { + jni_ctx->env = env; + jni_ctx->obj = obj; + return true; + } + return false; +} + +#define XML2LPC_CALLBACK_BUFFER_SIZE 1024 + +extern "C" void Java_org_linphone_tools_Xml2Lpc_callback (void *ctx, xml2lpc_log_level level, const char *fmt, va_list list) { + jni_xml2lpc_ctx *jni_ctx = (jni_xml2lpc_ctx *)ctx; + if(jni_ctx->ctx != NULL) { + JNIEnv *env = jni_ctx->env; + jobject obj = jni_ctx->obj; + + char buffer[XML2LPC_CALLBACK_BUFFER_SIZE]; + vsnprintf(buffer, XML2LPC_CALLBACK_BUFFER_SIZE, fmt, list); + jstring javaString = env->NewStringUTF(buffer); + jint javaLevel = level; + my_jni::callVoidMethod(env, obj, "Xml2Lpc", "printLog", "(ILjava/lang/String;)V", javaLevel, javaString); + } +} + +extern "C" void Java_org_linphone_tools_Xml2Lpc_init(JNIEnv *env, jobject obj) { + jni_xml2lpc_ctx *jni_ctx = new jni_xml2lpc_ctx(); + jni_ctx->env = env; + jni_ctx->obj = obj; + jni_ctx->ctx = xml2lpc_context_new(Java_org_linphone_tools_Xml2Lpc_callback, jni_ctx); + bool result = my_jni::setLongField(env, obj, "Xml2Lpc", "internalPtr", jni_ctx); + if(!result) { + xml2lpc_context_destroy(jni_ctx->ctx); + delete jni_ctx; + } +} + +extern "C" void Java_org_linphone_tools_Xml2Lpc_destroy(JNIEnv *env, jobject obj) { + jni_xml2lpc_ctx *jni_ctx = my_jni::getLongField(env, obj, "Xml2Lpc", "internalPtr"); + if(jni_ctx != NULL) { + jni_ctx->env = env; + jni_ctx->obj = obj; + if(jni_ctx->ctx) { + xml2lpc_context_destroy(jni_ctx->ctx); + } + delete jni_ctx; + my_jni::setLongField(env, obj, "Xml2Lpc", "internalPtr", NULL); + } +} + +extern "C" jint Java_org_linphone_tools_Xml2Lpc_setXmlFile(JNIEnv *env, jobject obj, jstring javaXmlFile) { + jni_xml2lpc_ctx *jni_ctx = my_jni::getLongField(env, obj, "Xml2Lpc", "internalPtr"); + jint ret = -666; + if(update_and_check_context(jni_ctx, env, obj)) { + const char *xmlFile = env->GetStringUTFChars(javaXmlFile, 0); + ret = xml2lpc_set_xml_file(jni_ctx->ctx, xmlFile); + env->ReleaseStringChars(javaXmlFile, (jchar *)xmlFile); + } + return ret; +} + +extern "C" jint Java_org_linphone_tools_Xml2Lpc_setXmlString(JNIEnv *env, jobject obj, jstring javaXmlString) { + jni_xml2lpc_ctx *jni_ctx = my_jni::getLongField(env, obj, "Xml2Lpc", "internalPtr"); + jint ret = -666; + if(update_and_check_context(jni_ctx, env, obj)) { + const char *xmlString = env->GetStringUTFChars(javaXmlString, 0); + ret = xml2lpc_set_xml_string(jni_ctx->ctx, xmlString); + env->ReleaseStringChars(javaXmlString, (jchar *)xmlString); + } + return ret; +} + +extern "C" jint Java_org_linphone_tools_Xml2Lpc_setXsdFile(JNIEnv *env, jobject obj, jstring javaXsdFile) { + jni_xml2lpc_ctx *jni_ctx = my_jni::getLongField(env, obj, "Xml2Lpc", "internalPtr"); + jint ret = -666; + if(update_and_check_context(jni_ctx, env, obj)) { + const char *xsdFile = env->GetStringUTFChars(javaXsdFile, 0); + ret = xml2lpc_set_xsd_file(jni_ctx->ctx, xsdFile); + env->ReleaseStringChars(javaXsdFile, (jchar *)xsdFile); + } + return ret; +} + +extern "C" jint Java_org_linphone_tools_Xml2Lpc_setXsdString(JNIEnv *env, jobject obj, jstring javaXsdString) { + jni_xml2lpc_ctx *jni_ctx = my_jni::getLongField(env, obj, "Xml2Lpc", "internalPtr"); + jint ret = -666; + if(update_and_check_context(jni_ctx, env, obj)) { + const char *xsdString = env->GetStringUTFChars(javaXsdString, 0); + ret = xml2lpc_set_xsd_string(jni_ctx->ctx, xsdString); + env->ReleaseStringChars(javaXsdString, (jchar *)xsdString); + } + return ret; +} + +extern "C" jint Java_org_linphone_tools_Xml2Lpc_validate(JNIEnv *env, jobject obj) { + jni_xml2lpc_ctx *jni_ctx = my_jni::getLongField(env, obj, "Xml2Lpc", "internalPtr"); + jint ret = -666; + if(update_and_check_context(jni_ctx, env, obj)) { + ret = xml2lpc_validate(jni_ctx->ctx); + } + return ret; +} + +extern "C" jint Java_org_linphone_tools_Xml2Lpc_convert(JNIEnv *env, jobject obj, jobject javaLpc) { + jni_xml2lpc_ctx *jni_ctx = my_jni::getLongField(env, obj, "Xml2Lpc", "internalPtr"); + jint ret = -666; + if(update_and_check_context(jni_ctx, env, obj)) { + LpConfig *lpc = my_jni::getLongField(env, javaLpc, "LpConfigImpl", "nativePtr"); + if(lpc != NULL) { + ret = xml2lpc_convert(jni_ctx->ctx, lpc); + } + } + return ret; +}