diff --git a/tools/metadoc.py b/tools/metadoc.py
index 1cf932daf..fd985a11f 100644
--- a/tools/metadoc.py
+++ b/tools/metadoc.py
@@ -191,3 +191,8 @@ class SandcastleCSharpTranslator(Translator):
if len(lines) > 0:
lines.insert(0, '')
lines.append('')
+
+
+class SandcastleJavaTranslator(Translator):
+ def _tag_as_brief(self, lines):
+ pass
diff --git a/wrappers/csharp/genwrapper.py b/wrappers/csharp/genwrapper.py
index e5aad72a7..f83c68361 100644
--- a/wrappers/csharp/genwrapper.py
+++ b/wrappers/csharp/genwrapper.py
@@ -566,7 +566,7 @@ def render(renderer, item, path):
os.unlink(tmppath)
def main():
- argparser = argparse.ArgumentParser(description='Generate source files for the C++ wrapper')
+ argparser = argparse.ArgumentParser(description='Generate source files for the C# wrapper')
argparser.add_argument('xmldir', type=str, help='Directory where the XML documentation of the Linphone\'s API generated by Doxygen is placed')
argparser.add_argument('-o --output', type=str, help='the directory where to generate the source files', dest='outputdir', default='.')
argparser.add_argument('-n --name', type=str, help='the name of the genarated source file', dest='outputfile', default='LinphoneWrapper.cs')
diff --git a/wrappers/java/CMakeLists.txt b/wrappers/java/CMakeLists.txt
new file mode 100644
index 000000000..66b01ea38
--- /dev/null
+++ b/wrappers/java/CMakeLists.txt
@@ -0,0 +1,38 @@
+############################################################################
+# CMakeLists.txt
+# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+############################################################################
+
+add_custom_command(OUTPUT linphone_jni.cc
+ COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/genwrapper.py" "${PROJECT_BINARY_DIR}/coreapi/help/doc/doxygen/xml"
+ DEPENDS ${PROJECT_SOURCE_DIR}/tools/genapixml.py
+ ${PROJECT_SOURCE_DIR}/tools/metadoc.py
+ ${PROJECT_SOURCE_DIR}/tools/abstractapi.py
+ genwrapper.py
+ wrapper_impl.mustache
+ linphone-doc
+ "${PROJECT_BINARY_DIR}/coreapi/help/doc/doxygen/xml/index.xml"
+)
+
+add_custom_target(linphonej ALL DEPENDS linphone_jni.cc)
+
+#install(FILES ${CMAKE_CURRENT_BINARY_DIR}/linphone_jni.cc
+# DESTINATION ${CMAKE_INSTALL_DATADIR}/linphonej
+#)
diff --git a/wrappers/java/genwrapper.py b/wrappers/java/genwrapper.py
new file mode 100644
index 000000000..ca85ed3c0
--- /dev/null
+++ b/wrappers/java/genwrapper.py
@@ -0,0 +1,400 @@
+#!/usr/bin/python
+
+# Copyright (C) 2017 Belledonne Communications SARL
+#
+# 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., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+import argparse
+import os
+import sys
+import pystache
+import errno
+
+sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'tools'))
+print(sys.path)
+import genapixml as CApi
+import abstractapi as AbsApi
+import metadoc
+
+##########################################################################
+
+class JavaTranslator(object):
+ def __init__(self):
+ self.docTranslator = metadoc.SandcastleJavaTranslator()
+
+ def throws_exception(self, _type):
+ if type(_type) is AbsApi.BaseType:
+ if _type.name == 'status':
+ return True
+ return False
+
+ def translate_argument_name(self, _argName):
+ return _argName.to_snake_case()
+
+ def translate_type(self, _type, native=False):
+ if type(_type) is AbsApi.ListType:
+ ptrtype = ''
+ if type(_type.containedTypeDesc) is AbsApi.ClassType:
+ ptrtype = self.translate_type(_type.containedTypeDesc, native)
+ elif type(_type.containedTypeDesc) is AbsApi.BaseType:
+ ptrtype = self.translate_type(_type.containedTypeDesc, native)
+ elif type(_type.containedTypeDesc) is AbsApi.EnumType:
+ ptrtype = self.translate_type(_type.containedTypeDesc, native)
+ else:
+ if _type.containedTypeDesc:
+ raise AbsApi.Error('translation of bctbx_list_t of ' + _type.containedTypeDesc.name)
+ else:
+ raise AbsApi.Error('translation of bctbx_list_t of unknow type !')
+ return ptrtype + '[]'
+
+ elif type(_type) is AbsApi.ClassType:
+ if native:
+ return 'long'
+ return _type.desc.name.to_camel_case()
+ elif type(_type) is AbsApi.EnumType:
+ if native:
+ return 'int'
+ return _type.desc.name.to_camel_case()
+ elif type(_type) is AbsApi.BaseType:
+ if _type.name == 'string':
+ return 'String'
+ elif _type.name == 'integer':
+ return 'int'
+ elif _type.name == 'floatant':
+ return 'float'
+ elif _type.name == 'size':
+ return 'int'
+ return _type.name
+
+ def translate_argument(self, _arg, native=False):
+ return '{0} {1}'.format(self.translate_type(_arg.type, native), self.translate_argument_name(_arg.name))
+
+ def translate_property(self, _property):
+ properties = []
+ if _property.getter is not None:
+ properties.append(self.translate_method(_property.getter))
+ if _property.setter is not None:
+ properties.append(self.translate_method(_property.setter))
+ return properties
+
+ def translate_method(self, _method):
+ methodDict = {}
+
+ methodDict['return'] = self.translate_type(_method.returnType)
+ methodDict['return_native'] = self.translate_type(_method.returnType, True)
+ methodDict['return_keyword'] = '' if methodDict['return'] == 'void' else 'return '
+
+ methodDict['convertInputClassArrayToLongArray'] = False
+ methodDict['convertOutputClassArrayToLongArray'] = type(_method.returnType) is AbsApi.ListType and type(_method.returnType.containedTypeDesc) is AbsApi.ClassType
+ if methodDict['convertOutputClassArrayToLongArray']:
+ methodDict['native_params_impl_list_param_name'] = 'classArray'
+ methodDict['native_params_impl_list_param_type'] = self.translate_type(_method.returnType.containedTypeDesc)
+
+ methodDict['name'] = _method.name.to_camel_case(lower=True)
+ methodDict['exception'] = self.throws_exception(_method.returnType)
+
+ methodDict['params'] = ''
+ methodDict['native_params'] = 'long nativePtr'
+ methodDict['static_native_params'] = ''
+ methodDict['native_params_impl'] = ''
+ for arg in _method.args:
+ if arg is not _method.args[0]:
+ methodDict['params'] += ', '
+ methodDict['native_params'] += ', '
+ methodDict['native_params_impl'] += ', '
+
+ methodDict['params'] += self.translate_argument(arg)
+ methodDict['native_params'] += self.translate_argument(arg, True)
+ methodDict['static_native_params'] += self.translate_argument(arg, True)
+ if type(arg.type) is AbsApi.ClassType:
+ methodDict['native_params_impl'] += '((' + self.translate_type(arg.type) + ')' + self.translate_argument_name(arg.name) + ').nativePtr'
+ elif type(arg.type) is AbsApi.ListType:
+ if type(arg.type.containedTypeDesc) is AbsApi.ClassType:
+ methodDict['convertInputClassArrayToLongArray'] = True
+ methodDict['native_params_impl_list_param_name'] = self.translate_argument_name(arg.name)
+ methodDict['native_params_impl_list_param_type'] = self.translate_type(arg.type.containedTypeDesc) + 'Impl'
+ methodDict['native_params_impl'] += 'longArray'
+ else:
+ methodDict['native_params_impl'] += self.translate_argument_name(arg.name)
+ else:
+ methodDict['native_params_impl'] += self.translate_argument_name(arg.name)
+
+ methodDict['classicMethod'] = not methodDict['convertInputClassArrayToLongArray'] and not methodDict['convertOutputClassArrayToLongArray']
+ methodDict['deprecated'] = _method.deprecated
+ methodDict['doc'] = self.docTranslator.translate(_method.briefDescription) if _method.briefDescription is not None else None
+
+ return methodDict
+
+ def translate_class(self, _class):
+ classDict = {
+ 'methods' : [],
+ 'staticMethods' : [],
+ }
+
+ classDict['isLinphoneFactory'] = _class.name.to_camel_case() == "Factory"
+ classDict['doc'] = self.docTranslator.translate(_class.briefDescription) if _class.briefDescription is not None else None
+
+ for _property in _class.properties:
+ try:
+ classDict['methods'] += self.translate_property(_property)
+ except AbsApi.Error as e:
+ print('error while translating {0} property: {1}'.format(_property.name.to_snake_case(), e.args[0]))
+
+ for method in _class.instanceMethods:
+ try:
+ methodDict = self.translate_method(method)
+ classDict['methods'].append(methodDict)
+ except AbsApi.Error as e:
+ print('Could not translate {0}: {1}'.format(method.name.to_snake_case(fullName=True), e.args[0]))
+
+ for method in _class.classMethods:
+ try:
+ methodDict = self.translate_method(method)
+ classDict['staticMethods'].append(methodDict)
+ except AbsApi.Error as e:
+ print('Could not translate {0}: {1}'.format(method.name.to_snake_case(fullName=True), e.args[0]))
+
+ return classDict
+
+ def translate_interface(self, _class):
+ interfaceDict = {
+ 'methods' : [],
+ }
+
+ interfaceDict['doc'] = self.docTranslator.translate(_class.briefDescription)
+
+ for method in _class.methods:
+ interfaceDict['methods'].append(self.translate_method(method))
+
+ return interfaceDict
+
+ def translate_enum(self, _class):
+ enumDict = {}
+
+ enumDict['name'] = _class.name.to_camel_case()
+ enumDict['doc'] = self.docTranslator.translate(_class.briefDescription)
+ enumDict['values'] = []
+ i = 0
+ lastValue = None
+
+ for enumValue in _class.values:
+ enumValDict = {}
+ enumValDict['name'] = enumValue.name.to_camel_case()
+ enumValDict['doc'] = self.docTranslator.translate(enumValue.briefDescription)
+ if type(enumValue.value) is int:
+ lastValue = enumValue.value
+ enumValDict['value'] = str(enumValue.value)
+ elif type(enumValue.value) is AbsApi.Flag:
+ enumValDict['value'] = '1<<' + str(enumValue.value.position)
+ else:
+ if lastValue is not None:
+ enumValDict['value'] = lastValue + 1
+ lastValue += 1
+ else:
+ enumValDict['value'] = i
+ i += 1
+ enumValDict['commarorsemicolon'] = ';' if i == len(_class.values) else ','
+ enumDict['values'].append(enumValDict)
+
+ return enumDict
+
+##########################################################################
+
+class JavaEnum(object):
+ def __init__(self, _enum, translator):
+ self._class = translator.translate_enum(_enum)
+ self.packageName = "org.linphone"
+ self.className = _enum.name.to_camel_case()
+ self.filename = self.className + ".java"
+ self.values = self._class['values']
+ self.doc = self._class['doc']
+ self.jniMethods = []
+
+class JavaInterface(object):
+ def __init__(self, _interface, translator):
+ self._class = translator.translate_interface(_interface)
+ self.packageName = "org.linphone"
+ self.className = _interface.name.to_camel_case()
+ self.filename = self.className + ".java"
+ self.imports = []
+ self.methods = self._class['methods']
+ self.doc = self._class['doc']
+ self.jniMethods = []
+
+class JavaInterfaceStub(object):
+ def __init__(self, _interface):
+ self.packageName = _interface.packageName
+ self.className = _interface.className
+ self.classNameStub = self.className + "Stub"
+ self.filename = self.className + "Stub.java"
+ self.methods = _interface.methods
+
+class JavaClass(object):
+ def __init__(self, _class, translator):
+ self._class = translator.translate_class(_class)
+ self.isLinphoneFactory = self._class['isLinphoneFactory']
+ self.packageName = "org.linphone"
+ self.className = _class.name.to_camel_case()
+ self.classImplName = self.className + "Impl"
+ self.filename = self.className + ".java"
+ self.imports = []
+ self.methods = self._class['methods']
+ self.staticMethods = self._class['staticMethods']
+ self.doc = self._class['doc']
+ self.jniMethods = []
+ self.enums = []
+
+ def add_enum(self, enum):
+ if enum.className.startswith(self.className):
+ enum.className = enum.className[len(self.className):]
+ self.enums.append(enum)
+
+class Jni(object):
+ def __init__(self):
+ self.methods = {}
+
+ def add_methods(self, name, methods):
+ self.methods[name] = methods
+
+##########################################################################
+
+class GenWrapper(object):
+ def __init__(self, srcdir, javadir, xmldir):
+ self.srcdir = srcdir
+ self.javadir = javadir
+
+ project = CApi.Project()
+ project.initFromDir(xmldir)
+ project.check()
+
+ self.parser = AbsApi.CParser(project)
+ self.parser.parse_all()
+ self.translator = JavaTranslator()
+ self.renderer = pystache.Renderer()
+ self.jni = Jni()
+
+ self.enums = {}
+ self.interfaces = {}
+ self.classes = {}
+ self.enums_list = {
+ 'CallState': 'Call',
+ 'ChatMessageState': 'ChatMessage',
+ 'ConfiguringState': 'Core',
+ 'CoreLogCollectionUploadState': 'Core',
+ 'GlobalState': 'Core',
+ 'RegistrationState': 'Core',
+ }
+ self.enums_to_remove = []
+
+ def render_all(self):
+ for _interface in self.parser.interfacesIndex.values():
+ self.render_java_interface(_interface)
+ for _class in self.parser.classesIndex.values():
+ self.render_java_class(_class)
+ for _enum in self.parser.enumsIndex.items():
+ if _enum[1] is not None:
+ self.render_java_enum(_enum[1])
+
+ for name, value in self.enums.iteritems():
+ if name in self.enums_list:
+ className = self.enums_list[name]
+ print 'Enum ' + name + ' belongs to class ' + className
+ self.classes[className].add_enum(value)
+ self.enums_to_remove.append(name)
+
+ for enum in self.enums_to_remove:
+ self.enums.pop(enum, None)
+
+ for name, value in self.enums.iteritems():
+ self.render(value, self.javadir + '/' + value.filename)
+ for name, value in self.interfaces.iteritems():
+ self.render(value, self.javadir + '/' + value.filename)
+ for name, value in self.classes.iteritems():
+ self.render(value, self.javadir + '/' + value.filename)
+
+ self.render(self.jni, self.srcdir + '/linphone_jni.cc')
+
+ def render(self, item, path):
+ tmppath = path + '.tmp'
+ content = ''
+ with open(tmppath, mode='w') as f:
+ f.write(self.renderer.render(item))
+ with open(tmppath, mode='rU') as f:
+ content = f.read()
+ with open(path, mode='w') as f:
+ f.write(content)
+ os.unlink(tmppath)
+
+ def render_java_enum(self, _class):
+ if _class is not None:
+ try:
+ javaenum = JavaEnum(_class, self.translator)
+ self.enums[javaenum.className] = javaenum
+ except AbsApi.Error as e:
+ print('Could not translate {0}: {1}'.format(_class.name.to_camel_case(fullName=True), e.args[0]))
+ self.jni.add_methods(javaenum.className, javaenum.jniMethods)
+
+ def render_java_interface(self, _class):
+ if _class is not None:
+ try:
+ javainterface = JavaInterface(_class, self.translator)
+ self.interfaces[javainterface.className] = javainterface
+ javaInterfaceStub = JavaInterfaceStub(javainterface)
+ self.interfaces[javaInterfaceStub.className] = javaInterfaceStub
+ except AbsApi.Error as e:
+ print('Could not translate {0}: {1}'.format(_class.name.to_camel_case(fullName=True), e.args[0]))
+ self.jni.add_methods(javainterface.className, javainterface.jniMethods)
+
+ def render_java_class(self, _class):
+ if _class is not None:
+ try:
+ javaclass = JavaClass(_class, self.translator)
+ self.classes[javaclass.className] = javaclass
+ except AbsApi.Error as e:
+ print('Could not translate {0}: {1}'.format(_class.name.to_camel_case(fullName=True), e.args[0]))
+ self.jni.add_methods(javaclass.className, javaclass.jniMethods)
+
+##########################################################################
+
+def main():
+ argparser = argparse.ArgumentParser(description='Generate source files for the Java wrapper')
+ argparser.add_argument('xmldir', type=str, help='Directory where the XML documentation of the Linphone\'s API generated by Doxygen is placed')
+ argparser.add_argument('-o --output', type=str, help='the directory where to generate the source files', dest='outputdir', default='.')
+ argparser.add_argument('-n --name', type=str, help='the name of the genarated source file', dest='outputfile', default='linphone_jni.cc')
+ args = argparser.parse_args()
+
+ srcdir = args.outputdir + '/src'
+ javadir = args.outputdir + '/java'
+
+ try:
+ os.makedirs(srcdir)
+ except OSError as e:
+ if e.errno != errno.EEXIST:
+ print("Cannot create '{0}' dircetory: {1}".format(srcdir, e.strerror))
+ sys.exit(1)
+
+ try:
+ os.makedirs(javadir)
+ except OSError as e:
+ if e.errno != errno.EEXIST:
+ print("Cannot create '{0}' dircetory: {1}".format(javadir, e.strerror))
+ sys.exit(1)
+
+ genwrapper = GenWrapper(srcdir, javadir, args.xmldir)
+ genwrapper.render_all()
+
+if __name__ == '__main__':
+ main()
diff --git a/wrappers/java/java_class.mustache b/wrappers/java/java_class.mustache
new file mode 100644
index 000000000..cd8284ea9
--- /dev/null
+++ b/wrappers/java/java_class.mustache
@@ -0,0 +1,156 @@
+/*
+{{className}}.java
+Copyright (C) 2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+package {{packageName}}
+
+{{#imports}}
+import {{import}}
+{{/imports}}
+{{#isLinphoneFactory}}
+import org.linphone.mediastream.Version;
+{{/isLinphoneFactory}}
+
+{{#doc}}
+/**
+ {{#lines}}
+ * {{line}}
+ {{/lines}}
+ */
+{{/doc}}
+public interface {{className}} {
+{{#enums}}
+ enum {{className}} {
+ {{#values}}
+ {{#doc}}
+ /**
+ {{#lines}}
+ * {{line}}
+ {{/lines}}
+ */
+ {{/doc}}
+ {{name}}({{value}}){{commarorsemicolon}}
+
+ {{/values}}
+ protected final int mValue;
+
+ private {{className}} (int value) {
+ mValue = value;
+ }
+
+ static protected {{className}} fromInt(int value) throws CoreException {
+ switch(value) {
+ {{#values}}
+ case {{value}}: return {{name}};
+ {{/values}}
+ default:
+ throw new CoreException("Unhandled enum value " + value + " for {{className}}");
+ }
+ }
+ };
+
+{{/enums}}
+{{#isLinphoneFactory}}
+
+{{/isLinphoneFactory}}
+{{#methods}}
+ {{#doc}}
+ /**
+ {{#lines}}
+ * {{line}}
+ {{/lines}}
+ */
+ {{/doc}}
+ {{#deprecated}}@deprecated
+ {{/deprecated}}public {{return}} {{name}}({{params}}){{#exception}} throws CoreException{{/exception}};
+
+{{/methods}}
+
+{{#staticMethods}}
+ {{#doc}}
+ /**
+ {{#lines}}
+ * {{line}}
+ {{/lines}}
+ */
+ {{/doc}}
+ public {{return}} {{name}}({{params}}){{#exception}} throws CoreException{{/exception}};
+
+{{/staticMethods}}
+}
+
+class {{classImplName}} implements {{className}} {
+
+ protected long nativePtr = 0;
+
+{{#isLinphoneFactory}}
+ private static boolean loadOptionalLibrary(String s) {
+ try {
+ System.loadLibrary(s);
+ return true;
+ } catch (Throwable e) {
+ android.util.Log.w("LinphoneCoreFactoryImpl", "Unable to load optional library " + s + ": " +e.getMessage());
+ }
+ return false;
+ }
+
+ static {
+ System.loadLibrary("gnustl_shared");
+ loadOptionalLibrary("ffmpeg-linphone");
+ System.loadLibrary("bctoolbox");
+ System.loadLibrary("ortp");
+ System.loadLibrary("mediastreamer_base");
+ System.loadLibrary("mediastreamer_voip");
+ System.loadLibrary("linphone");
+ Version.dumpCapabilities();
+ }
+{{/isLinphoneFactory}}
+
+{{#methods}}
+ private native {{return_native}} {{name}}({{native_params}});
+ public {{return}} {{name}}({{params}}) {{#exception}}throws CoreException{{/exception}} {
+ {{#convertInputClassArrayToLongArray}}
+ long[] longArray = new long[{{native_params_impl_list_param_name}}.length];
+ for (int i=0; i < {{native_params_impl_list_param_name}}.length; i++) {
+ longArray[i] = (({{native_params_impl_list_param_type}}){{native_params_impl_list_param_name}}[i]).nativePtr;
+ }
+ {{name}}(nativePtr{{native_params_impl}});
+ {{/convertInputClassArrayToLongArray}}
+ {{#convertOutputClassArrayToLongArray}}
+ long[] longArray = {{name}}(nativePtr{{native_params_impl}});
+ if (longArray == null) return null;
+
+ {{native_params_impl_list_param_type}}[] classArray = new {{native_params_impl_list_param_type}}[longArray.length];
+ for (int i=0; i < longArray.length; i++) {
+ classArray[i] = new {{native_params_impl_list_param_type}}Impl(longArray[i]);
+ }
+ return classArray;
+ {{/convertOutputClassArrayToLongArray}}
+ {{#classicMethod}}
+ {{return_keyword}}{{name}}(nativePtr{{native_params_impl}});
+ {{/classicMethod}}
+ }
+
+{{/methods}}
+
+{{#staticMethods}}
+ @Override
+ private native {{return_native}} {{name}}({{static_native_params}});
+
+{{/staticMethods}}
+}
\ No newline at end of file
diff --git a/wrappers/java/java_enum.mustache b/wrappers/java/java_enum.mustache
new file mode 100644
index 000000000..a890ff72e
--- /dev/null
+++ b/wrappers/java/java_enum.mustache
@@ -0,0 +1,60 @@
+/*
+{{className}}.java
+Copyright (C) 2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+package {{packageName}}
+
+{{#imports}}
+import {{import}}
+{{/imports}}
+
+{{#doc}}
+/**
+ {{#lines}}
+ * {{line}}
+ {{/lines}}
+ */
+{{/doc}}
+public enum {{className}} {
+{{#values}}
+ {{#doc}}
+ /**
+ {{#lines}}
+ * {{line}}
+ {{/lines}}
+ */
+ {{/doc}}
+ {{name}}({{value}}){{commarorsemicolon}}
+
+{{/values}}
+ protected final int mValue;
+
+ private {{className}} (int value) {
+ mValue = value;
+ }
+
+ static protected {{className}} fromInt(int value) throws CoreException {
+ switch(value) {
+ {{#values}}
+ case {{value}}: return {{name}};
+ {{/values}}
+ default:
+ throw new CoreException("Unhandled enum value " + value + " for {{className}}");
+ }
+ }
+}
\ No newline at end of file
diff --git a/wrappers/java/java_enum_old.mustache b/wrappers/java/java_enum_old.mustache
new file mode 100644
index 000000000..81f01e1bb
--- /dev/null
+++ b/wrappers/java/java_enum_old.mustache
@@ -0,0 +1,65 @@
+/*
+{{className}}.java
+Copyright (C) 2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+package {{packageName}}
+
+{{#imports}}
+import {{import}}
+{{/imports}}
+
+{{#doc}}
+/**
+ {{#lines}}
+ * {{line}}
+ {{/lines}}
+ */
+{{/doc}}
+static public class {{className}} {
+ static private Vector<{{className}}> values = new Vector<{{className}}>();
+{{#values}}
+
+ {{#doc}}
+ /**
+ {{#lines}}
+ * {{line}}
+ {{/lines}}
+ */
+ {{/doc}}
+ static public {{className}} {{name}} = new {{className}}({{value}}, {{name}});
+{{/values}}
+
+ protected final int mValue;
+ private final String mStringValue;
+
+ private {{className}}(int value, String stringValue) {
+ mValue = value;
+ values.addElement(this);
+ mStringValue = stringValue;
+ }
+ public static {{className}} fromInt(int value) {
+ for (int i = 0; i < values.size(); i++) {
+ {{className}} mstate = ({{className}}) values.elementAt(i);
+ if (mstate.mValue == value) return mstate;
+ }
+ throw new RuntimeException("{{className}} not found [" + value + "]");
+ }
+ public String toString() {
+ return mStringValue;
+ }
+}
\ No newline at end of file
diff --git a/wrappers/java/java_interface.mustache b/wrappers/java/java_interface.mustache
new file mode 100644
index 000000000..9832f7a8d
--- /dev/null
+++ b/wrappers/java/java_interface.mustache
@@ -0,0 +1,46 @@
+/*
+{{className}}.java
+Copyright (C) 2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+package {{packageName}}
+
+{{#imports}}
+import {{import}}
+{{/imports}}
+
+{{#doc}}
+/**
+ {{#lines}}
+ * {{line}}
+ {{/lines}}
+ */
+{{/doc}}
+public interface {{className}} {
+{{#methods}}
+ {{#doc}}
+ /**
+ {{#lines}}
+ * {{line}}
+ {{/lines}}
+ */
+ {{/doc}}
+ {{#deprecated}}@deprecated
+ {{/deprecated}}public {{return}} {{name}}({{params}}){{#exception}} throws CoreException{{/exception}};
+
+{{/methods}}
+}
\ No newline at end of file
diff --git a/wrappers/java/java_interface_stub.mustache b/wrappers/java/java_interface_stub.mustache
new file mode 100644
index 000000000..afb401674
--- /dev/null
+++ b/wrappers/java/java_interface_stub.mustache
@@ -0,0 +1,34 @@
+/*
+{{classNameStub}}.java
+Copyright (C) 2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+package {{packageName}}
+
+{{#imports}}
+import {{import}}
+{{/imports}}
+
+public class {{classNameStub}} implements {{className}} {
+{{#methods}}
+ @Override
+ public {{return}} {{name}}({{params}}){{#exception}} throws CoreException{{/exception}} {
+ // Auto-generated method stub
+ }
+
+{{/methods}}
+}
\ No newline at end of file
diff --git a/wrappers/java/jni.mustache b/wrappers/java/jni.mustache
new file mode 100644
index 000000000..7c5b17133
--- /dev/null
+++ b/wrappers/java/jni.mustache
@@ -0,0 +1,38 @@
+/*
+linphone_jni.cc
+Copyright (C) 2017 Belledonne Communications SARL
+
+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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include
+#include
+
+JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *ajvm, void *reserved) {
+#ifdef __ANDROID__
+ ms_set_jvm(ajvm);
+#endif /* __ANDROID__ */
+ jvm=ajvm;
+ return JNI_VERSION_1_2;
+}
+
+static const char* GetStringUTFChars(JNIEnv* env, jstring string) {
+ const char *cstring = string ? env->GetStringUTFChars(string, NULL) : NULL;
+ return cstring;
+}
+
+static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char *cstring) {
+ if (string) env->ReleaseStringUTFChars(string, cstring);
+}
\ No newline at end of file