summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--vpp-api/java/Makefile.am8
-rw-r--r--vpp-api/java/jvpp-core/io/fd/vpp/jvpp/core/test/LispAdjacencyTest.java124
-rw-r--r--vpp-api/java/jvpp-core/io/fd/vpp/jvpp/core/test/Readme.txt1
-rw-r--r--vpp-api/java/jvpp-core/jvpp_core.c4
-rwxr-xr-xvpp-api/java/jvpp/gen/jvpp_gen.py48
-rw-r--r--vpp-api/java/jvpp/gen/jvppgen/dto_gen.py2
-rw-r--r--vpp-api/java/jvpp/gen/jvppgen/jni_gen.py291
-rw-r--r--vpp-api/java/jvpp/gen/jvppgen/jvpp_c_gen.py286
-rw-r--r--vpp-api/java/jvpp/gen/jvppgen/types_gen.py227
-rw-r--r--vpp-api/java/jvpp/gen/jvppgen/util.py130
10 files changed, 779 insertions, 342 deletions
diff --git a/vpp-api/java/Makefile.am b/vpp-api/java/Makefile.am
index cdb83791d6d..390562b4d2a 100644
--- a/vpp-api/java/Makefile.am
+++ b/vpp-api/java/Makefile.am
@@ -92,11 +92,13 @@ jvpp-core/io_fd_vpp_jvpp_core_JVppCoreImpl.h: jvpp-registry/io_fd_vpp_jvpp_VppJN
cp -rf @srcdir@/jvpp-core/* -t jvpp-core/
mkdir -p jvpp-core/target
cd jvpp-core \
- && mkdir -p dto future callfacade callback notification \
+ && mkdir -p types dto future callfacade callback notification \
&& @srcdir@/jvpp/gen/jvpp_gen.py -i defs_vpp_papi.py --plugin_name core \
- && cp -rf dto future callfacade callback notification *.java -t $(packagedir_jvpp_core) \
- && rm -rf dto future callfacade callback notification *.java
+ && cp -rf types dto future callfacade callback notification *.java -t $(packagedir_jvpp_core) \
+ && rm -rf types dto future callfacade callback notification *.java
+
$(JAVAC) -classpath jvpp-registry/target -d jvpp-core/target jvpp-core/$(packagedir_jvpp_core)/*.java \
+ jvpp-core/$(packagedir_jvpp_core)/types/*.java \
jvpp-core/$(packagedir_jvpp_core)/dto/*.java \
jvpp-core/$(packagedir_jvpp_core)/callback/*.java \
jvpp-core/$(packagedir_jvpp_core)/notification/*.java \
diff --git a/vpp-api/java/jvpp-core/io/fd/vpp/jvpp/core/test/LispAdjacencyTest.java b/vpp-api/java/jvpp-core/io/fd/vpp/jvpp/core/test/LispAdjacencyTest.java
new file mode 100644
index 00000000000..d7f5039b152
--- /dev/null
+++ b/vpp-api/java/jvpp-core/io/fd/vpp/jvpp/core/test/LispAdjacencyTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.vpp.jvpp.core.test;
+
+import io.fd.vpp.jvpp.JVppRegistry;
+import io.fd.vpp.jvpp.JVppRegistryImpl;
+import io.fd.vpp.jvpp.core.JVppCoreImpl;
+import io.fd.vpp.jvpp.core.dto.LispAddDelAdjacency;
+import io.fd.vpp.jvpp.core.dto.LispAddDelLocalEid;
+import io.fd.vpp.jvpp.core.dto.LispAddDelLocatorSet;
+import io.fd.vpp.jvpp.core.dto.LispAddDelRemoteMapping;
+import io.fd.vpp.jvpp.core.dto.LispAdjacenciesGet;
+import io.fd.vpp.jvpp.core.dto.LispAdjacenciesGetReply;
+import io.fd.vpp.jvpp.core.dto.LispEnableDisable;
+import io.fd.vpp.jvpp.core.future.FutureJVppCoreFacade;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.ExecutionException;
+import java.util.logging.Logger;
+
+/**
+ * Tests lisp adjacency creation and read (custom vpe.api type support showcase).
+ */
+public class LispAdjacencyTest {
+
+ private static final Logger LOG = Logger.getLogger(LispAdjacencyTest.class.getName());
+
+ private static void enableLisp(final FutureJVppCoreFacade jvpp) throws ExecutionException, InterruptedException {
+ final LispEnableDisable request = new LispEnableDisable();
+ request.isEn = 1;
+ jvpp.lispEnableDisable(request).toCompletableFuture().get();
+ LOG.info("Lisp enabled successfully");
+ }
+
+ private static void addLocatorSet(final FutureJVppCoreFacade jvpp) throws ExecutionException, InterruptedException {
+ final LispAddDelLocatorSet request = new LispAddDelLocatorSet();
+ request.isAdd = 1;
+ request.locatorSetName = "ls1".getBytes(StandardCharsets.UTF_8);
+ jvpp.lispAddDelLocatorSet(request).toCompletableFuture().get();
+ LOG.info("Locator set created successfully:" + request.toString());
+ }
+
+ private static void addLocalEid(final FutureJVppCoreFacade jvpp) throws ExecutionException, InterruptedException {
+ final LispAddDelLocalEid request = new LispAddDelLocalEid();
+ request.isAdd = 1;
+ request.locatorSetName = "ls1".getBytes(StandardCharsets.UTF_8);
+ request.eid = new byte[] {1, 2, 1, 10};
+ request.eidType = 0; // ip4
+ request.vni = 0;
+ request.prefixLen = 32;
+ jvpp.lispAddDelLocalEid(request).toCompletableFuture().get();
+ LOG.info("Local EID created successfully:" + request.toString());
+ }
+
+ private static void addRemoteMapping(final FutureJVppCoreFacade jvpp)
+ throws ExecutionException, InterruptedException {
+ final LispAddDelRemoteMapping request = new LispAddDelRemoteMapping();
+ request.isAdd = 1;
+ request.vni = 0;
+ request.eid = new byte[] {1, 2, 1, 20};
+ request.eidLen = 32;
+ request.rlocNum = 1;
+ request.rlocs = new byte[] {1, 1, 1, 1, 2, 1, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ jvpp.lispAddDelRemoteMapping(request).toCompletableFuture().get();
+ LOG.info("Remote mapping created successfully:" + request.toString());
+ }
+
+ private static void addAdjacency(final FutureJVppCoreFacade jvpp) throws ExecutionException, InterruptedException {
+ final LispAddDelAdjacency request = new LispAddDelAdjacency();
+ request.isAdd = 1;
+ request.leid = new byte[] {1, 2, 1, 10};
+ request.leidLen = 32;
+ request.reid = new byte[] {1, 2, 1, 20};
+ request.reidLen = 32;
+ request.eidType = 0; // ip4
+ request.vni = 0;
+ jvpp.lispAddDelAdjacency(request).toCompletableFuture().get();
+ LOG.info("Lisp adjacency created successfully:" + request.toString());
+ }
+
+ private static void showAdjacencies(final FutureJVppCoreFacade jvpp)
+ throws ExecutionException, InterruptedException {
+ final LispAdjacenciesGetReply reply =
+ jvpp.lispAdjacenciesGet(new LispAdjacenciesGet()).toCompletableFuture().get();
+ LOG.info("Lisp adjacency received successfully:" + reply.toString());
+ }
+
+ private static void testAdjacency(final FutureJVppCoreFacade jvpp) throws Exception {
+ enableLisp(jvpp);
+ addLocatorSet(jvpp);
+ addLocalEid(jvpp);
+ addRemoteMapping(jvpp);
+ addAdjacency(jvpp);
+ showAdjacencies(jvpp);
+ }
+
+ private static void testFutureApi() throws Exception {
+ LOG.info("Create lisp adjacency test");
+ try (final JVppRegistry registry = new JVppRegistryImpl("LispAdjacencyTest");
+ final FutureJVppCoreFacade jvppFacade = new FutureJVppCoreFacade(registry, new JVppCoreImpl())) {
+ LOG.info("Successfully connected to VPP");
+
+ testAdjacency(jvppFacade);
+ LOG.info("Disconnecting...");
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ testFutureApi();
+ }
+}
diff --git a/vpp-api/java/jvpp-core/io/fd/vpp/jvpp/core/test/Readme.txt b/vpp-api/java/jvpp-core/io/fd/vpp/jvpp/core/test/Readme.txt
index 2c9c42439bc..c1b0c5aa2de 100644
--- a/vpp-api/java/jvpp-core/io/fd/vpp/jvpp/core/test/Readme.txt
+++ b/vpp-api/java/jvpp-core/io/fd/vpp/jvpp/core/test/Readme.txt
@@ -14,3 +14,4 @@ CreateSubInterfaceTest - Tests sub-interface creation
FutureApiNotificationTest - Tests interface notifications using Future based JVpp facade
FutureApiTest - Execution of more complex calls using Future based JVpp facade
L2AclTest - Tests L2 ACL creation
+LispAdjacencyTest - Tests lisp adjacency creation and read (custom vpe.api type support showcase)
diff --git a/vpp-api/java/jvpp-core/jvpp_core.c b/vpp-api/java/jvpp-core/jvpp_core.c
index 8872ef5ffea..83c0bb2a8bf 100644
--- a/vpp-api/java/jvpp-core/jvpp_core.c
+++ b/vpp-api/java/jvpp-core/jvpp_core.c
@@ -71,8 +71,8 @@ JNIEXPORT void JNICALL Java_io_fd_vpp_jvpp_core_JVppCoreImpl_init0
vl_msg_api_set_handlers(VL_API_##N, #n, \
vl_api_##n##_t_handler, \
vl_noop_handler, \
- vl_api_##n##_t_endian, \
- vl_api_##n##_t_print, \
+ vl_noop_handler, \
+ vl_noop_handler, \
sizeof(vl_api_##n##_t), 1);
foreach_api_reply_handler;
#undef _
diff --git a/vpp-api/java/jvpp/gen/jvpp_gen.py b/vpp-api/java/jvpp/gen/jvpp_gen.py
index 80bb4b9e93a..3be83824e9c 100755
--- a/vpp-api/java/jvpp/gen/jvpp_gen.py
+++ b/vpp-api/java/jvpp/gen/jvpp_gen.py
@@ -19,6 +19,7 @@ import importlib
import sys
import os
+from jvppgen import types_gen
from jvppgen import callback_gen
from jvppgen import notification_gen
from jvppgen import dto_gen
@@ -37,7 +38,6 @@ from jvppgen import util
#
# where
# defs_api_vpp_papi.py - vpe.api in python format (generated by vppapigen)
-from jvppgen.util import vpp_2_jni_type_mapping
parser = argparse.ArgumentParser(description='VPP Java API generator')
parser.add_argument('-i', action="store", dest="inputfile")
@@ -47,7 +47,7 @@ args = parser.parse_args()
sys.path.append(".")
-print "args.inputfile %s" % args.inputfile
+print "Generating Java API for %s" % args.inputfile
importdir = os.path.dirname(args.inputfile)
print "importdir %s" % importdir
inputfile = os.path.basename(args.inputfile)
@@ -60,13 +60,6 @@ print "control_ping_class %s" % control_ping_class
sys.path.append(importdir)
cfg = importlib.import_module(inputfile, package=None)
-
-# FIXME: functions unsupported due to problems with vpe.api
-def is_supported(f_name):
- return f_name not in {'vnet_ip4_fib_counters', 'vnet_ip6_fib_counters',
- 'lisp_adjacencies_get_reply', 'lisp_adjacencies_get'}
-
-
def is_request_field(field_name):
return field_name not in {'_vl_msg_id', 'client_index', 'context'}
@@ -86,60 +79,52 @@ def get_args(t, filter):
def get_types(t, filter):
types_list = []
- c_types_list = []
lengths_list = []
for i in t:
if not filter(i[1]):
continue
if len(i) is 3: # array type
- types_list.append(vpp_2_jni_type_mapping[i[0]] + 'Array')
- c_types_list.append(i[0] + '[]')
+ types_list.append(i[0] + '[]')
lengths_list.append((i[2], False))
elif len(i) is 4: # variable length array type
- types_list.append(vpp_2_jni_type_mapping[i[0]] + 'Array')
- c_types_list.append(i[0] + '[]')
+ types_list.append(i[0] + '[]')
lengths_list.append((i[3], True))
else: # primitive type
- types_list.append(vpp_2_jni_type_mapping[i[0]])
- c_types_list.append(i[0])
+ types_list.append(i[0])
lengths_list.append((0, False))
- return types_list, c_types_list, lengths_list
+ return types_list, lengths_list
-def get_definitions():
+def get_definitions(defs):
# Pass 1
func_list = []
func_name = {}
- for a in cfg.messages:
- if not is_supported(a[0]):
- continue
-
+ for a in defs:
java_name = util.underscore_to_camelcase(a[0])
# For replies include all the arguments except message_id
if util.is_reply(java_name):
- types, c_types, lengths = get_types(a[1:], is_response_field)
+ types, lengths = get_types(a[1:], is_response_field)
func_name[a[0]] = dict(
[('name', a[0]), ('java_name', java_name),
('args', get_args(a[1:], is_response_field)), ('full_args', get_args(a[1:], lambda x: True)),
- ('types', types), ('c_types', c_types), ('lengths', lengths)])
+ ('types', types), ('lengths', lengths)])
# For requests skip message_id, client_id and context
else:
- types, c_types, lengths = get_types(a[1:], is_request_field)
+ types, lengths = get_types(a[1:], is_request_field)
func_name[a[0]] = dict(
[('name', a[0]), ('java_name', java_name),
('args', get_args(a[1:], is_request_field)), ('full_args', get_args(a[1:], lambda x: True)),
- ('types', types), ('c_types', c_types), ('lengths', lengths)])
+ ('types', types), ('lengths', lengths)])
# Indexed by name
func_list.append(func_name[a[0]])
return func_list, func_name
-func_list, func_name = get_definitions()
-
base_package = 'io.fd.vpp.jvpp'
plugin_package = base_package + '.' + plugin_name
+types_package = 'types'
dto_package = 'dto'
callback_package = 'callback'
notification_package = 'notification'
@@ -148,6 +133,11 @@ future_package = 'future'
callback_facade_package = 'callfacade'
control_ping_class_fqn = "%s.%s.%s" % (plugin_package, dto_package, control_ping_class)
+types_list, types_name = get_definitions(cfg.types)
+
+types_gen.generate_types(types_list, plugin_package, types_package, inputfile)
+
+func_list, func_name = get_definitions(cfg.messages)
dto_gen.generate_dtos(func_list, base_package, plugin_package, plugin_name.title(), dto_package, args.inputfile)
jvpp_impl_gen.generate_jvpp(func_list, base_package, plugin_package, plugin_name, control_ping_class_fqn, dto_package, args.inputfile)
callback_gen.generate_callbacks(func_list, base_package, plugin_package, plugin_name.title(), callback_package, dto_package, args.inputfile)
@@ -155,3 +145,5 @@ notification_gen.generate_notification_registry(func_list, base_package, plugin_
jvpp_c_gen.generate_jvpp(func_list, plugin_name, args.inputfile)
jvpp_future_facade_gen.generate_jvpp(func_list, base_package, plugin_package, plugin_name.title(), dto_package, callback_package, notification_package, future_package, args.inputfile)
jvpp_callback_facade_gen.generate_jvpp(func_list, base_package, plugin_package, plugin_name.title(), dto_package, callback_package, notification_package, callback_facade_package, args.inputfile)
+
+print "Java API for %s generated successfully" % args.inputfile
diff --git a/vpp-api/java/jvpp/gen/jvppgen/dto_gen.py b/vpp-api/java/jvpp/gen/jvppgen/dto_gen.py
index 12354793bf7..a043c9459b0 100644
--- a/vpp-api/java/jvpp/gen/jvppgen/dto_gen.py
+++ b/vpp-api/java/jvpp/gen/jvppgen/dto_gen.py
@@ -280,7 +280,7 @@ def generate_dump_reply_dto(request_dto_name, base_package, plugin_package, dto_
cls_name = camel_case_dto_name + dump_dto_suffix
# using artificial type for fields, just to bypass the is_array check in base methods generators
# the type is not really used
- artificial_type = 'jstring'
+ artificial_type = 'u8'
# In case of already existing artificial reply dump DTO, just update it
# Used for sub-dump dtos
diff --git a/vpp-api/java/jvpp/gen/jvppgen/jni_gen.py b/vpp-api/java/jvpp/gen/jvppgen/jni_gen.py
new file mode 100644
index 00000000000..4b03b31d163
--- /dev/null
+++ b/vpp-api/java/jvpp/gen/jvppgen/jni_gen.py
@@ -0,0 +1,291 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2016 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from string import Template
+
+import util
+
+variable_length_array_value_template = Template("""mp->${length_var_name}""")
+variable_length_array_template = Template("""clib_net_to_host_${length_field_type}(${value})""")
+
+dto_field_id_template = Template("""
+ jfieldID ${field_reference_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${field_name}", "${jni_signature}");""")
+
+default_dto_field_setter_template = Template("""
+ (*env)->Set${jni_setter}(env, ${object_name}, ${field_reference_name}FieldId, mp->${c_name});
+""")
+
+variable_length_array_value_template = Template("""mp->${length_var_name}""")
+variable_length_array_template = Template("""clib_net_to_host_${length_field_type}(${value})""")
+
+u16_dto_field_setter_template = Template("""
+ (*env)->Set${jni_setter}(env, ${object_name}, ${field_reference_name}FieldId, clib_net_to_host_u16(mp->${c_name}));
+""")
+
+u32_dto_field_setter_template = Template("""
+ (*env)->Set${jni_setter}(env, ${object_name}, ${field_reference_name}FieldId, clib_net_to_host_u32(mp->${c_name}));
+""")
+
+u64_dto_field_setter_template = Template("""
+ (*env)->Set${jni_setter}(env, ${object_name}, ${field_reference_name}FieldId, clib_net_to_host_u64(mp->${c_name}));
+""")
+
+u8_array_dto_field_setter_template = Template("""
+ jbyteArray ${field_reference_name} = (*env)->NewByteArray(env, ${field_length});
+ (*env)->SetByteArrayRegion(env, ${field_reference_name}, 0, ${field_length}, (const jbyte*)mp->${c_name});
+ (*env)->SetObjectField(env, ${object_name}, ${field_reference_name}FieldId, ${field_reference_name});
+""")
+
+u16_array_dto_field_setter_template = Template("""
+ {
+ jshortArray ${field_reference_name} = (*env)->NewShortArray(env, ${field_length});
+ jshort * ${field_reference_name}ArrayElements = (*env)->GetShortArrayElements(env, ${field_reference_name}, NULL);
+ unsigned int _i;
+ for (_i = 0; _i < ${field_length}; _i++) {
+ ${field_reference_name}ArrayElements[_i] = clib_net_to_host_u16(mp->${c_name}[_i]);
+ }
+
+ (*env)->ReleaseShortArrayElements(env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
+ (*env)->SetObjectField(env, ${object_name}, ${field_reference_name}FieldId, ${field_reference_name});
+ }
+""")
+
+u32_array_dto_field_setter_template = Template("""
+ {
+ jintArray ${field_reference_name} = (*env)->NewIntArray(env, ${field_length});
+ jint * ${field_reference_name}ArrayElements = (*env)->GetIntArrayElements(env, ${field_reference_name}, NULL);
+ unsigned int _i;
+ for (_i = 0; _i < ${field_length}; _i++) {
+ ${field_reference_name}ArrayElements[_i] = clib_net_to_host_u32(mp->${c_name}[_i]);
+ }
+
+ (*env)->ReleaseIntArrayElements(env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
+ (*env)->SetObjectField(env, ${object_name}, ${field_reference_name}FieldId, ${field_reference_name});
+ }
+""")
+
+# For each u64 array we get its elements. Then we convert values to host byte order.
+# All changes to jlong* buffer are written to jlongArray (isCopy is set to NULL)
+u64_array_dto_field_setter_template = Template("""
+ {
+ jlongArray ${field_reference_name} = (*env)->NewLongArray(env, ${field_length});
+ jlong * ${field_reference_name}ArrayElements = (*env)->GetLongArrayElements(env, ${field_reference_name}, NULL);
+ unsigned int _i;
+ for (_i = 0; _i < ${field_length}; _i++) {
+ ${field_reference_name}ArrayElements[_i] = clib_net_to_host_u64(mp->${c_name}[_i]);
+ }
+
+ (*env)->ReleaseLongArrayElements(env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
+ (*env)->SetObjectField(env, ${object_name}, ${field_reference_name}FieldId, ${field_reference_name});
+ }
+""")
+
+dto_field_setter_templates = {'u8': default_dto_field_setter_template,
+ 'u16': u16_dto_field_setter_template,
+ 'u32': u32_dto_field_setter_template,
+ 'i32': u32_dto_field_setter_template,
+ 'u64': u64_dto_field_setter_template,
+ 'f64': default_dto_field_setter_template, # fixme
+ 'u8[]': u8_array_dto_field_setter_template,
+ 'u16[]': u16_array_dto_field_setter_template,
+ 'u32[]': u32_array_dto_field_setter_template,
+ 'u64[]': u64_array_dto_field_setter_template
+ }
+
+
+def jni_reply_handler_for_type(handler_name, ref_name, field_type, c_name, field_reference_name,
+ field_name, field_length, is_variable_len_array, length_field_type,
+ object_name="dto"):
+ """
+ Generates jni code that initializes a field of java object (dto or custom type).
+ To be used in reply message handlers.
+ :param field_type: type of the field to be initialized (as defined in vpe.api)
+ :param c_name: name of the message struct member that stores initialization value
+ :param field_reference_name: name of the field reference in generated code
+ :param field_name: name of the field (camelcase)
+ :param field_length: integer or name of variable that stores field length
+ :param object_name: name of the object to be initialized
+ """
+
+ # todo move validation to vppapigen
+ if field_type.endswith('[]') and field_length == '0':
+ raise Exception('Variable array \'%s\' defined in \'%s\' '
+ 'should have defined length (e.g. \'%s[%s_length]\''
+ % (c_name, handler_name, c_name, c_name))
+
+ if is_variable_len_array:
+ length_var_name = field_length
+ field_length = variable_length_array_value_template.substitute(length_var_name=length_var_name)
+ if length_field_type != 'u8': # we need net to host conversion:
+ field_length = variable_length_array_template.substitute(
+ length_field_type=length_field_type, value=field_length)
+
+ # for retval don't generate setters
+ if util.is_retval_field(c_name):
+ return ""
+
+ jni_signature = util.jni_2_signature_mapping[field_type]
+ jni_setter = util.jni_field_accessors[field_type]
+
+ result = dto_field_id_template.substitute(
+ field_reference_name=field_reference_name,
+ field_name=field_name,
+ class_ref_name=ref_name,
+ jni_signature=jni_signature)
+
+ dto_setter_template = dto_field_setter_templates[field_type]
+
+ result += dto_setter_template.substitute(
+ jni_signature=jni_signature,
+ object_name=object_name,
+ field_reference_name=field_reference_name,
+ c_name=c_name,
+ jni_setter=jni_setter,
+ field_length=field_length)
+ return result
+
+
+request_field_identifier_template = Template("""
+ jfieldID ${field_reference_name}FieldId = (*env)->GetFieldID(env, ${object_name}Class, "${field_name}", "${jni_signature}");
+ ${jni_type} ${field_reference_name} = (*env)->Get${jni_getter}(env, ${object_name}, ${field_reference_name}FieldId);
+ """)
+
+array_length_enforcement_template = Template("""
+ size_t max_size = ${field_length};
+ if (cnt > max_size) cnt = max_size;""")
+
+u8_struct_setter_template = Template("""
+ mp->${c_name} = ${field_reference_name};""")
+
+u16_struct_setter_template = Template("""
+ mp->${c_name} = clib_host_to_net_u16(${field_reference_name});""")
+
+u32_struct_setter_template = Template("""
+ mp->${c_name} = clib_host_to_net_u32(${field_reference_name});""")
+
+i32_struct_setter_template = Template("""
+ mp->${c_name} = clib_host_to_net_i32(${field_reference_name});!""")
+
+u64_struct_setter_template = Template("""
+ mp->${c_name} = clib_host_to_net_u64(${field_reference_name});""")
+
+array_length_enforcement_template = Template("""
+ size_t max_size = ${field_length};
+ if (cnt > max_size) cnt = max_size;""")
+
+u8_array_struct_setter_template = Template("""
+ if (${field_reference_name}) {
+ jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name});
+ ${field_length_check}
+ (*env)->GetByteArrayRegion(env, ${field_reference_name}, 0, cnt, (jbyte *)mp->${c_name});
+ }
+""")
+
+u16_array_struct_setter_template = Template("""
+ jshort * ${field_reference_name}ArrayElements = (*env)->GetShortArrayElements(env, ${field_reference_name}, NULL);
+ if (${field_reference_name}) {
+ size_t _i;
+ jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name});
+ ${field_length_check}
+ for (_i = 0; _i < cnt; _i++) {
+ mp->${c_name}[_i] = clib_host_to_net_u16(${field_reference_name}ArrayElements[_i]);
+ }
+ }
+ (*env)->ReleaseShortArrayElements (env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
+ """)
+
+u32_array_struct_setter_template = Template("""
+ jint * ${field_reference_name}ArrayElements = (*env)->GetIntArrayElements(env, ${field_reference_name}, NULL);
+ if (${field_reference_name}) {
+ size_t _i;
+ jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name});
+ ${field_length_check}
+ for (_i = 0; _i < cnt; _i++) {
+ mp->${c_name}[_i] = clib_host_to_net_u32(${field_reference_name}ArrayElements[_i]);
+ }
+ }
+ (*env)->ReleaseIntArrayElements (env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
+ """)
+
+u64_array_struct_setter_template = Template("""
+ jlong * ${field_reference_name}ArrayElements = (*env)->GetLongArrayElements(env, ${field_reference_name}, NULL);
+ if (${field_reference_name}) {
+ size_t _i;
+ jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name});
+ ${field_length_check}
+ for (_i = 0; _i < cnt; _i++) {
+ mp->${c_name}[_i] = clib_host_to_net_u64(${field_reference_name}ArrayElements[_i]);
+ }
+ }
+ (*env)->ReleaseLongArrayElements (env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
+ """)
+
+struct_setter_templates = {'u8': u8_struct_setter_template,
+ 'u16': u16_struct_setter_template,
+ 'u32': u32_struct_setter_template,
+ 'i32': u32_struct_setter_template,
+ 'u64': u64_struct_setter_template,
+ 'u8[]': u8_array_struct_setter_template,
+ 'u16[]': u16_array_struct_setter_template,
+ 'u32[]': u32_array_struct_setter_template,
+ 'u64[]': u64_array_struct_setter_template
+ }
+
+
+def jni_request_binding_for_type(field_type, c_name, field_reference_name, field_name, field_length,
+ is_variable_len_array, object_name="request"):
+ """
+ Generates jni code that initializes C structure that corresponds to a field of java object
+ (dto or custom type). To be used in request message handlers.
+ :param field_type: type of the field to be initialized (as defined in vpe.api)
+ :param c_name: name of the message struct member to be initialized
+ :param field_reference_name: name of the field reference in generated code
+ :param field_name: name of the field (camelcase)
+ :param field_length: integer or name of variable that stores field length
+ :param object_name: name of the object to be initialized
+ """
+ # field identifiers
+ jni_type = util.vpp_2_jni_type_mapping[field_type]
+ jni_signature = util.jni_2_signature_mapping[field_type]
+ jni_getter = util.jni_field_accessors[field_type]
+
+ # field identifier
+ msg_initialization = request_field_identifier_template.substitute(
+ jni_type=jni_type,
+ field_reference_name=field_reference_name,
+ field_name=field_name,
+ jni_signature=jni_signature,
+ jni_getter=jni_getter,
+ object_name=object_name)
+
+ # field setter
+ field_length_check = ""
+
+ # check if we are processing variable length array:
+ if is_variable_len_array:
+ field_length = util.underscore_to_camelcase(field_length)
+
+ # enforce max length if array has fixed length or uses variable length syntax
+ if str(field_length) != "0":
+ field_length_check = array_length_enforcement_template.substitute(field_length=field_length)
+
+ struct_setter_template = struct_setter_templates[field_type]
+
+ msg_initialization += struct_setter_template.substitute(
+ c_name=c_name,
+ field_reference_name=field_reference_name,
+ field_length_check=field_length_check)
+
+ return msg_initialization
diff --git a/vpp-api/java/jvpp/gen/jvppgen/jvpp_c_gen.py b/vpp-api/java/jvpp/gen/jvppgen/jvpp_c_gen.py
index d63acd6965f..1a35a6c09c0 100644
--- a/vpp-api/java/jvpp/gen/jvppgen/jvpp_c_gen.py
+++ b/vpp-api/java/jvpp/gen/jvppgen/jvpp_c_gen.py
@@ -17,6 +17,9 @@
import os, util
from string import Template
+import jni_gen
+
+
def is_manually_generated(f_name, plugin_name):
return f_name in {'control_ping_reply'}
@@ -54,6 +57,7 @@ static void delete_class_references(JNIEnv* env) {
$delete_class_invocations
}""")
+
def generate_class_cache(func_list, plugin_name):
class_references = []
find_class_invocations = []
@@ -105,94 +109,10 @@ request_class_template = Template("""
jclass requestClass = (*env)->FindClass(env, "io/fd/vpp/jvpp/${plugin_name}/dto/${java_name_upper}");""")
request_field_identifier_template = Template("""
- jfieldID ${java_name}FieldId = (*env)->GetFieldID(env, requestClass, "${java_name}", "${jni_signature}");
- ${jni_type} ${java_name} = (*env)->Get${jni_getter}(env, request, ${java_name}FieldId);
+ jfieldID ${field_reference_name}FieldId = (*env)->GetFieldID(env, ${object_name}Class, "${field_name}", "${jni_signature}");
+ ${jni_type} ${field_reference_name} = (*env)->Get${jni_getter}(env, ${object_name}, ${field_reference_name}FieldId);
""")
-u8_struct_setter_template = Template("""
- mp->${c_name} = ${java_name};""")
-
-u16_struct_setter_template = Template("""
- mp->${c_name} = clib_host_to_net_u16(${java_name});""")
-
-u32_struct_setter_template = Template("""
- mp->${c_name} = clib_host_to_net_u32(${java_name});""")
-
-i32_struct_setter_template = Template("""
- mp->${c_name} = clib_host_to_net_i32(${java_name});!""")
-
-u64_struct_setter_template = Template("""
- mp->${c_name} = clib_host_to_net_u64(${java_name});""")
-
-fixed_array_length_enforcement_template = Template("""
- size_t max_size = ${field_length};
- if (cnt > max_size) cnt = max_size;""")
-
-u8_array_struct_setter_template = Template("""
- if (${java_name}) {
- jsize cnt = (*env)->GetArrayLength (env, ${java_name});
- ${field_length_check}
- (*env)->GetByteArrayRegion(env, ${java_name}, 0, cnt, (jbyte *)mp->${c_name});
- }
-""")
-
-u16_array_struct_setter_template = Template("""
- jshort * ${java_name}ArrayElements = (*env)->GetShortArrayElements(env, ${java_name}, NULL);
- if (${java_name}) {
- size_t _i;
- jsize cnt = (*env)->GetArrayLength (env, ${java_name});
- ${field_length_check}
- for (_i = 0; _i < cnt; _i++) {
- mp->${c_name}[_i] = clib_host_to_net_u16(${java_name}ArrayElements[_i]);
- }
- }
- (*env)->ReleaseShortArrayElements (env, ${java_name}, ${java_name}ArrayElements, 0);
- """)
-
-u32_array_struct_setter_template = Template("""
- jint * ${java_name}ArrayElements = (*env)->GetIntArrayElements(env, ${java_name}, NULL);
- if (${java_name}) {
- size_t _i;
- jsize cnt = (*env)->GetArrayLength (env, ${java_name});
- ${field_length_check}
- for (_i = 0; _i < cnt; _i++) {
- mp->${c_name}[_i] = clib_host_to_net_u32(${java_name}ArrayElements[_i]);
- }
- }
- (*env)->ReleaseIntArrayElements (env, ${java_name}, ${java_name}ArrayElements, 0);
- """)
-
-u64_array_struct_setter_template = Template("""
- jlong * ${java_name}ArrayElements = (*env)->GetLongArrayElements(env, ${java_name}, NULL);
- if (${java_name}) {
- size_t _i;
- jsize cnt = (*env)->GetArrayLength (env, ${java_name});
- ${field_length_check}
- for (_i = 0; _i < cnt; _i++) {
- mp->${c_name}[_i] = clib_host_to_net_u64(${java_name}ArrayElements[_i]);
- }
- }
- (*env)->ReleaseLongArrayElements (env, ${java_name}, ${java_name}ArrayElements, 0);
- """)
-
-vl_api_ip4_fib_counter_t_array_struct_setter_template = Template("""
- // vl_api_ip4_fib_counter_t_array_field_setter_template FIXME""")
-
-vl_api_ip6_fib_counter_t_array_struct_setter_template = Template("""
- // vl_api_ip6_fib_counter_t_array_field_setter_template FIXME""")
-
-struct_setter_templates = {'u8': u8_struct_setter_template,
- 'u16': u16_struct_setter_template,
- 'u32': u32_struct_setter_template,
- 'i32': u32_struct_setter_template,
- 'u64': u64_struct_setter_template,
- 'u8[]': u8_array_struct_setter_template,
- 'u16[]': u16_array_struct_setter_template,
- 'u32[]': u32_array_struct_setter_template,
- 'u64[]': u64_array_struct_setter_template,
- 'vl_api_ip4_fib_counter_t[]': vl_api_ip4_fib_counter_t_array_struct_setter_template,
- 'vl_api_ip6_fib_counter_t[]': vl_api_ip6_fib_counter_t_array_struct_setter_template
- }
jni_impl_template = Template("""
/**
@@ -200,13 +120,12 @@ jni_impl_template = Template("""
* Generated based on $inputfile preparsed data:
$api_data
*/
-JNIEXPORT jint JNICALL Java_io_fd_vpp_jvpp_${plugin_name}_JVpp${java_plugin_name}Impl_${java_name}0
+JNIEXPORT jint JNICALL Java_io_fd_vpp_jvpp_${plugin_name}_JVpp${java_plugin_name}Impl_${field_name}0
(JNIEnv * env, jclass clazz$args) {
${plugin_name}_main_t *plugin_main = &${plugin_name}_main;
vl_api_${c_name}_t * mp;
u32 my_context_id = vppjni_get_context_id (&jvpp_main);
$request_class
- $field_identifiers
// create message:
mp = vl_msg_api_alloc(sizeof(*mp));
@@ -215,7 +134,8 @@ JNIEXPORT jint JNICALL Java_io_fd_vpp_jvpp_${plugin_name}_JVpp${java_plugin_name
mp->client_index = plugin_main->my_client_index;
mp->context = clib_host_to_net_u32 (my_context_id);
- $struct_setters
+ $msg_initialization
+
// send message:
vl_msg_api_send_shmem (plugin_main->vl_input_queue, (u8 *)&mp);
if ((*env)->ExceptionCheck(env)) {
@@ -235,8 +155,7 @@ def generate_jni_impl(func_list, plugin_name, inputfile):
arguments = ''
request_class = ''
- field_identifiers = ''
- struct_setters = ''
+ msg_initialization = ''
f_name_uppercase = f_name.upper()
if f['args']:
@@ -247,142 +166,29 @@ def generate_jni_impl(func_list, plugin_name, inputfile):
java_name_upper=camel_case_function_name_upper,
plugin_name=plugin_name)
- # field identifiers
- for t in zip(f['types'], f['args']):
- jni_type = t[0]
- java_field_name = util.underscore_to_camelcase(t[1])
- jni_signature = util.jni_2_signature_mapping[jni_type]
- jni_getter = util.jni_field_accessors[jni_type]
- field_identifiers += request_field_identifier_template.substitute(
- jni_type=jni_type,
- java_name=java_field_name,
- jni_signature=jni_signature,
- jni_getter=jni_getter)
-
- # field setters
- for t in zip(f['c_types'], f['args'], f['lengths']):
- c_type = t[0]
- c_name = t[1]
- field_length = t[2][0]
- field_length_check = ""
-
- # check if we are processing variable length array:
- if t[2][1]:
- field_length = util.underscore_to_camelcase(t[2][0])
-
- # enforce max length if array has fixed length or uses variable length syntax
- if str(t[2][0]) != "0":
- field_length_check = fixed_array_length_enforcement_template.substitute(field_length=field_length)
-
- java_field_name = util.underscore_to_camelcase(c_name)
-
- struct_setter_template = struct_setter_templates[c_type]
-
- struct_setters += struct_setter_template.substitute(
- c_name=c_name,
- java_name=java_field_name,
- field_length_check=field_length_check)
+ for t in zip(f['types'], f['args'], f['lengths']):
+ field_name = util.underscore_to_camelcase(t[1])
+ msg_initialization += jni_gen.jni_request_binding_for_type(field_type=t[0], c_name=t[1],
+ field_reference_name=field_name,
+ field_name=field_name,
+ field_length=t[2][0],
+ is_variable_len_array=t[2][1])
jni_impl.append(jni_impl_template.substitute(
inputfile=inputfile,
api_data=util.api_message_to_javadoc(f),
- java_name=camel_case_function_name,
+ field_reference_name=camel_case_function_name,
+ field_name=camel_case_function_name,
c_name_uppercase=f_name_uppercase,
c_name=f_name,
plugin_name=plugin_name,
java_plugin_name=plugin_name.title(),
request_class=request_class,
- field_identifiers=field_identifiers,
- struct_setters=struct_setters,
+ msg_initialization=msg_initialization,
args=arguments))
return "\n".join(jni_impl)
-
-dto_field_id_template = Template("""
- jfieldID ${java_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${java_name}", "${jni_signature}");""")
-
-default_dto_field_setter_template = Template("""
- (*env)->Set${jni_setter}(env, dto, ${java_name}FieldId, mp->${c_name});
-""")
-
-variable_length_array_value_template = Template("""mp->${length_var_name}""")
-variable_length_array_template = Template("""clib_net_to_host_${length_field_type}(${value})""")
-
-u16_dto_field_setter_template = Template("""
- (*env)->Set${jni_setter}(env, dto, ${java_name}FieldId, clib_net_to_host_u16(mp->${c_name}));
-""")
-
-u32_dto_field_setter_template = Template("""
- (*env)->Set${jni_setter}(env, dto, ${java_name}FieldId, clib_net_to_host_u32(mp->${c_name}));
-""")
-
-u64_dto_field_setter_template = Template("""
- (*env)->Set${jni_setter}(env, dto, ${java_name}FieldId, clib_net_to_host_u64(mp->${c_name}));
-""")
-
-u8_array_dto_field_setter_template = Template("""
- jbyteArray ${java_name} = (*env)->NewByteArray(env, ${field_length});
- (*env)->SetByteArrayRegion(env, ${java_name}, 0, ${field_length}, (const jbyte*)mp->${c_name});
- (*env)->SetObjectField(env, dto, ${java_name}FieldId, ${java_name});
-""")
-
-u16_array_dto_field_setter_template = Template("""
- {
- jshortArray ${java_name} = (*env)->NewShortArray(env, ${field_length});
- jshort * ${java_name}ArrayElements = (*env)->GetShortArrayElements(env, ${java_name}, NULL);
- unsigned int _i;
- for (_i = 0; _i < ${field_length}; _i++) {
- ${java_name}ArrayElements[_i] = clib_net_to_host_u16(mp->${c_name}[_i]);
- }
-
- (*env)->ReleaseShortArrayElements(env, ${java_name}, ${java_name}ArrayElements, 0);
- (*env)->SetObjectField(env, dto, ${java_name}FieldId, ${java_name});
- }
-""")
-
-u32_array_dto_field_setter_template = Template("""
- {
- jintArray ${java_name} = (*env)->NewIntArray(env, ${field_length});
- jint * ${java_name}ArrayElements = (*env)->GetIntArrayElements(env, ${java_name}, NULL);
- unsigned int _i;
- for (_i = 0; _i < ${field_length}; _i++) {
- ${java_name}ArrayElements[_i] = clib_net_to_host_u32(mp->${c_name}[_i]);
- }
-
- (*env)->ReleaseIntArrayElements(env, ${java_name}, ${java_name}ArrayElements, 0);
- (*env)->SetObjectField(env, dto, ${java_name}FieldId, ${java_name});
- }
-""")
-
-# For each u64 array we get its elements. Then we convert values to host byte order.
-# All changes to jlong* buffer are written to jlongArray (isCopy is set to NULL)
-u64_array_dto_field_setter_template = Template("""
- {
- jlongArray ${java_name} = (*env)->NewLongArray(env, ${field_length});
- jlong * ${java_name}ArrayElements = (*env)->GetLongArrayElements(env, ${java_name}, NULL);
- unsigned int _i;
- for (_i = 0; _i < ${field_length}; _i++) {
- ${java_name}ArrayElements[_i] = clib_net_to_host_u64(mp->${c_name}[_i]);
- }
-
- (*env)->ReleaseLongArrayElements(env, ${java_name}, ${java_name}ArrayElements, 0);
- (*env)->SetObjectField(env, dto, ${java_name}FieldId, ${java_name});
- }
-""")
-
-dto_field_setter_templates = {'u8': default_dto_field_setter_template,
- 'u16': u16_dto_field_setter_template,
- 'u32': u32_dto_field_setter_template,
- 'i32': u32_dto_field_setter_template,
- 'u64': u64_dto_field_setter_template,
- 'f64': default_dto_field_setter_template, #fixme
- 'u8[]': u8_array_dto_field_setter_template,
- 'u16[]': u16_array_dto_field_setter_template,
- 'u32[]': u32_array_dto_field_setter_template,
- 'u64[]': u64_array_dto_field_setter_template
- }
-
# code fragment for checking result of the operation before sending request reply
callback_err_handler_template = Template("""
// for negative result don't send callback message but send error callback
@@ -418,6 +224,7 @@ static void vl_api_${handler_name}_t_handler (vl_api_${handler_name}_t * mp)
(*env)->CallVoidMethod(env, plugin_main->callbackObject, callbackMethod, dto);
}""")
+
def generate_msg_handlers(func_list, plugin_name, inputfile):
handlers = []
for f in func_list:
@@ -438,25 +245,20 @@ def generate_msg_handlers(func_list, plugin_name, inputfile):
dto_setters = ''
err_handler = ''
# dto setters
- for t in zip(f['c_types'], f['types'], f['args'], f['lengths']):
- c_type = t[0]
- jni_type = t[1]
- c_name = t[2]
- field_length = t[3][0]
-
- if jni_type.endswith('Array') and field_length == '0':
- raise Exception('Variable array \'%s\' defined in message \'%s\' '
- 'should have defined length (e.g. \'%s[%s_length]\''
- % (c_name, handler_name, c_name, c_name))
-
- # check if we are processing variable length array
- if t[3][1]:
- length_var_name = t[3][0]
- length_field_type = f['c_types'][f['args'].index(length_var_name)]
- field_length = variable_length_array_value_template.substitute(length_var_name=length_var_name)
- if length_field_type != 'u8': # we need net to host conversion:
- field_length = variable_length_array_template.substitute(
- length_field_type=length_field_type, value=field_length)
+ for t in zip(f['types'], f['args'], f['lengths']):
+ c_name = t[1]
+ java_name = util.underscore_to_camelcase(c_name)
+ field_length = t[2][0]
+ is_variable_len_array = t[2][1]
+ length_field_type = None
+ if is_variable_len_array:
+ length_field_type = f['types'][f['args'].index(field_length)]
+ dto_setters += jni_gen.jni_reply_handler_for_type(handler_name=handler_name, ref_name=ref_name,
+ field_type=t[0], c_name=t[1],
+ field_reference_name=java_name,
+ field_name=java_name, field_length=field_length,
+ is_variable_len_array=is_variable_len_array,
+ length_field_type=length_field_type)
# for retval don't generate setters and generate retval check
if util.is_retval_field(c_name):
@@ -465,24 +267,6 @@ def generate_msg_handlers(func_list, plugin_name, inputfile):
)
continue
- java_field_name = util.underscore_to_camelcase(c_name)
- jni_signature = util.jni_2_signature_mapping[jni_type]
- jni_setter = util.jni_field_accessors[jni_type]
-
- dto_setters += dto_field_id_template.substitute(
- java_name=java_field_name,
- class_ref_name=ref_name,
- jni_signature=jni_signature)
-
- dto_setter_template = dto_field_setter_templates[c_type]
-
- dto_setters += dto_setter_template.substitute(
- java_name=java_field_name,
- jni_signature=jni_signature,
- c_name=c_name,
- jni_setter=jni_setter,
- field_length=field_length)
-
handlers.append(msg_handler_template.substitute(
inputfile=inputfile,
api_data=util.api_message_to_javadoc(f),
diff --git a/vpp-api/java/jvpp/gen/jvppgen/types_gen.py b/vpp-api/java/jvpp/gen/jvppgen/types_gen.py
new file mode 100644
index 00000000000..d12fb3d7850
--- /dev/null
+++ b/vpp-api/java/jvpp/gen/jvppgen/types_gen.py
@@ -0,0 +1,227 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2016 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+from string import Template
+
+import util
+import jni_gen
+import dto_gen
+
+type_template = Template("""
+package $plugin_package.$type_package;
+
+/**
+ * <p>This class represents $c_type_name type definition.
+ * <br>It was generated by types_gen.py based on $inputfile preparsed data:
+ * <pre>
+$docs
+ * </pre>
+ */
+public final class $java_type_name {
+$fields
+$methods
+}
+""")
+
+field_template = Template(""" public $type $name;\n""")
+
+
+def generate_type_fields(type_definition):
+ """
+ Generates fields for class representing typeonly definition
+ :param type_definition: python representation of typeonly definition
+ :return: string representing class fields
+ """
+ fields = ""
+ for t in zip(type_definition['types'], type_definition['args']):
+ field_name = util.underscore_to_camelcase(t[1])
+ fields += field_template.substitute(type=util.jni_2_java_type_mapping[t[0]],
+ name=field_name)
+ return fields
+
+object_struct_setter_template = Template("""
+ {
+ jclass ${field_reference_name}Class = (*env)->FindClass(env, "${class_FQN}");
+ memset (&(mp->${c_name}), 0, sizeof (mp->${c_name}));
+ ${struct_initialization}
+ }
+""")
+
+object_array_struct_setter_template = Template("""
+ {
+ jclass ${field_reference_name}ArrayElementClass = (*env)->FindClass(env, "${class_FQN}");
+ if (${field_reference_name}) {
+ size_t _i;
+ jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name});
+ ${field_length_check}
+ for (_i = 0; _i < cnt; _i++) {
+ jobject ${field_reference_name}ArrayElement = (*env)->GetObjectArrayElement(env, ${field_reference_name}, _i);
+ memset (&(mp->${c_name}[_i]), 0, sizeof (mp->${c_name}[_i]));
+ ${struct_initialization}
+ }
+ }
+ }
+""")
+
+object_dto_field_setter_template = Template("""
+ {
+ jclass ${field_reference_name}Class = (*env)->FindClass(env, "${class_FQN}");
+ jmethodID ${field_reference_name}Constructor = (*env)->GetMethodID(env, ${field_reference_name}Class, "<init>", "()V");
+ jobject ${field_reference_name} = (*env)->NewObject(env, ${field_reference_name}Class, ${field_reference_name}Constructor);
+ ${type_initialization}
+ (*env)->SetObjectField(env, dto, ${field_reference_name}FieldId, ${field_reference_name});
+ }
+""")
+
+object_array_dto_field_setter_template = Template("""
+ {
+ jclass ${field_reference_name}Class = (*env)->FindClass(env, "${class_FQN}");
+ jobjectArray ${field_reference_name} = (*env)->NewObjectArray(env, ${field_length}, ${field_reference_name}Class, 0);
+ unsigned int _i;
+ for (_i = 0; _i < ${field_length}; _i++) {
+ jmethodID ${field_reference_name}Constructor = (*env)->GetMethodID(env, ${field_reference_name}Class, "<init>", "()V");
+ jobject ${field_reference_name}ArrayElement = (*env)->NewObject(env, ${field_reference_name}Class, ${field_reference_name}Constructor);
+ ${type_initialization}
+ (*env)->SetObjectArrayElement(env, ${field_reference_name}, _i, ${field_reference_name}ArrayElement);
+ }
+ (*env)->SetObjectField(env, dto, ${field_reference_name}FieldId, ${field_reference_name});
+ }
+""")
+
+
+def generate_struct_initialization(type_def, c_name_prefix, object_name, indent):
+ struct_initialization = ""
+ # field identifiers
+ for t in zip(type_def['types'], type_def['args'], type_def['lengths']):
+ field_reference_name = "${c_name}" + util.underscore_to_camelcase_upper(t[1])
+ field_name = util.underscore_to_camelcase(t[1])
+ struct_initialization += jni_gen.jni_request_binding_for_type(field_type=t[0], c_name=c_name_prefix + t[1],
+ field_reference_name=field_reference_name,
+ field_name=field_name,
+ field_length=t[2][0],
+ is_variable_len_array=t[2][1],
+ object_name=object_name)
+ return indent + struct_initialization.replace('\n', '\n' + indent)
+
+
+def generate_type_setter(handler_name, type_def, c_name_prefix, object_name, indent):
+ type_initialization = ""
+ for t in zip(type_def['types'], type_def['args'], type_def['lengths']):
+ field_length = t[2][0]
+ is_variable_len_array = t[2][1]
+ length_field_type = None
+ if is_variable_len_array:
+ length_field_type = type_def['types'][type_def['args'].index(field_length)]
+ type_initialization += jni_gen.jni_reply_handler_for_type(handler_name=handler_name,
+ ref_name="${field_reference_name}",
+ field_type=t[0], c_name=c_name_prefix + t[1],
+ field_reference_name="${c_name}" + util.underscore_to_camelcase_upper(t[1]),
+ field_name=util.underscore_to_camelcase(t[1]),
+ field_length=field_length,
+ is_variable_len_array=is_variable_len_array,
+ length_field_type=length_field_type,
+ object_name=object_name)
+ return indent + type_initialization.replace('\n', '\n' + indent)
+
+
+def generate_types(types_list, plugin_package, types_package, inputfile):
+ """
+ Generates Java representation of custom types defined in api file.
+ """
+
+ #
+ if not types_list:
+ print "Skipping custom types generation (%s does not define custom types)." % inputfile
+ return
+
+ print "Generating custom types"
+
+ if not os.path.exists(types_package):
+ raise Exception("%s folder is missing" % types_package)
+
+ for type in types_list:
+ c_type_name = type['name']
+ java_type_name = util.underscore_to_camelcase_upper(type['name'])
+ dto_path = os.path.join(types_package, java_type_name + ".java")
+
+ fields = generate_type_fields(type)
+
+ dto_file = open(dto_path, 'w')
+ dto_file.write(type_template.substitute(plugin_package=plugin_package,
+ type_package=types_package,
+ c_type_name=c_type_name,
+ inputfile=inputfile,
+ docs=util.api_message_to_javadoc(type),
+ java_type_name=java_type_name,
+ fields=fields,
+ methods=dto_gen.generate_dto_base_methods(java_type_name, type)
+ ))
+
+ # update type mappings:
+ # todo fix vpe.api to use type_name instead of vl_api_type_name_t
+ type_name = "vl_api_" + c_type_name + "_t"
+ java_fqn = "%s.%s.%s" % (plugin_package, types_package, java_type_name)
+ util.vpp_2_jni_type_mapping[type_name] = "jobject"
+ util.vpp_2_jni_type_mapping[type_name + "[]"] = "jobjectArray"
+ util.jni_2_java_type_mapping[type_name] = java_fqn
+ util.jni_2_java_type_mapping[type_name + "[]"] = java_fqn + "[]"
+ jni_name = java_fqn.replace('.', "/")
+ jni_signature = "L" + jni_name + ";"
+ util.jni_2_signature_mapping[type_name] = "L" + jni_name + ";"
+ util.jni_2_signature_mapping[type_name + "[]"] = "[" + jni_signature
+ util.jni_field_accessors[type_name] = "ObjectField"
+ util.jni_field_accessors[type_name + "[]"] = "ObjectField"
+
+ jni_gen.struct_setter_templates[type_name] = Template(
+ object_struct_setter_template.substitute(
+ c_name="${c_name}",
+ field_reference_name="${field_reference_name}",
+ class_FQN=jni_name,
+ struct_initialization=generate_struct_initialization(type, "${c_name}.",
+ "${field_reference_name}", ' ' * 4))
+ )
+
+ jni_gen.struct_setter_templates[type_name+ "[]"] = Template(
+ object_array_struct_setter_template.substitute(
+ c_name="${c_name}",
+ field_reference_name="${field_reference_name}",
+ field_length_check="${field_length_check}",
+ class_FQN=jni_name,
+ struct_initialization=generate_struct_initialization(type, "${c_name}[_i].",
+ "${field_reference_name}ArrayElement", ' ' * 8))
+ )
+
+ jni_gen.dto_field_setter_templates[type_name] = Template(
+ object_dto_field_setter_template.substitute(
+ field_reference_name="${field_reference_name}",
+ field_length="${field_length}",
+ class_FQN=jni_name,
+ type_initialization=generate_type_setter(c_type_name, type, "${c_name}.",
+ "${field_reference_name}", ' ' * 4))
+ )
+
+ jni_gen.dto_field_setter_templates[type_name + "[]"] = Template(
+ object_array_dto_field_setter_template.substitute(
+ field_reference_name="${field_reference_name}",
+ field_length="${field_length}",
+ class_FQN=jni_name,
+ type_initialization=generate_type_setter(c_type_name, type, "${c_name}[_i].",
+ "${field_reference_name}ArrayElement", ' ' * 8))
+ )
+
+ dto_file.flush()
+ dto_file.close()
+
diff --git a/vpp-api/java/jvpp/gen/jvppgen/util.py b/vpp-api/java/jvpp/gen/jvppgen/util.py
index 712f17866c3..4d3fca342dd 100644
--- a/vpp-api/java/jvpp/gen/jvppgen/util.py
+++ b/vpp-api/java/jvpp/gen/jvppgen/util.py
@@ -65,78 +65,94 @@ def get_reply_suffix(name):
else:
return reply_suffix
-# http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html
-jni_2_java_type_mapping = {'jbyte': 'byte',
- 'jbyteArray': 'byte[]',
- 'jchar': 'char',
- 'jcharArray': 'char[]',
- 'jshort': 'short',
- 'jshortArray': 'short[]',
- 'jint': 'int',
- 'jintArray': 'int[]',
- 'jlong': 'long',
- 'jlongArray': 'long[]',
- 'jdouble': 'double',
- 'jdoubleArray': 'double[]',
- 'jfloat': 'float',
- 'jfloatArray': 'float[]',
- 'void': 'void',
- 'jstring': 'java.lang.String',
- 'jobject': 'java.lang.Object',
- 'jobjectArray': 'java.lang.Object[]'
- }
-
-# https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/types.html#type_signatures
-jni_2_signature_mapping = {'jbyte': 'B',
- 'jbyteArray': '[B',
- 'jchar': 'C',
- 'jcharArray': '[C',
- 'jshort': 'S',
- 'jshortArray': '[S',
- 'jint': 'I',
- 'jintArray': '[I',
- 'jlong': 'J',
- 'jlongArray': '[J',
- 'jdouble': 'D',
- 'jdoubleArray': '[D',
- 'jfloat': 'F',
- 'jfloatArray': '[F'
- }
-
-# https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#Get_type_Field_routines
-jni_field_accessors = {
- 'jbyte': 'ByteField',
- 'jbyteArray': 'ObjectField',
- 'jchar': 'CharField',
- 'jcharArray': 'ObjectField',
- 'jshort': 'ShortField',
- 'jshortArray': 'ObjectField',
- 'jint': 'IntField',
- 'jintArray': 'ObjectField',
- 'jlong': 'LongField',
- 'jlongArray': 'ObjectField',
- 'jdouble': 'DoubleField',
- 'jdoubleArray': 'ObjectField',
- 'jfloat': 'FloatField',
- 'jfloatArray': 'ObjectField'
-}
-
# Mapping according to:
# http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html
#
# Unsigned types are converted to signed java types that have the same size.
# It is the API user responsibility to interpret them correctly.
+jni_2_java_type_mapping = {'u8': 'byte',
+ 'u8[]': 'byte[]',
+ 'i8': 'byte',
+ 'i8[]': 'byte[]',
+ 'u16': 'short',
+ 'u16[]': 'short[]',
+ 'i16': 'short',
+ 'i16[]': 'short[]',
+ 'u32': 'int',
+ 'u32[]': 'int[]',
+ 'i32': 'int',
+ 'i32[]': 'int[]',
+ 'u64': 'long',
+ 'u64[]': 'long[]',
+ 'i64': 'long',
+ 'i64[]': 'long[]',
+ 'f64': 'double',
+ 'f64[]': 'double[]'
+ }
+
vpp_2_jni_type_mapping = {'u8': 'jbyte',
+ 'u8[]': 'jbyteArray',
'i8': 'jbyte',
+ 'u8[]': 'jbyteArray',
'u16': 'jshort',
+ 'u16[]': 'jshortArray',
'i16': 'jshort',
+ 'i16[]': 'jshortArray',
'u32': 'jint',
+ 'u32[]': 'jintArray',
'i32': 'jint',
+ 'i32[]': 'jintArray',
'u64': 'jlong',
+ 'u64[]': 'longArray',
'i64': 'jlong',
- 'f64': 'jdouble'
+ 'u64[]': 'longArray',
+ 'f64': 'jdouble',
+ 'f64[]': 'jdoubleArray'
}
+# https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/types.html#type_signatures
+jni_2_signature_mapping = {'u8': 'B',
+ 'u8[]': '[B',
+ 'i8': 'B',
+ 'i8[]': '[B',
+ 'u16': 'S',
+ 'u16[]': '[S',
+ 'i16': 'S',
+ 'i16[]': '[S',
+ 'u32': 'I',
+ 'u32[]': '[I',
+ 'i32': 'I',
+ 'i32[]': '[I',
+ 'u64': 'J',
+ 'u64[]': '[J',
+ 'i64': 'J',
+ 'i64[]': '[J',
+ 'f64': 'D',
+ 'f64[]': '[D'
+ }
+
+# https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#Get_type_Field_routines
+jni_field_accessors = {'u8': 'ByteField',
+ 'u8[]': 'ObjectField',
+ 'i8': 'ByteField',
+ 'i8[]': 'ObjectField',
+ 'u16': 'ShortField',
+ 'u16[]': 'ObjectField',
+ 'i16': 'ShortField',
+ 'i16[]': 'ObjectField',
+ 'u32': 'IntField',
+ 'u32[]': 'ObjectField',
+ 'i32': 'IntField',
+ 'i32[]': 'ObjectField',
+ 'u64': 'LongField',
+ 'u64[]': 'ObjectField',
+ 'i64': 'LongField',
+ 'i64[]': 'ObjectField',
+ 'f64': 'DoubleField',
+ 'f64[]': 'ObjectField'
+ }
+
+
# vpe.api calls that do not follow naming conventions and have to be handled exceptionally when finding reply -> request mapping
# FIXME in vpe.api
unconventional_naming_rep_req = {