diff options
author | Michal Cmarada <mcmarada@cisco.com> | 2019-01-31 10:57:40 +0100 |
---|---|---|
committer | Damjan Marion <dmarion@me.com> | 2019-02-19 15:14:02 +0000 |
commit | 4e633e1043e867fd24badeb0405f794793beb9a9 (patch) | |
tree | acc92341b32be50bdef030becb2c65efe5252da2 /extras/japi/java/jvpp | |
parent | aed61801947146e6a93e7791d382bd21d050ee14 (diff) |
VPP-1504: Remove JVPP
As part of JVPP migration this removes JVPP completely from VPP.
Change-Id: I6b74e7961aa474ae471e63fe43a624cd9fc3659b
Signed-off-by: Michal Cmarada <mcmarada@cisco.com>
Diffstat (limited to 'extras/japi/java/jvpp')
19 files changed, 0 insertions, 3562 deletions
diff --git a/extras/japi/java/jvpp/gen/jvpp_gen.py b/extras/japi/java/jvpp/gen/jvpp_gen.py deleted file mode 100755 index 067a92f86be..00000000000 --- a/extras/japi/java/jvpp/gen/jvpp_gen.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env python2 -# -# Copyright (c) 2016,2018 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 argparse -import logging -import os -import sys - -from jvppgen.types_gen import generate_types -from jvppgen.enums_gen import generate_enums -from jvppgen.unions_gen import generate_unions -from jvppgen.dto_gen import generate_dtos -from jvppgen.jvpp_ifc_gen import generate_java_ifc -from jvppgen.jvpp_impl_gen import generate_java_impl -from jvppgen.callback_gen import generate_callbacks -from jvppgen.jni_gen import generate_jni -from jvppgen.notification_gen import generate_notifications -from jvppgen.jvpp_future_facade_gen import generate_future_facade -from jvppgen.jvpp_callback_facade_gen import generate_callback_facade -from jvppgen.jvpp_model import JVppModel - - -def generate_jvpp(root_dir, model, logger): - base_dir = "%s/target/%s" % (root_dir, model.plugin_package.replace(".", "/")) - generate_types(_work_dir(base_dir, "types"), model, logger) - generate_enums(_work_dir(base_dir, "types"), model, logger) - generate_unions(_work_dir(base_dir, "types"), model, logger) - generate_dtos(_work_dir(base_dir, "dto"), model, logger) - generate_java_ifc(_work_dir(base_dir), model, logger) - generate_java_impl(_work_dir(base_dir), model, logger) - generate_callbacks(_work_dir(base_dir, "callback"), model, logger) - generate_jni(root_dir, model, logger) - generate_notifications(_work_dir(base_dir, "notification"), model, logger) - generate_future_facade(_work_dir(base_dir, "future"), model, logger) - generate_callback_facade(_work_dir(base_dir, "callfacade"), model, logger) - - -def _work_dir(work_dir, sub_dir=None): - if sub_dir: - work_dir = "%s/%s" % (work_dir, sub_dir) - try: - os.makedirs(work_dir) - except OSError: - if not os.path.isdir(work_dir): - raise - return work_dir - - -def _init_logger(): - try: - verbose = int(os.getenv("V", 0)) - except: - verbose = 0 - - log_level = logging.WARNING - if verbose == 1: - log_level = logging.INFO - elif verbose >= 2: - log_level = logging.DEBUG - - logging.basicConfig(stream=sys.stdout, level=log_level) - logger = logging.getLogger("JVPP GEN") - logger.setLevel(log_level) - return logger - - -if __name__ == '__main__': - logger = _init_logger() - - argparser = argparse.ArgumentParser(description="VPP Java API generator") - argparser.add_argument('-i', nargs='+', metavar='api_file.json', help="json vpp api file(s)") - argparser.add_argument('--plugin_name') - argparser.add_argument('--root_dir') - args = argparser.parse_args() - - logger.info("Generating Java API for %s" % args.i) - logger.debug("plugin_name: %s" % args.plugin_name) - logger.debug("root_dir: %s" % args.root_dir) - - model = JVppModel(logger, args.i, args.plugin_name) - generate_jvpp(args.root_dir, model, logger) diff --git a/extras/japi/java/jvpp/gen/jvppgen/__init__.py b/extras/japi/java/jvpp/gen/jvppgen/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 --- a/extras/japi/java/jvpp/gen/jvppgen/__init__.py +++ /dev/null diff --git a/extras/japi/java/jvpp/gen/jvppgen/callback_gen.py b/extras/japi/java/jvpp/gen/jvppgen/callback_gen.py deleted file mode 100755 index b1ad2013372..00000000000 --- a/extras/japi/java/jvpp/gen/jvppgen/callback_gen.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env python2 -# -# Copyright (c) 2016,2018 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 - -from jvpp_model import is_request, is_dump, is_control_ping, is_control_ping_reply - - -def generate_callbacks(work_dir, model, logger): - json_api_files = model.json_api_files - logger.debug("Generating Callback interfaces for %s" % json_api_files) - plugin_package = model.plugin_package - - callbacks = [] - for msg in model.messages: - name = msg.java_name_upper - if is_control_ping(msg) or is_control_ping_reply(msg): - # Skip control_ping managed by jvpp registry. - continue - if is_dump(msg) or is_request(msg): - continue - - callbacks.append("%s.callback.%sCallback" % (plugin_package, name)) - callback = _CALLBACK_TEMPLATE.substitute( - plugin_package=plugin_package, - json_filename=json_api_files, - name=name) - - with open("%s/%sCallback.java" % (work_dir, name), "w") as f: - f.write(callback) - - plugin_name = model.plugin_java_name - with open("%s/JVpp%sGlobalCallback.java" % (work_dir, plugin_name), "w") as f: - f.write(_GLOBAL_CALLBACK_TEMPLATE.substitute( - plugin_package=plugin_package, - json_filename=json_api_files, - plugin_name=plugin_name, - callbacks=", ".join(callbacks) - )) - -_CALLBACK_TEMPLATE = Template("""package $plugin_package.callback; - -/** - * <p>Represents callback for plugin's api message. - * <br>It was generated by jvppgen/callback_gen.py based on $json_filename. - */ -public interface ${name}Callback extends io.fd.vpp.jvpp.callback.JVppCallback { - - void on${name}(${plugin_package}.dto.${name} reply); -} -""") - -_GLOBAL_CALLBACK_TEMPLATE = Template("""package $plugin_package.callback; - -/** - * <p>Global aggregated callback interface. - * <br>It was generated by jvppgen/callback_gen.py based on $json_filename. - */ -public interface JVpp${plugin_name}GlobalCallback extends io.fd.vpp.jvpp.callback.ControlPingCallback, $callbacks { -} -""") diff --git a/extras/japi/java/jvpp/gen/jvppgen/dto_gen.py b/extras/japi/java/jvpp/gen/jvppgen/dto_gen.py deleted file mode 100755 index cbd969d51fe..00000000000 --- a/extras/japi/java/jvpp/gen/jvppgen/dto_gen.py +++ /dev/null @@ -1,231 +0,0 @@ -#!/usr/bin/env python2 -# -# Copyright (c) 2016,2018 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 - -from jvpp_common_gen import generate_hash_code, generate_equals, generate_to_string, generate_fields -from jvpp_model import is_request, is_reply, is_retval, is_dump, is_details, is_event, is_control_ping, \ - is_control_ping_reply - - -def generate_dtos(work_dir, model, logger): - logger.debug("Generating DTOs for %s " % model.json_api_files) - _generate_message_dtos(work_dir, model, logger) - _generate_dump_reply_wrappers(work_dir, model, logger) - - -def _generate_message_dtos(work_dir, model, logger): - for msg in model.messages: - logger.debug("Generating DTO for message %s", msg) - class_name = msg.java_name_upper - - if is_control_ping(msg) or is_control_ping_reply(msg): - # Skip control_ping managed by jvpp registry. - continue - if is_request(msg): - dto = _generate_request_dto(msg, model, base_type="JVppRequest") - elif is_dump(msg): - dto = _generate_request_dto(msg, model, base_type="JVppDump") - elif is_reply(msg) or is_details(msg): - dto = _generate_reply_dto(msg, model) - elif is_event(msg): - dto = _generate_event_dto(msg, model) - else: - logger.warn("Failed to generate DTO for: %s. Message type is not supported." % msg) - continue - with open("%s/%s.java" % (work_dir, class_name), "w") as f: - f.write(dto) - - -def _generate_request_dto(msg, model, base_type): - msg_java_name_upper = msg.java_name_upper - fields = msg.fields - return _REQUEST_TEMPLATE.substitute( - plugin_package=model.plugin_package, - json_filename=model.json_api_files, - json_definition=msg.doc, - class_name=msg_java_name_upper, - base_type=base_type, - fields=generate_fields(fields), - hash_code=generate_hash_code(fields), - equals=generate_equals(msg_java_name_upper, fields), - to_string=generate_to_string(msg_java_name_upper, fields), - send=_generate_send(model, msg)) - -_REQUEST_TEMPLATE = Template(""" -package $plugin_package.dto; - -/** - * <p>This class represents request DTO. - * <br>It was generated by dto_gen.py based on $json_filename: - * <pre> -$json_definition - * </pre> - */ -public final class $class_name implements io.fd.vpp.jvpp.dto.$base_type { -$fields -$hash_code -$equals -$to_string -$send -} -""") - - -def _generate_send(model, msg): - return _SEND_TEMPLATE.substitute( - plugin_package=model.plugin_package, - plugin_name=model.plugin_java_name, - method_name=msg.java_name_lower, - args="this" if msg.has_fields else "" - ) - -_SEND_TEMPLATE = Template(""" - @Override - public int send(final io.fd.vpp.jvpp.JVpp jvpp) throws io.fd.vpp.jvpp.VppInvocationException { - return (($plugin_package.JVpp${plugin_name})jvpp).$method_name($args); - }""") - - -def _generate_reply_dto(msg, model): - msg_java_name_upper = msg.java_name_upper - # Negative retval is mapped to java exception, so filter it out: - fields = filter(lambda field: not is_retval(field), msg.fields) - return _REPLY_TEMPLATE.substitute( - plugin_package=model.plugin_package, - json_filename=model.json_api_files, - json_definition=msg.doc, - class_name=msg_java_name_upper, - request_name=msg.request_java, - fields=generate_fields(fields), - hash_code=generate_hash_code(fields), - equals=generate_equals(msg_java_name_upper, fields), - to_string=generate_to_string(msg_java_name_upper, fields)) - -_REPLY_TEMPLATE = Template(""" -package $plugin_package.dto; - -/** - * <p>This class represents reply DTO. - * <br>It was generated by jvpp_dto_gen.py based on $json_filename: - * <pre> -$json_definition - * </pre> - */ -public final class $class_name implements io.fd.vpp.jvpp.dto.JVppReply<$plugin_package.dto.$request_name> { -$fields -$hash_code -$equals -$to_string -} -""") - - -def _generate_event_dto(msg, model): - msg_java_name_upper = msg.java_name_upper - # Negative retval is mapped to java exception, so filter it out: - fields = filter(lambda field: not is_retval(field), msg.fields) - return _EVENT_TEMPLATE.substitute( - plugin_package=model.plugin_package, - json_filename=model.json_api_files, - json_definition=msg.doc, - class_name=msg_java_name_upper, - fields=generate_fields(fields), - hash_code=generate_hash_code(fields), - equals=generate_equals(msg_java_name_upper, fields), - to_string=generate_to_string(msg_java_name_upper, fields)) - -_EVENT_TEMPLATE = Template(""" -package $plugin_package.dto; - -/** - * <p>This class represents event DTO. - * <br>It was generated by jvpp_dto_gen.py based on $json_filename: - * <pre> -$json_definition - * </pre> - */ -public final class $class_name { -$fields -$hash_code -$equals -$to_string -} -""") - - -def _generate_dump_reply_wrappers(work_dir, model, logger): - for msg in model.messages: - if is_details(msg): - logger.debug("Generating ReplyDump DTO for message %s", msg) - details_class = msg.java_name_upper - dto = _REPLY_DUMP_TEMPLATE.substitute( - plugin_package=model.plugin_package, - json_filename=model.json_api_files, - json_definition=msg.doc, - details_class=details_class, - details_field=msg.java_name_lower, - dump_class=msg.request_java - ) - with open("%s/%sReplyDump.java" % (work_dir, details_class), "w") as f: - f.write(dto) - -_REPLY_DUMP_TEMPLATE = Template(""" -package $plugin_package.dto; - -/** - * <p>This class represents dump reply wrapper. - * <br>It was generated by jvpp_dto_gen.py based on $json_filename: - * <pre> -$json_definition - * </pre> - */ -public final class ${details_class}ReplyDump implements io.fd.vpp.jvpp.dto.JVppReplyDump<${plugin_package}.dto.${dump_class}, ${plugin_package}.dto.${details_class}> { - - public java.util.List<${details_class}> ${details_field} = new java.util.ArrayList<>(); - - @Override - @io.fd.vpp.jvpp.coverity.SuppressFBWarnings("UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD") - public int hashCode() { - return java.util.Objects.hash(${details_field}); - } - - @Override - public boolean equals(final Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - final ${details_class}ReplyDump other = (${details_class}ReplyDump) o; - - if (!java.util.Objects.equals(this.${details_field}, other.${details_field})) { - return false; - } - - return true; - } - - @Override - public java.lang.String toString() { - return "${details_class}ReplyDump{" + - "${details_field}=" + ${details_field} + "}"; - } - - -} -""") diff --git a/extras/japi/java/jvpp/gen/jvppgen/enums_gen.py b/extras/japi/java/jvpp/gen/jvppgen/enums_gen.py deleted file mode 100755 index 8ba96558428..00000000000 --- a/extras/japi/java/jvpp/gen/jvppgen/enums_gen.py +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/env python2 -# -# Copyright (c) 2016,2018 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 - -from jvpp_model import Enum - - -def generate_enums(work_dir, model, logger): - logger.debug("Generating enums for %s " % model.json_api_files) - - for t in model.types: - if not isinstance(t, Enum): - continue - logger.debug("Generating DTO for enum %s", t) - type_class_name = t.java_name - type_class = _ENUM_TEMPLATE.substitute( - plugin_package=model.plugin_package, - c_type_name=t.name, - json_filename=model.json_api_files, - json_definition=t.doc, - java_enum_name=type_class_name, - constants=_generate_constants(t.constants), - value_type=t.value.type.java_name - ) - with open("%s/%s.java" % (work_dir, type_class_name), "w") as f: - f.write(type_class) - -_ENUM_TEMPLATE = Template(""" -package $plugin_package.types; - -/** - * <p>This class represents $c_type_name enum definition. - * <br>It was generated by enums_gen.py based on $json_filename: - * <pre> -$json_definition - * </pre> - */ -public enum $java_enum_name { -$constants; - - public final $value_type value; - - $java_enum_name(final $value_type value) { - this.value = value; - } - - public static $java_enum_name forValue(final $value_type value) { - for ($java_enum_name enumeration : $java_enum_name.values()) { - if (value == enumeration.value) { - return enumeration; - } - } - return null; - } -} -""") - - -def _generate_constants(constants): - return ",\n".join(_CONSTANT_TEMPLATE.substitute(name=c['name'], value=c['value']) for c in constants) - -_CONSTANT_TEMPLATE = Template(""" $name($value)""") diff --git a/extras/japi/java/jvpp/gen/jvppgen/jni_common_gen.py b/extras/japi/java/jvpp/gen/jvppgen/jni_common_gen.py deleted file mode 100755 index b52e5ff2d2c..00000000000 --- a/extras/japi/java/jvpp/gen/jvppgen/jni_common_gen.py +++ /dev/null @@ -1,482 +0,0 @@ -#!/usr/bin/env python2 -# -# Copyright (c) 2018 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 - -from jvpp_model import is_array, is_retval, Class, Enum, Union - - -def generate_j2c_identifiers(element, class_ref_name, object_ref_name): - identifiers = [] - for field in element.fields: - field_type = field.type - identifiers.append(_REQUEST_FIELD_IDENTIFIER_TEMPLATE.substitute( - java_name=field.java_name, - class_ref_name=class_ref_name, - jni_signature=field_type.jni_signature, - jni_type=field_type.jni_type, - jni_accessor=field_type.jni_accessor, - object_ref_name=object_ref_name - )) - return "".join(identifiers) - -_REQUEST_FIELD_IDENTIFIER_TEMPLATE = Template(""" - jfieldID ${java_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}, "${java_name}", "${jni_signature}"); - ${jni_type} ${java_name} = (*env)->Get${jni_accessor}Field(env, ${object_ref_name}, ${java_name}FieldId); -""") - - -# TODO(VPP-1187): do not inline JNI object creation inside message handlers to reduce number of special cases -def generate_j2c_swap(element, struct_ref_name, is_alias): - initialization = [] - for field in element.fields: - initialization.append(generate_j2c_field_swap(field, struct_ref_name, is_alias)) - return "\n".join(initialization) - - -def generate_j2c_field_swap(field, struct_ref_name, is_alias): - if is_array(field): - return _generate_j2c_array_swap(field, struct_ref_name, is_alias) - else: - return _generate_j2c_scalar_swap(field, struct_ref_name, is_alias) - - -def _generate_j2c_array_swap(field, struct_ref_name, is_alias): - # TODO(VPP-1186): move the logic to JNI generators - base_type = field.type.base_type - if isinstance(base_type, (Class, Enum, Union)): - return _generate_j2c_object_array_swap(field, struct_ref_name) - elif base_type.is_swap_needed: - return _generate_j2c_primitive_type_array_swap(field, struct_ref_name) - else: - return _generate_j2c_primitive_type_array_no_swap(field, struct_ref_name, is_alias) - - -def _generate_j2c_object_array_swap(field, struct_ref_name): - field_type = field.type - field_reference_name = field.java_name - c_name = field.name - host = "%sArrayElement" % field_reference_name - net = "%s->%s[_i]" % (struct_ref_name, c_name) - swap_elements = field_type.get_host_to_net_function(host, net) - return _J2C_OBJECT_ARRAY_SWAP_TEMPLATE.substitute( - field_reference_name=field_reference_name, - field_length_check=_generate_field_length_check(field), - swap_elements=swap_elements) - -_J2C_OBJECT_ARRAY_SWAP_TEMPLATE = Template(""" - { - 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); - ${swap_elements}; - } - } - } -""") - - -def _generate_j2c_primitive_type_array_swap(field, struct_ref_name): - field_reference_name = field.java_name - field_type = field.type - host = "%sArrayElements[_i]" % field_reference_name - net = "%s->%s[_i]" % (struct_ref_name, field.name) - swap_elements = field_type.get_host_to_net_function(host, net) - return _J2C_PRIMITIVE_TYPE_ARRAY_SWAP_TEMPLATE.substitute( - field_reference_name=field_reference_name, - field_length_check=_generate_field_length_check(field), - base_type=field_type.base_type.jni_accessor, - jni_base_type=field_type.base_type.jni_type, - swap_elements=swap_elements - ) - -_J2C_PRIMITIVE_TYPE_ARRAY_SWAP_TEMPLATE = Template(""" - if (${field_reference_name}) { - ${jni_base_type} * ${field_reference_name}ArrayElements = (*env)->Get${base_type}ArrayElements(env, ${field_reference_name}, NULL); - size_t _i; - jsize cnt = (*env)->GetArrayLength(env, ${field_reference_name}); - ${field_length_check} - for (_i = 0; _i < cnt; _i++) { - ${swap_elements}; - } - (*env)->Release${base_type}ArrayElements (env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0); - } - """) - - -def _generate_j2c_primitive_type_array_no_swap(field, struct_ref_name, is_alias): - field_type = field.type - if not is_alias: - template = _J2C_PRIMITIVE_TYPE_ARRAY_NO_SWAP_TEMPLATE - else: - template = _J2C_ALIAS_PRIMITIVE_TYPE_ARRAY_NO_SWAP_TEMPLATE - - return template.substitute( - field_reference_name=field.java_name, - field_length_check=_generate_field_length_check(field), - base_type=field_type.base_type.jni_accessor, - jni_base_type=field_type.base_type.jni_type, - struct_reference_name=struct_ref_name, - c_name=field.name - ) - -_J2C_PRIMITIVE_TYPE_ARRAY_NO_SWAP_TEMPLATE = Template(""" - if (${field_reference_name}) { - jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name}); - ${field_length_check} - (*env)->Get${base_type}ArrayRegion(env, ${field_reference_name}, 0, cnt, (${jni_base_type} *)${struct_reference_name}->${c_name}); - } -""") - - -_J2C_ALIAS_PRIMITIVE_TYPE_ARRAY_NO_SWAP_TEMPLATE = Template(""" - if (${field_reference_name}) { - jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name}); - ${field_length_check} - (*env)->Get${base_type}ArrayRegion(env, ${field_reference_name}, 0, cnt, (${jni_base_type} *)${struct_reference_name}); - } -""") - - -def _generate_field_length_check(field): - # Enforce max length if array has fixed length or uses variable length syntax - field_length = str(field.array_len) - if field.array_len_field: - field_length = field.array_len_field.java_name - - # TODO: remove when ZLAs without length field are disabled - if field_length != "0": - return _FIELD_LENGTH_CHECK.substitute(field_length=field_length) - else: - return "" - - -# Make sure we do not write more elements that are expected -_FIELD_LENGTH_CHECK = Template(""" - size_t max_size = ${field_length}; - if (cnt > max_size) cnt = max_size;""") - - -def _generate_j2c_scalar_swap(field, struct_ref_name, is_alias): - field_type = field.type - if field_type.is_swap_needed: - host = field.java_name - if not is_alias: - net = "%s->%s" % (struct_ref_name, field.name) - if field_type.name == "string": - net = "%s->%s" % (struct_ref_name, field.name) - return " _host_to_net_%s(env, %s, (vl_api_string_t *) &%s);" % (field_type.name, host, net) - else: - return " %s;" % field_type.get_host_to_net_function(host, net) - else: - net = "%s" % struct_ref_name - return " *%s;" % field_type.get_host_to_net_function(host, net) - else: - return " %s->%s = %s;" % (struct_ref_name, field.name, field.java_name) - - -def generate_c2j_swap(element, object_ref_name, struct_ref_name, is_alias): - msg_java_name = element.java_name_lower - initialization = [] - for field in element.fields: - if is_retval(field): - # For retval don't generate setters and generate retval check - continue - elif is_array(field): - initialization.append(_generate_c2j_array_swap(msg_java_name, field, object_ref_name, struct_ref_name, is_alias)) - else: - initialization.append(_generate_c2j_scalar_swap(msg_java_name, field, object_ref_name, struct_ref_name, is_alias)) - return "".join(initialization) - - -def _generate_c2j_array_swap(msg_java_name, field, object_ref_name, struct_ref_name, is_alias): - # TODO(VPP-1186): move the logic to JNI generators - base_type = field.type.base_type - if isinstance(base_type, (Class, Union)): - return _generate_c2j_object_array_swap(msg_java_name, field, object_ref_name, struct_ref_name) - elif isinstance(base_type, Enum): - return _generate_c2j_enum_array_swap(msg_java_name, field, object_ref_name, struct_ref_name) - elif base_type.is_swap_needed: - return _generate_c2j_primitive_type_array_swap(msg_java_name, field, object_ref_name, struct_ref_name) - else: - return _generate_c2j_primitive_type_array_no_swap(msg_java_name, field, object_ref_name, struct_ref_name, is_alias) - - -def _generate_c2j_object_array_swap(msg_java_name, field, object_ref_name, struct_ref_name): - field_type = field.type - return _C2J_OBJECT_ARRAY_SWAP_TEMPLATE.substitute( - field_reference_name=field.java_name, - class_ref_name=msg_java_name, - jni_signature=field_type.jni_signature, - jni_name=field_type.base_type.jni_name, - field_length=_generate_array_length(field, struct_ref_name), - net_to_host_function=field_type.net_to_host_function, - struct_ref_name=struct_ref_name, - object_ref_name=object_ref_name, - c_name=field.name - ) - -_C2J_OBJECT_ARRAY_SWAP_TEMPLATE = Template(""" - jfieldID ${field_reference_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${field_reference_name}", "${jni_signature}"); - { - jclass ${field_reference_name}Class = (*env)->FindClass(env, "${jni_name}"); - jobjectArray ${field_reference_name} = (*env)->NewObjectArray(env, ${field_length}, ${field_reference_name}Class, 0); - jmethodID ${field_reference_name}Constructor = (*env)->GetMethodID(env, ${field_reference_name}Class, "<init>", "()V"); - unsigned int _i; - for (_i = 0; _i < ${field_length}; _i++) { - jobject ${field_reference_name}ArrayElement = (*env)->NewObject(env, ${field_reference_name}Class, ${field_reference_name}Constructor); - ${net_to_host_function}(env, &(${struct_ref_name}->${c_name}[_i]), ${field_reference_name}ArrayElement); - (*env)->SetObjectArrayElement(env, ${field_reference_name}, _i, ${field_reference_name}ArrayElement); - (*env)->DeleteLocalRef(env, ${field_reference_name}ArrayElement); - } - (*env)->SetObjectField(env, ${object_ref_name}, ${field_reference_name}FieldId, ${field_reference_name}); - (*env)->DeleteLocalRef(env, ${field_reference_name}); - } -""") - - -def _generate_c2j_enum_array_swap(msg_java_name, field, object_ref_name, struct_ref_name): - field_type = field.type - base_type = field_type.base_type - return _C2J_ENUM_ARRAY_SWAP_TEMPLATE.substitute( - field_reference_name=field.java_name, - class_ref_name=msg_java_name, - jni_signature=field_type.jni_signature, - jni_name=base_type.jni_name, - field_length=_generate_array_length(field, struct_ref_name), - net_to_host_function=field_type.net_to_host_function, - jni_signature_enum_value=base_type.value.type.jni_signature, - struct_ref_name=struct_ref_name, - object_ref_name=object_ref_name, - c_name=field.name - ) - -_C2J_ENUM_ARRAY_SWAP_TEMPLATE = Template(""" - jfieldID ${field_reference_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${field_reference_name}", "${jni_signature}"); - { - jclass ${field_reference_name}Class = (*env)->FindClass(env, "${jni_name}"); - jobjectArray ${field_reference_name} = (*env)->NewObjectArray(env, ${field_length}, ${field_reference_name}Class, 0); - jmethodID ${field_reference_name}Constructor = (*env)->GetStaticMethodID(env, ${field_reference_name}Class, "forValue", "(${jni_signature_enum_value})${jni_signature}"); - unsigned int _i; - for (_i = 0; _i < ${field_length}; _i++) { - jobject ${field_reference_name}ArrayElement = (*env)->CallStaticObjectMethod(env, ${field_reference_name}Class, ${field_reference_name}Constructor, ${net_to_host_function}(${struct_ref_name}->${c_name}[_i])); - (*env)->SetObjectArrayElement(env, ${field_reference_name}, _i, ${field_reference_name}ArrayElement); - (*env)->DeleteLocalRef(env, ${field_reference_name}ArrayElement); - } - (*env)->SetObjectField(env, ${object_ref_name}, ${field_reference_name}FieldId, ${field_reference_name}); - (*env)->DeleteLocalRef(env, ${field_reference_name}); - } -""") - - -def _generate_c2j_primitive_type_array_swap(msg_java_name, field, object_ref_name, struct_ref_name): - field_type = field.type - return _C2J_PRIMITIVE_TYPE_ARRAY_SWAP_TEMPLATE.substitute( - field_reference_name=field.java_name, - class_ref_name=msg_java_name, - jni_signature=field_type.jni_signature, - jni_type=field_type.jni_type, - base_type=field_type.base_type.jni_accessor, - field_length=_generate_array_length(field, struct_ref_name), - jni_base_type=field_type.base_type.jni_type, - object_ref_name=object_ref_name, - struct_ref_name=struct_ref_name, - net_to_host_function=field_type.net_to_host_function, - c_name=field.name - ) - -_C2J_PRIMITIVE_TYPE_ARRAY_SWAP_TEMPLATE = Template(""" - jfieldID ${field_reference_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${field_reference_name}", "${jni_signature}"); - { - ${jni_type} ${field_reference_name} = (*env)->New${base_type}Array(env, ${field_length}); - ${jni_base_type} * ${field_reference_name}ArrayElements = (*env)->Get${base_type}ArrayElements(env, ${field_reference_name}, NULL); - unsigned int _i; - for (_i = 0; _i < ${field_length}; _i++) { - ${field_reference_name}ArrayElements[_i] = ${net_to_host_function}(${struct_ref_name}->${c_name}[_i]); - } - - (*env)->Release${base_type}ArrayElements(env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0); - (*env)->SetObjectField(env, ${object_ref_name}, ${field_reference_name}FieldId, ${field_reference_name}); - (*env)->DeleteLocalRef(env, ${field_reference_name}); - } -""") - - -def _generate_c2j_primitive_type_array_no_swap(msg_java_name, field, object_ref_name, struct_ref_name, is_alias): - field_type = field.type - if not is_alias: - template = _C2J_PRIMITIVE_TYPE_ARRAY_NO_SWAP_TEMPLATE - else: - template = _C2J_ALIAS_PRIMITIVE_TYPE_ARRAY_NO_SWAP_TEMPLATE - return template.substitute( - field_reference_name=field.java_name, - class_ref_name=msg_java_name, - jni_signature=field_type.jni_signature, - jni_type=field_type.jni_type, - base_type=field_type.base_type.jni_accessor, - field_length=_generate_array_length(field, struct_ref_name), - jni_base_type=field_type.base_type.jni_type, - object_ref_name=object_ref_name, - struct_ref_name=struct_ref_name, - c_name=field.name - ) - -_C2J_PRIMITIVE_TYPE_ARRAY_NO_SWAP_TEMPLATE = Template(""" - jfieldID ${field_reference_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${field_reference_name}", "${jni_signature}"); - ${jni_type} ${field_reference_name} = (*env)->New${base_type}Array(env, ${field_length}); - (*env)->Set${base_type}ArrayRegion(env, ${field_reference_name}, 0, ${field_length}, (const ${jni_base_type}*)${struct_ref_name}->${c_name}); - (*env)->SetObjectField(env, ${object_ref_name}, ${field_reference_name}FieldId, ${field_reference_name}); - (*env)->DeleteLocalRef(env, ${field_reference_name}); -""") - - -_C2J_ALIAS_PRIMITIVE_TYPE_ARRAY_NO_SWAP_TEMPLATE = Template(""" - jfieldID ${field_reference_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${field_reference_name}", "${jni_signature}"); - ${jni_type} ${field_reference_name} = (*env)->New${base_type}Array(env, ${field_length}); - (*env)->Set${base_type}ArrayRegion(env, ${field_reference_name}, 0, ${field_length}, (const ${jni_base_type}*)${struct_ref_name}); - (*env)->SetObjectField(env, ${object_ref_name}, ${field_reference_name}FieldId, ${field_reference_name}); - (*env)->DeleteLocalRef(env, ${field_reference_name}); -""") - - -def _generate_array_length(field, struct_ref_name): - if field.array_len_field: - len_field = field.array_len_field - if len_field.type.is_swap_needed: - return "%s(%s->%s)" % (len_field.type.host_to_net_function, struct_ref_name, len_field.name) - else: - return "%s->%s" % (struct_ref_name, len_field.name) - return field.array_len - - -def _generate_c2j_scalar_swap(msg_java_name, field, object_ref_name, struct_ref_name, is_alias): - field_type = field.type - if field_type.is_swap_needed: - # TODO(VPP-1186): move the logic to JNI generators - if isinstance(field_type, (Class, Union)): - return _generate_c2j_object_swap(msg_java_name, field, object_ref_name, struct_ref_name) - elif isinstance(field_type, Enum): - return _generate_c2j_enum_swap(msg_java_name, field, object_ref_name, struct_ref_name) - else: - return _generate_c2j_primitive_type_swap(msg_java_name, field, object_ref_name, struct_ref_name, is_alias) - else: - return _generate_c2j_primitive_type_no_swap(msg_java_name, field, object_ref_name, struct_ref_name) - - -def _generate_c2j_object_swap(msg_java_name, field, object_ref_name, struct_ref_name): - field_type = field.type - return _C2J_OBJECT_SWAP_TEMPLATE.substitute( - java_name=field.java_name, - class_ref_name=msg_java_name, - jni_signature=field_type.jni_signature, - jni_name=field_type.jni_name, - jni_accessor=field_type.jni_accessor, - object_ref_name=object_ref_name, - struct_ref_name=struct_ref_name, - net_to_host_function=field_type.net_to_host_function, - c_name=field.name) - -_C2J_OBJECT_SWAP_TEMPLATE = Template(""" - jfieldID ${java_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${java_name}", "${jni_signature}"); - jclass ${java_name}Class = (*env)->FindClass(env, "${jni_name}"); - jmethodID ${java_name}Constructor = (*env)->GetMethodID(env, ${java_name}Class, "<init>", "()V"); - jobject ${java_name} = (*env)->NewObject(env, ${java_name}Class, ${java_name}Constructor); - ${net_to_host_function}(env, &(${struct_ref_name}->${c_name}), ${java_name}); - (*env)->Set${jni_accessor}Field(env, ${object_ref_name}, ${java_name}FieldId, ${java_name}); - (*env)->DeleteLocalRef(env, ${java_name}); -""") - - -def _generate_c2j_enum_swap(msg_java_name, field, object_ref_name, struct_ref_name): - field_type = field.type - return _C2J_ENUM_SWAP_TEMPLATE.substitute( - java_name=field.java_name, - class_ref_name=msg_java_name, - jni_signature=field_type.jni_signature, - jni_signature_enum_value=field_type.value.type.jni_signature, - jni_name=field_type.jni_name, - jni_accessor=field_type.jni_accessor, - object_ref_name=object_ref_name, - struct_ref_name=struct_ref_name, - net_to_host_function=field_type.net_to_host_function, - c_name=field.name) - -_C2J_ENUM_SWAP_TEMPLATE = Template(""" - jfieldID ${java_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${java_name}", "${jni_signature}"); - jclass ${java_name}Class = (*env)->FindClass(env, "${jni_name}"); - jmethodID ${java_name}Constructor = (*env)->GetStaticMethodID(env, ${java_name}Class, "forValue", "(${jni_signature_enum_value})${jni_signature}"); - jobject ${java_name} = (*env)->CallStaticObjectMethod(env, ${java_name}Class, ${java_name}Constructor, ${net_to_host_function}(${struct_ref_name}->${c_name})); - (*env)->SetObjectField(env, ${object_ref_name}, ${java_name}FieldId, ${java_name}); - (*env)->DeleteLocalRef(env, ${java_name}); -""") - - -def _generate_c2j_primitive_type_swap(msg_java_name, field, object_ref_name, struct_ref_name, is_alias): - field_type = field.type - if not is_alias: - if field_type.name == "string": - template = _C2J_STRING_TYPE_SWAP_TEMPLATE - else: - template = _C2J_PRIMITIVE_TYPE_SWAP_TEMPLATE - else: - template = _C2J_ALIAS_PRIMITIVE_TYPE_SWAP_TEMPLATE - return template.substitute( - java_name=field.java_name, - class_ref_name=msg_java_name, - jni_signature=field_type.jni_signature, - jni_accessor=field_type.jni_accessor, - object_ref_name=object_ref_name, - net_to_host_function=field_type.net_to_host_function, - struct_ref_name=struct_ref_name, - c_name=field.name - ) - -_C2J_PRIMITIVE_TYPE_SWAP_TEMPLATE = Template(""" - jfieldID ${java_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${java_name}", "${jni_signature}"); - (*env)->Set${jni_accessor}Field(env, ${object_ref_name}, ${java_name}FieldId, ${net_to_host_function}(${struct_ref_name}->${c_name})); -""") - - -_C2J_STRING_TYPE_SWAP_TEMPLATE = Template(""" - jfieldID ${java_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${java_name}", "${jni_signature}"); - (*env)->Set${jni_accessor}Field(env, ${object_ref_name}, ${java_name}FieldId, ${net_to_host_function}(env, (const vl_api_string_t *) &${struct_ref_name}->${c_name})); -""") - - -_C2J_ALIAS_PRIMITIVE_TYPE_SWAP_TEMPLATE = Template(""" - jfieldID ${java_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${java_name}", "${jni_signature}"); - (*env)->Set${jni_accessor}Field(env, ${object_ref_name}, ${java_name}FieldId, ${net_to_host_function}(*${struct_ref_name})); -""") - - -def _generate_c2j_primitive_type_no_swap(msg_java_name, field, object_ref_name, struct_ref_name): - field_type = field.type - return _C2J_PRIMITIVE_TYPE_NO_SWAP_TEMPLATE.substitute( - java_name=field.java_name, - class_ref_name=msg_java_name, - jni_signature=field_type.jni_signature, - jni_accessor=field_type.jni_accessor, - object_ref_name=object_ref_name, - struct_ref_name=struct_ref_name, - c_name=field.name - ) - -_C2J_PRIMITIVE_TYPE_NO_SWAP_TEMPLATE = Template(""" - jfieldID ${java_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${java_name}", "${jni_signature}"); - (*env)->Set${jni_accessor}Field(env, ${object_ref_name}, ${java_name}FieldId, ${struct_ref_name}->${c_name}); -""") diff --git a/extras/japi/java/jvpp/gen/jvppgen/jni_gen.py b/extras/japi/java/jvpp/gen/jvppgen/jni_gen.py deleted file mode 100755 index ad6c2614062..00000000000 --- a/extras/japi/java/jvpp/gen/jvppgen/jni_gen.py +++ /dev/null @@ -1,160 +0,0 @@ -#!/usr/bin/env python2 -# -# Copyright (c) 2016,2018 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 - -from jni_impl_gen import generate_jni_impl -from jni_msg_handlers_gen import generate_jni_handlers -from jni_type_handlers_gen import generate_type_handlers -from jvpp_model import is_control_ping, is_dump, is_request, is_control_ping_reply - - -def generate_jni(work_dir, model, logger): - logger.debug("Generating jvpp C for %s" % model.json_api_files) - plugin_name = model.plugin_name - messages = model.messages - - with open("%s/jvpp_%s_gen.h" % (work_dir, plugin_name), "w") as f: - f.write(_JVPP_C_TEMPLATE.substitute( - json_filename=model.json_api_files, - class_cache=_generate_class_cache(plugin_name, messages), - api_verification=_generate_api_verification(messages), - type_handlers=generate_type_handlers(model, logger), - jni_implementations=generate_jni_impl(model), - msg_handlers=generate_jni_handlers(model), - handler_registration=_generate_handler_registration(messages))) - -_JVPP_C_TEMPLATE = Template("""/** - * This file contains JNI bindings for jvpp Java API. - * It was generated by jvpp_jni_gen.py based on $json_filename. - */ -$class_cache - -$api_verification - -// Type handlers -$type_handlers - -// JNI bindings -$jni_implementations - -// Message handlers -$msg_handlers - -$handler_registration -""") - - -def _generate_class_cache(plugin_name, messages): - references = [] - for msg in messages: - if is_control_ping(msg) or is_control_ping_reply(msg): - # Skip control_ping managed by jvpp registry. - continue - references.append(( - msg.java_name_lower, - 'io/fd/vpp/jvpp/%s/dto/%s' % (plugin_name, msg.java_name_upper) - )) - - references.append(('callbackException', 'io/fd/vpp/jvpp/VppCallbackException')) - - return _CLASS_CACHE_TEMPLATE.substitute( - class_references=_generate_class_references(references), - create_references=_generate_create_references(references), - delete_references=_generate_delete_references(references) - ) - -_CLASS_CACHE_TEMPLATE = Template(""" -// JAVA class reference cache -$class_references - -static int cache_class_references(JNIEnv* env) { -$create_references - return 0; -} - -static void delete_class_references(JNIEnv* env) { -$delete_references -}""") - - -def _generate_class_references(references): - return "\n".join("jclass %sClass;" % r[0] for r in references) - - -def _generate_create_references(references): - items = [] - for r in references: - items.append(_CREATE_GLOBAL_REF_TEMPLATE.substitute( - ref_name=r[0], - fqn_name=r[1] - )) - return "".join(items) - -_CREATE_GLOBAL_REF_TEMPLATE = Template(""" - ${ref_name}Class = (jclass)(*env)->NewGlobalRef(env, (*env)->FindClass(env, "${fqn_name}")); - if ((*env)->ExceptionCheck(env)) { - (*env)->ExceptionDescribe(env); - return JNI_ERR; - }""") - - -def _generate_delete_references(references): - items = [] - for r in references: - items.append(_DELETE_CLASS_INVOCATION_TEMPLATE.substitute(ref_name=r[0])) - return "".join(items) - -_DELETE_CLASS_INVOCATION_TEMPLATE = Template(""" - if (${ref_name}Class) { - (*env)->DeleteGlobalRef(env, ${ref_name}Class); - }""") - - -def _generate_api_verification(messages): - items = [] - for msg in messages: - items.append("_(%s_%s) \\" % (msg.name, msg.crc)) - return _API_VERIFICATION_TEMPLATE.substitute(messages="\n".join(items)) - -_API_VERIFICATION_TEMPLATE = Template(""" -// List of supported API messages used for verification -#define foreach_supported_api_message \\ -$messages -""") - - -def _generate_handler_registration(messages): - """ - Generates msg handler registration for all messages except for dumps and requests. - :param messages: collection of VPP API messages. - """ - handlers = [] - for msg in messages: - if is_control_ping(msg) or is_control_ping_reply(msg): - # Skip control_ping managed by jvpp registry. - continue - if is_dump(msg) or is_request(msg): - continue - name = msg.name - crc = msg.crc - handlers.append("_(%s_%s, %s) \\" % (name, crc, name)) - return _HANDLER_REGISTRATION_TEMPLATE.substitute(handlers="\n".join(handlers)) - -_HANDLER_REGISTRATION_TEMPLATE = Template(""" -// Registration of message handlers in vlib -#define foreach_api_reply_handler \\ -$handlers -""") diff --git a/extras/japi/java/jvpp/gen/jvppgen/jni_impl_gen.py b/extras/japi/java/jvpp/gen/jvppgen/jni_impl_gen.py deleted file mode 100755 index 2941778f208..00000000000 --- a/extras/japi/java/jvpp/gen/jvppgen/jni_impl_gen.py +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env python2 -# -# Copyright (c) 2018 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 - -from jni_common_gen import generate_j2c_identifiers, generate_j2c_swap -from jvpp_model import is_dump, is_request, is_control_ping, is_control_ping_reply - - -def generate_jni_impl(model): - """ - Generates JNI bindings for sending dump and request messages. - :param model: meta-model of VPP API used for jVPP generation. - """ - jni_impl = [] - for msg in model.messages: - if is_control_ping(msg) or is_control_ping_reply(msg): - # Skip control ping managed by jvpp registry. - continue - if not (is_dump(msg) or is_request(msg)): - continue - arguments = "" - request_class = "" - jni_identifiers = "" - msg_initialization = "" - - if msg.has_fields: - arguments = ", jobject request" - request_class = _REQUEST_CLASS_TEMPLATE.substitute( - plugin_name=model.plugin_name, - java_dto_name=msg.java_name_upper - ) - jni_identifiers = generate_j2c_identifiers(msg, class_ref_name="requestClass", object_ref_name="request") - msg_initialization = generate_j2c_swap(msg, struct_ref_name="mp", is_alias=False) - - jni_impl.append(_JNI_IMPL_TEMPLATE.substitute( - c_name=msg.name, - json_filename=model.json_api_files, - json_definition=msg.doc, - plugin_name=model.plugin_name, - plugin_java_name=model.plugin_java_name, - java_method_name=msg.java_name_lower, - arguments=arguments, - request_class=request_class, - jni_identifiers=jni_identifiers, - msg_size=_generate_msg_size(msg), - crc=msg.crc, - msg_initialization=msg_initialization - )) - return "".join(jni_impl) - - -_JNI_IMPL_TEMPLATE = Template(""" -/** - * JNI binding for sending ${c_name} message. - * Generated based on $json_filename: -$json_definition - */ -JNIEXPORT jint JNICALL Java_io_fd_vpp_jvpp_${plugin_name}_JVpp${plugin_java_name}Impl_${java_method_name}0 -(JNIEnv * env, jclass clazz${arguments}) { - ${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 -$jni_identifiers - - // create message: - const size_t _size = ${msg_size}; - mp = vl_msg_api_alloc(_size); - memset (mp, 0, _size); - mp->_vl_msg_id = ntohs (get_message_id(env, "${c_name}_${crc}")); - mp->client_index = plugin_main->my_client_index; - mp->context = clib_host_to_net_u32 (my_context_id); - -$msg_initialization - - // send message: - if (CLIB_DEBUG > 1) - clib_warning ("Sending ${c_name} message"); - vl_msg_api_send_shmem (plugin_main->vl_input_queue, (u8 *)&mp); - if ((*env)->ExceptionCheck(env)) { - return JNI_ERR; - } - return my_context_id; -}""") - -# TODO: cache method and field identifiers to achieve better performance -# https://jira.fd.io/browse/HONEYCOMB-42 -_REQUEST_CLASS_TEMPLATE = Template(""" jclass requestClass = (*env)->FindClass(env, "io/fd/vpp/jvpp/${plugin_name}/dto/${java_dto_name}"); -""") - - -def _generate_msg_size(msg): - msg_size = "sizeof(*mp)" - _size_components = [] - for field in msg.fields: - # Ignore ZLAs for simplicity (to support them we need to call JNI functions to check actual size) - if field.array_len_field: - _size_components += " + %s*sizeof(%s)" % (field.array_len_field.java_name, field.type.base_type.vpp_name) - # FIXME(VPP-586): for proper nested structures support, we need generate functions computing type sizes - # and use it instead of sizeof - if field.type.name == "string": - _size_components += " + jstr_length(env, %s) * sizeof(u8)" % field.name - return msg_size + "".join(_size_components) diff --git a/extras/japi/java/jvpp/gen/jvppgen/jni_msg_handlers_gen.py b/extras/japi/java/jvpp/gen/jvppgen/jni_msg_handlers_gen.py deleted file mode 100755 index 5f274a3e1dd..00000000000 --- a/extras/japi/java/jvpp/gen/jvppgen/jni_msg_handlers_gen.py +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env python2 -# -# Copyright (c) 2018 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 - -from jni_common_gen import generate_c2j_swap -from jvpp_model import is_dump, is_request, is_control_ping, is_control_ping_reply, is_retval - - -def generate_jni_handlers(model): - """ - Generates msg handlers for all messages except for dumps and requests (handled by vpp, not client). - :param model: meta-model of VPP API used for jVPP generation. - """ - jni_impl = [] - for msg in model.messages: - msg_name = msg.name - if is_control_ping(msg) or is_control_ping_reply(msg): - # Skip control ping managed by jvpp registry. - continue - if is_dump(msg) or is_request(msg): - continue - - jni_impl.append(_MSG_HANDLER_TEMPLATE.substitute( - c_name=msg_name, - json_filename=model.json_api_files, - json_definition=msg.doc, - plugin_name=model.plugin_name, - err_handler=_generate_error_handler(msg), - class_ref_name=msg.java_name_lower, - dto_name=msg.java_name_upper, - dto_setters=generate_c2j_swap(msg, object_ref_name="dto", struct_ref_name="mp", is_alias=False) - )) - return "".join(jni_impl) - -_MSG_HANDLER_TEMPLATE = Template(""" -/** - * Handler for ${c_name} message. - * Generated based on $json_filename: -$json_definition - */ -static void vl_api_${c_name}_t_handler (vl_api_${c_name}_t * mp) -{ - ${plugin_name}_main_t *plugin_main = &${plugin_name}_main; - JNIEnv *env = jvpp_main.jenv; - jthrowable exc; -$err_handler - - if (CLIB_DEBUG > 1) - clib_warning ("Received ${c_name} event message"); - - jmethodID constructor = (*env)->GetMethodID(env, ${class_ref_name}Class, "<init>", "()V"); - - // User does not have to provide callbacks for all VPP messages. - // We are ignoring messages that are not supported by user. - (*env)->ExceptionClear(env); // just in case exception occurred in different place and was not properly cleared - jmethodID callbackMethod = (*env)->GetMethodID(env, plugin_main->callbackClass, "on${dto_name}", "(Lio/fd/vpp/jvpp/${plugin_name}/dto/${dto_name};)V"); - exc = (*env)->ExceptionOccurred(env); - if (exc) { - clib_warning("Unable to extract on${dto_name} method reference from ${plugin_name} plugin's callbackClass. Ignoring message.\\n"); - (*env)->ExceptionDescribe(env); - (*env)->ExceptionClear(env); - return; - } - - jobject dto = (*env)->NewObject(env, ${class_ref_name}Class, constructor); -$dto_setters - - (*env)->CallVoidMethod(env, plugin_main->callbackObject, callbackMethod, dto); - // free DTO as per http://stackoverflow.com/questions/1340938/memory-leak-when-calling-java-code-from-c-using-jni - (*env)->DeleteLocalRef(env, dto); -}""") - - -def _generate_error_handler(msg): - err_handler = "" - for field in msg.fields: - if is_retval(field): - err_handler = _ERR_HANDLER_TEMPLATE.substitute(name=msg.name) - return err_handler - -# Code fragment for checking result of the operation before sending request reply. -# Error checking is optional (some messages, e.g. detail messages do not have retval field). -_ERR_HANDLER_TEMPLATE = Template(""" - // for negative result don't send callback message but send error callback - if (mp->retval<0) { - call_on_error("${name}", mp->context, mp->retval, plugin_main->callbackClass, plugin_main->callbackObject, callbackExceptionClass); - return; - } - if (mp->retval == VNET_API_ERROR_IN_PROGRESS) { - clib_warning("Result in progress"); - return; - }""") diff --git a/extras/japi/java/jvpp/gen/jvppgen/jni_type_handlers_gen.py b/extras/japi/java/jvpp/gen/jvppgen/jni_type_handlers_gen.py deleted file mode 100755 index 59aaf95065a..00000000000 --- a/extras/japi/java/jvpp/gen/jvppgen/jni_type_handlers_gen.py +++ /dev/null @@ -1,235 +0,0 @@ -#!/usr/bin/env python2 -# -# Copyright (c) 2018 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 - -from jni_common_gen import generate_j2c_swap, generate_j2c_field_swap, generate_j2c_identifiers, generate_c2j_swap -from jvpp_model import Class, Enum, Union - - -def generate_type_handlers(model, logger): - """ - Generates host-to-net and net-to-host functions for all custom types defined in the VPP API - :param model: meta-model of VPP API used for jVPP generation. - :param logger: jVPP logger - """ - type_handlers = [] - for t in model.types: - #TODO(VPP-1186): move the logic to JNI generators - if isinstance(t, Class): - _generate_class(model, t, type_handlers) - elif isinstance(t, Enum): - _generate_enum(model, t, type_handlers) - elif isinstance(t, Union): - _generate_union(model, t, type_handlers) - else: - logger.debug("Skipping custom JNI type handler generation for %s", t) - - return "\n".join(type_handlers) - - -def _generate_class(model, t, type_handlers): - ref_name = t.java_name_lower - if t.name in model._aliases: - is_alias = True - else: - is_alias = False - - type_handlers.append(_TYPE_HOST_TO_NET_TEMPLATE.substitute( - c_name=t.name, - json_filename=model.json_api_files, - json_definition=t.doc, - type_reference_name=ref_name, - class_FQN=t.jni_name, - jni_identifiers=generate_j2c_identifiers(t, class_ref_name="%sClass" % ref_name, object_ref_name="_host"), - type_swap=generate_j2c_swap(t, struct_ref_name="_net", is_alias=is_alias) - )) - type_handlers.append(_TYPE_NET_TO_HOST_TEMPLATE.substitute( - c_name=t.name, - json_filename=model.json_api_files, - json_definition=t.doc, - type_reference_name=ref_name, - class_FQN=t.jni_name, - type_swap=generate_c2j_swap(t, object_ref_name="_host", struct_ref_name="_net", is_alias=is_alias) - )) - -_TYPE_HOST_TO_NET_TEMPLATE = Template(""" -/** - * Host to network byte order conversion for ${c_name} type. - * Generated based on $json_filename: -$json_definition - */ -static inline void _host_to_net_${c_name}(JNIEnv * env, jobject _host, vl_api_${c_name}_t * _net) -{ - jclass ${type_reference_name}Class = (*env)->FindClass(env, "${class_FQN}"); -$jni_identifiers -$type_swap -}""") - -_TYPE_NET_TO_HOST_TEMPLATE = Template(""" -/** - * Network to host byte order conversion for ${c_name} type. - * Generated based on $json_filename: -$json_definition - */ -static inline void _net_to_host_${c_name}(JNIEnv * env, vl_api_${c_name}_t * _net, jobject _host) -{ - jclass ${type_reference_name}Class = (*env)->FindClass(env, "${class_FQN}"); -$type_swap -}""") - - -def _generate_enum(model, t, type_handlers): - value_type = t.value.type - type_handlers.append(_ENUM_NET_TO_HOST_TEMPLATE.substitute( - c_name=t.name, - json_filename=model.json_api_files, - json_definition=t.doc, - class_FQN=t.jni_name, - jni_signature=value_type.jni_signature, - jni_type=value_type.jni_type, - jni_accessor=value_type.jni_accessor, - swap=_generate_scalar_host_to_net_swap(t.value) - )) - - type_handlers.append(_ENUM_HOST_TO_NET_TEMPLATE.substitute( - c_name=t.name, - json_filename=model.json_api_files, - json_definition=t.doc, - class_FQN=t.jni_name, - jni_type=value_type.jni_type, - type_swap=_generate_scalar_net_to_host_swap(t.value) - )) - -_ENUM_NET_TO_HOST_TEMPLATE = Template(""" -/** - * Host to network byte order conversion for ${c_name} enum. - * Generated based on $json_filename: -$json_definition - */ -static inline void _host_to_net_${c_name}(JNIEnv * env, jobject _host, vl_api_${c_name}_t * _net) -{ - jclass enumClass = (*env)->FindClass(env, "${class_FQN}"); - jmethodID getValueMethod = (*env)->GetMethodID(env, enumClass, "ordinal", "()I"); - ${jni_type} value = (*env)->CallIntMethod(env, _host, getValueMethod); - ${swap}; -}""") - -_ENUM_HOST_TO_NET_TEMPLATE = Template(""" -/** - * Network to host byte order conversion for ${c_name} type. - * Generated based on $json_filename: -$json_definition - */ -static inline ${jni_type} _net_to_host_${c_name}(vl_api_${c_name}_t _net) -{ - return (${jni_type}) $type_swap -}""") - - -def _generate_scalar_host_to_net_swap(field): - field_type = field.type - if field_type.is_swap_needed: - return field_type.get_host_to_net_function(field.java_name, "*_net") - else: - return "*_net = %s" % field.java_name - - -def _generate_scalar_net_to_host_swap(field): - field_type = field.type - if field_type.is_swap_needed: - return "%s((%s) _net);" % (field_type.net_to_host_function, field_type.name) - else: - return "_net" - - -def _generate_union(model, t, type_handlers): - type_handlers.append(_generate_union_host_to_net(model, t)) - type_handlers.append(_generate_union_net_to_host(model, t)) - - -def _generate_union_host_to_net(model, t): - swap = [] - for i, field in enumerate(t.fields): - field_type = field.type - if t.name in model._aliases: - is_alias = True - else: - is_alias = False - swap.append(_UNION_FIELD_HOST_TO_NET_TEMPLATE.substitute( - field_index=i, - java_name=field.java_name, - jni_signature=field_type.jni_signature, - jni_type=field_type.jni_type, - jni_accessor=field_type.jni_accessor, - swap=generate_j2c_field_swap(field, struct_ref_name="_net", is_alias=is_alias) - )) - - return _UNION_HOST_TO_NET_TEMPLATE.substitute( - c_name=t.name, - json_filename=model.json_api_files, - json_definition=t.doc, - class_FQN=t.jni_name, - swap="".join(swap) - ) - -_UNION_FIELD_HOST_TO_NET_TEMPLATE = Template(""" - if (_activeMember == ${field_index}) { - jfieldID fieldId = (*env)->GetFieldID(env, _class, "${java_name}", "${jni_signature}"); - ${jni_type} ${java_name} = (*env)->Get${jni_accessor}Field(env, _host, fieldId); - ${swap} - }""") - -_UNION_HOST_TO_NET_TEMPLATE = Template(""" -/** - * Host to network byte order conversion for ${c_name} union. - * Generated based on $json_filename: -$json_definition - */ -static inline void _host_to_net_${c_name}(JNIEnv * env, jobject _host, vl_api_${c_name}_t * _net) -{ - jclass _class = (*env)->FindClass(env, "${class_FQN}"); - - jfieldID _activeMemberFieldId = (*env)->GetFieldID(env, _class, "_activeMember", "I"); - jint _activeMember = (*env)->GetIntField(env, _host, _activeMemberFieldId); -$swap -}""") - - -def _generate_union_net_to_host(model, t): - if t.name in model._aliases: - is_alias = True - else: - is_alias = False - return _UNION_NET_TO_HOST_TEMPLATE.substitute( - c_name=t.name, - json_filename=model.json_api_files, - json_definition=t.doc, - type_reference_name=t.java_name_lower, - class_FQN=t.jni_name, - swap=generate_c2j_swap(t, object_ref_name="_host", struct_ref_name="_net", is_alias=is_alias) - ) - -_UNION_NET_TO_HOST_TEMPLATE = Template(""" -/** - * Network to host byte order conversion for ${c_name} union. - * Generated based on $json_filename: -$json_definition - */ -static inline void _net_to_host_${c_name}(JNIEnv * env, vl_api_${c_name}_t * _net, jobject _host) -{ - jclass ${type_reference_name}Class = (*env)->FindClass(env, "${class_FQN}"); -$swap -}""") diff --git a/extras/japi/java/jvpp/gen/jvppgen/jvpp_callback_facade_gen.py b/extras/japi/java/jvpp/gen/jvppgen/jvpp_callback_facade_gen.py deleted file mode 100644 index ebc552bfda6..00000000000 --- a/extras/japi/java/jvpp/gen/jvppgen/jvpp_callback_facade_gen.py +++ /dev/null @@ -1,289 +0,0 @@ -#!/usr/bin/env python2 -# -# Copyright (c) 2016,2018 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 - -from jvpp_model import is_control_ping, is_dump, is_request, is_event, is_control_ping_reply - - -def generate_callback_facade(work_dir, model, logger): - """ Generates callback facade """ - logger.debug("Generating JVpp callback facade for %s" % model.json_api_files) - _generate_ifc(work_dir, model), - _generate_impl(work_dir, model) - _generate_callback(work_dir, model) - - -def _generate_ifc(work_dir, model): - with open("%s/CallbackJVpp%s.java" % (work_dir, model.plugin_java_name), "w") as f: - f.write(_IFC_TEMPLATE.substitute( - plugin_package=model.plugin_package, - json_filename=model.json_api_files, - plugin_name=model.plugin_java_name, - methods=_generate_ifc_methods(model) - )) - -_IFC_TEMPLATE = Template(""" -package $plugin_package.callfacade; - -/** - * <p>Callback Java API representation of $plugin_package plugin. - * <br>It was generated by jvpp_callback_facade_gen.py based on $json_filename. - */ -public interface CallbackJVpp${plugin_name} extends io.fd.vpp.jvpp.notification.EventRegistryProvider, java.lang.AutoCloseable { - - // TODO add send - -$methods -} -""") - - -def _generate_ifc_methods(model): - plugin_package = model.plugin_package - methods = [] - for msg in model.messages: - if is_control_ping(msg): - # Skip control ping managed by jvpp registry. - continue - if not (is_dump(msg) or is_request(msg)): - # Skip replies and messages that do not not have replies (e.g events/counters). - continue - template = _IFC_NO_ARG_METHOD_TEMPLATE - if msg.has_fields: - template = _IFC_METHOD_TEMPLATE - methods.append(template.substitute( - name=msg.java_name_lower, - plugin_package=plugin_package, - request=msg.java_name_upper, - reply=msg.reply_java - )) - return "\n".join(methods) - -_IFC_NO_ARG_METHOD_TEMPLATE = Template( - """ void $name($plugin_package.callback.${reply}Callback callback) throws io.fd.vpp.jvpp.VppInvocationException;""") - -_IFC_METHOD_TEMPLATE = Template( - """ void $name($plugin_package.dto.$request request, $plugin_package.callback.${reply}Callback callback) throws io.fd.vpp.jvpp.VppInvocationException;""") - - -def _generate_impl(work_dir, model): - with open("%s/CallbackJVpp%sFacade.java" % (work_dir, model.plugin_java_name), "w") as f: - f.write(_IMPL_TEMPLATE.substitute( - plugin_package=model.plugin_package, - json_filename=model.json_api_files, - plugin_name=model.plugin_java_name, - methods=_generate_impl_methods(model) - )) - -_IMPL_TEMPLATE = Template(""" -package $plugin_package.callfacade; - -/** - * <p>Default implementation of Callback${plugin_name}JVpp interface. - * <br>It was generated by jvpp_callback_facade_gen.py based on $json_filename. - */ -public final class CallbackJVpp${plugin_name}Facade implements CallbackJVpp${plugin_name} { - - private final $plugin_package.JVpp${plugin_name} jvpp; - private final java.util.Map<Integer, io.fd.vpp.jvpp.callback.JVppCallback> callbacks; - private final $plugin_package.notification.${plugin_name}EventRegistryImpl eventRegistry = new $plugin_package.notification.${plugin_name}EventRegistryImpl(); - /** - * <p>Create CallbackJVpp${plugin_name}Facade object for provided JVpp instance. - * Constructor internally creates CallbackJVppFacadeCallback class for processing callbacks - * and then connects to provided JVpp instance - * - * @param jvpp provided io.fd.vpp.jvpp.JVpp instance - * - * @throws java.io.IOException in case instance cannot connect to JVPP - */ - public CallbackJVpp${plugin_name}Facade(final io.fd.vpp.jvpp.JVppRegistry registry, final $plugin_package.JVpp${plugin_name} jvpp) throws java.io.IOException { - this.jvpp = java.util.Objects.requireNonNull(jvpp,"jvpp is null"); - this.callbacks = new java.util.HashMap<>(); - java.util.Objects.requireNonNull(registry, "JVppRegistry should not be null"); - registry.register(jvpp, new CallbackJVpp${plugin_name}FacadeCallback(this.callbacks, eventRegistry)); - } - - @Override - public $plugin_package.notification.${plugin_name}EventRegistry getEventRegistry() { - return eventRegistry; - } - - @Override - public void close() throws Exception { - jvpp.close(); - } - - // TODO add send() - -$methods -} -""") - - -def _generate_impl_methods(model): - plugin_package = model.plugin_package - methods = [] - for msg in model.messages: - if is_control_ping(msg): - # Skip control ping managed by jvpp registry. - continue - if not (is_dump(msg) or is_request(msg)): - # Skip replies and messages that do not not have replies (e.g events/counters). - continue - template = _IMPL_NO_ARG_METHOD_TEMPLATE - if msg.has_fields: - template = _IMPL_METHOD_TEMPLATE - methods.append(template.substitute( - name=msg.java_name_lower, - plugin_package=plugin_package, - request=msg.java_name_upper, - reply=msg.reply_java - )) - return "\n".join(methods) - -_IMPL_NO_ARG_METHOD_TEMPLATE = Template( - """ public final void $name($plugin_package.callback.${reply}Callback callback) throws io.fd.vpp.jvpp.VppInvocationException { - synchronized (callbacks) { - callbacks.put(jvpp.$name(), callback); - } - } -""") - -_IMPL_METHOD_TEMPLATE = Template(""" public final void $name($plugin_package.dto.$request request, $plugin_package.callback.${reply}Callback callback) throws io.fd.vpp.jvpp.VppInvocationException { - synchronized (callbacks) { - callbacks.put(jvpp.$name(request), callback); - } - } -""") - - -def _generate_callback(work_dir, model): - with open("%s/CallbackJVpp%sFacadeCallback.java" % (work_dir, model.plugin_java_name), "w") as f: - f.write(_CALLBACK_TEMPLATE.substitute( - plugin_package=model.plugin_package, - json_filename=model.json_api_files, - plugin_name=model.plugin_java_name, - methods=_generate_callback_methods(model) - )) - -_CALLBACK_TEMPLATE = Template(""" -package $plugin_package.callfacade; - -/** - * <p>Implementation of JVppGlobalCallback interface for Java Callback API. - * <br>It was generated by jvpp_callback_facade_gen.py based on $json_filename. - */ -public final class CallbackJVpp${plugin_name}FacadeCallback implements $plugin_package.callback.JVpp${plugin_name}GlobalCallback { - - private final java.util.Map<Integer, io.fd.vpp.jvpp.callback.JVppCallback> requests; - private final $plugin_package.notification.Global${plugin_name}EventCallback eventCallback; - private static final java.util.logging.Logger LOG = java.util.logging.Logger.getLogger(CallbackJVpp${plugin_name}FacadeCallback.class.getName()); - - public CallbackJVpp${plugin_name}FacadeCallback(final java.util.Map<Integer, io.fd.vpp.jvpp.callback.JVppCallback> requestMap, - final $plugin_package.notification.Global${plugin_name}EventCallback eventCallback) { - this.requests = requestMap; - this.eventCallback = eventCallback; - } - - @Override - public void onError(io.fd.vpp.jvpp.VppCallbackException reply) { - - io.fd.vpp.jvpp.callback.JVppCallback failedCall; - synchronized(requests) { - failedCall = requests.remove(reply.getCtxId()); - } - - if(failedCall != null) { - try { - failedCall.onError(reply); - } catch(RuntimeException ex) { - ex.addSuppressed(reply); - LOG.log(java.util.logging.Level.WARNING, java.lang.String.format("Callback: %s failed while handling exception: %s", failedCall, reply), ex); - } - } - } - - @Override - @SuppressWarnings("unchecked") - public void onControlPingReply(final io.fd.vpp.jvpp.dto.ControlPingReply reply) { - - io.fd.vpp.jvpp.callback.ControlPingCallback callback; - final int replyId = reply.context; - synchronized(requests) { - callback = (io.fd.vpp.jvpp.callback.ControlPingCallback) requests.remove(replyId); - } - - if(callback != null) { - callback.onControlPingReply(reply); - } - } - -$methods -} -""") - - -def _generate_callback_methods(model): - plugin_package = model.plugin_package - methods = [] - for msg in model.messages: - if is_dump(msg) or is_request(msg): - continue - if is_control_ping_reply(msg): - # Skip control ping managed by jvpp registry. - continue - - # Generate callbacks for all messages except for dumps and requests (handled by vpp, not client). - template = _CALLBACK_METHOD_TEMPLATE - if is_event(msg): - template = _CALLBACK_EVENT_METHOD_TEMPLATE - msg_name = msg.java_name_upper - methods.append(template.substitute( - message=msg_name, - callback="%sCallback" % msg_name, - plugin_package=plugin_package - )) - return "\n".join(methods) - -_CALLBACK_METHOD_TEMPLATE = Template(""" - @Override - @SuppressWarnings("unchecked") - public void on${message}(final $plugin_package.dto.${message} reply) { - - $plugin_package.callback.$callback callback; - final int replyId = reply.context; - if (LOG.isLoggable(java.util.logging.Level.FINE)) { - LOG.fine(java.lang.String.format("Received ${message} event message: %s", reply)); - } - synchronized(requests) { - callback = ($plugin_package.callback.$callback) requests.remove(replyId); - } - - if(callback != null) { - callback.on${message}(reply); - } - } -""") - -_CALLBACK_EVENT_METHOD_TEMPLATE = Template(""" - @Override - @SuppressWarnings("unchecked") - public void on${message}($plugin_package.dto.${message} notification) { - if (LOG.isLoggable(java.util.logging.Level.FINE)) { - LOG.fine(java.lang.String.format("Received ${message} event message: %s", notification)); - } - eventCallback.on${message}(notification); - } -""") diff --git a/extras/japi/java/jvpp/gen/jvppgen/jvpp_common_gen.py b/extras/japi/java/jvpp/gen/jvppgen/jvpp_common_gen.py deleted file mode 100755 index 499adbc3f56..00000000000 --- a/extras/japi/java/jvpp/gen/jvppgen/jvpp_common_gen.py +++ /dev/null @@ -1,114 +0,0 @@ -#!/usr/bin/env python2 -# -# Copyright (c) 2018 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 - -from jvpp_model import is_array - - -def generate_fields(fields, access_modifier="public"): - return "\n".join(_FIELD_TEMPLATE - .substitute(access_modifier=access_modifier, type=f.type.java_name_fqn, name=f.java_name) - for f in fields) - -_FIELD_TEMPLATE = Template(""" ${access_modifier} ${type} ${name};""") - - -def generate_hash_code(fields): - if len(fields) == 1 and is_array(fields[0]): - return _HASH_CODE_SINGLE_ARRAY_TEMPLATE.substitute(array_field=fields[0].java_name) - return _HASH_CODE_TEMPLATE.substitute(fields=", ".join(f.java_name for f in fields)) - -_HASH_CODE_TEMPLATE = Template(""" - @Override - @io.fd.vpp.jvpp.coverity.SuppressFBWarnings("UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD") - public int hashCode() { - return java.util.Objects.hash($fields); - }""") - -_HASH_CODE_SINGLE_ARRAY_TEMPLATE = Template(""" - @Override - @io.fd.vpp.jvpp.coverity.SuppressFBWarnings("UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD") - public int hashCode() { - return java.util.Arrays.hashCode($array_field); - }""") - - -def generate_equals(class_name, fields): - comparisons = [] - for f in fields: - if is_array(f): - comparisons.append(_EQUALS_ARRAY_FIELD_TEMPLATE.substitute(field_name=f.java_name)) - else: - comparisons.append(_EQUALS_FIELD_TEMPLATE.substitute(field_name=f.java_name)) - - if comparisons: - comparisons.insert(0, _EQUALS_OTHER_TEMPLATE.substitute(cls_name=class_name)) - return _EQUALS_TEMPLATE.substitute(comparisons="\n".join(comparisons)) - -_EQUALS_TEMPLATE = Template(""" - @Override - public boolean equals(final Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } -$comparisons - - return true; - }""") - -_EQUALS_OTHER_TEMPLATE = Template(""" - final $cls_name other = ($cls_name) o; -""") - -_EQUALS_FIELD_TEMPLATE = Template(""" if (!java.util.Objects.equals(this.$field_name, other.$field_name)) { - return false; - }""") - -_EQUALS_ARRAY_FIELD_TEMPLATE = Template(""" if (!java.util.Arrays.equals(this.$field_name, other.$field_name)) { - return false; - }""") - - -def generate_to_string(class_name, fields): - to_string = [] - for f in fields: - if is_array(f): - to_string.append(_TO_STRING_ARRAY_FIELD_TEMPLATE.substitute(field_name=f.java_name)) - else: - to_string.append(_TO_STRING_FIELD_TEMPLATE.substitute(field_name=f.java_name)) - - to_string_fields = " \"}\";" - if to_string: - to_string_fields = " + \", \" +\n".join(to_string) + " + \"}\";" - - return _TO_STRING_TEMPLATE.substitute( - class_name=class_name, - to_string_fields=to_string_fields - ) - -_TO_STRING_TEMPLATE = Template(""" - @Override - public java.lang.String toString() { - return "$class_name{" + -$to_string_fields - }""") - -_TO_STRING_FIELD_TEMPLATE = Template(""" \"$field_name=\" + $field_name""") - -_TO_STRING_ARRAY_FIELD_TEMPLATE = Template( - """ \"$field_name=\" + java.util.Arrays.toString($field_name)""") diff --git a/extras/japi/java/jvpp/gen/jvppgen/jvpp_future_facade_gen.py b/extras/japi/java/jvpp/gen/jvppgen/jvpp_future_facade_gen.py deleted file mode 100644 index 3da367a4d5f..00000000000 --- a/extras/japi/java/jvpp/gen/jvppgen/jvpp_future_facade_gen.py +++ /dev/null @@ -1,338 +0,0 @@ -#!/usr/bin/env python2 -# -# Copyright (c) 2016,2018 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 - -from jvpp_model import is_control_ping, is_control_ping_reply, is_dump, is_request, is_details, is_reply, is_event - - -def generate_future_facade(work_dir, model, logger): - logger.debug("Generating JVpp future facade for %s" % model.json_api_files) - _generate_future_jvpp(work_dir, model), - _generate_future_jvpp_facade(work_dir, model) - _generate_future_jvpp_callback(work_dir, model) - - -def _generate_future_jvpp(work_dir, model): - with open("%s/FutureJVpp%s.java" % (work_dir, model.plugin_java_name), "w") as f: - f.write(_FUTURE_JVPP_TEMPLATE.substitute( - plugin_package=model.plugin_package, - json_filename=model.json_api_files, - plugin_name=model.plugin_java_name, - methods=_generate_future_jvpp_methods(model) - )) - -_FUTURE_JVPP_TEMPLATE = Template(''' -package $plugin_package.future; - -/** - * <p>Async facade extension adding specific methods for each request invocation - * <br>It was generated by jvpp_future_facade_gen.py based on $json_filename. - */ -public interface FutureJVpp${plugin_name} extends io.fd.vpp.jvpp.future.FutureJVppInvoker { -$methods - - @Override - public $plugin_package.notification.${plugin_name}EventRegistry getEventRegistry(); - -} -''') - - -def _generate_future_jvpp_methods(model): - methods = [] - for msg in model.messages: - if is_control_ping(msg) or is_control_ping_reply(msg): - # Skip control_ping managed by jvpp registry. - continue - reply_name = None - if is_request(msg): - reply_name = msg.reply_java - elif is_dump(msg): - # use reply dump wrappers - reply_name = "%sReplyDump" % msg.reply_java - else: - continue - - methods.append(_FUTURE_JVPP_METHOD_TEMPLATE.substitute( - plugin_package=model.plugin_package, - method_name=msg.java_name_lower, - reply_name=reply_name, - request_name=msg.java_name_upper - )) - return "".join(methods) - -_FUTURE_JVPP_METHOD_TEMPLATE = Template(''' - java.util.concurrent.CompletionStage<${plugin_package}.dto.${reply_name}> ${method_name}(${plugin_package}.dto.${request_name} request); -''') - - -def _generate_future_jvpp_facade(work_dir, model): - with open("%s/FutureJVpp%sFacade.java" % (work_dir, model.plugin_java_name), "w") as f: - f.write(_FUTURE_JVPP_FACADE_TEMPLATE.substitute( - plugin_package=model.plugin_package, - json_filename=model.json_api_files, - plugin_name=model.plugin_java_name, - methods=_generate_future_jvpp_facade_methods(model) - )) - -_FUTURE_JVPP_FACADE_TEMPLATE = Template(''' -package $plugin_package.future; - -/** - * <p>Implementation of FutureJVpp based on AbstractFutureJVppInvoker - * <br>It was generated by jvpp_future_facade_gen.py based on $json_filename. - */ -public class FutureJVpp${plugin_name}Facade extends io.fd.vpp.jvpp.future.AbstractFutureJVppInvoker implements FutureJVpp${plugin_name} { - - private final $plugin_package.notification.${plugin_name}EventRegistryImpl eventRegistry = new $plugin_package.notification.${plugin_name}EventRegistryImpl(); - - /** - * <p>Create FutureJVpp${plugin_name}Facade object for provided JVpp instance. - * Constructor internally creates FutureJVppFacadeCallback class for processing callbacks - * and then connects to provided JVpp instance - * - * @param jvpp provided io.fd.vpp.jvpp.JVpp instance - * - * @throws java.io.IOException in case instance cannot connect to JVPP - */ - public FutureJVpp${plugin_name}Facade(final io.fd.vpp.jvpp.JVppRegistry registry, final io.fd.vpp.jvpp.JVpp jvpp) throws java.io.IOException { - super(jvpp, registry, new java.util.HashMap<>()); - java.util.Objects.requireNonNull(registry, "JVppRegistry should not be null"); - registry.register(jvpp, new FutureJVpp${plugin_name}FacadeCallback(getRequests(), eventRegistry)); - } - - @Override - public $plugin_package.notification.${plugin_name}EventRegistry getEventRegistry() { - return eventRegistry; - } - -$methods -} -''') - - -def _generate_future_jvpp_facade_methods(model): - methods = [] - for msg in model.messages: - if is_control_ping(msg) or is_control_ping_reply(msg): - # Skip control_ping managed by jvpp registry. - continue - template = None - if is_request(msg): - template = _FUTURE_JVPP_FACADE_REQUEST_TEMPLATE - elif is_dump(msg): - template = _FUTURE_JVPP_FACADE_DUMP_TEMPLATE - else: - continue - - methods.append(template.substitute( - plugin_package=model.plugin_package, - method_name=msg.java_name_lower, - reply_name=msg.reply_java, - request_name=msg.java_name_upper - )) - return "".join(methods) - -_FUTURE_JVPP_FACADE_REQUEST_TEMPLATE = Template(''' - @Override - public java.util.concurrent.CompletionStage<${plugin_package}.dto.${reply_name}> ${method_name}(${plugin_package}.dto.${request_name} request) { - return send(request); - } -''') - -_FUTURE_JVPP_FACADE_DUMP_TEMPLATE = Template(''' - @Override - public java.util.concurrent.CompletionStage<${plugin_package}.dto.${reply_name}ReplyDump> ${method_name}(${plugin_package}.dto.${request_name} request) { - return send(request, new ${plugin_package}.dto.${reply_name}ReplyDump()); - } -''') - - -def _generate_future_jvpp_callback(work_dir, model): - with open("%s/FutureJVpp%sFacadeCallback.java" % (work_dir, model.plugin_java_name), "w") as f: - f.write(_FUTURE_JVPP_CALLBACK_TEMPLATE.substitute( - plugin_package=model.plugin_package, - json_filename=model.json_api_files, - plugin_name=model.plugin_java_name, - methods=_generate_future_jvpp_callback_methods(model) - )) - -_FUTURE_JVPP_CALLBACK_TEMPLATE = Template(""" -package $plugin_package.future; - -/** - * <p>Async facade callback setting values to future objects - * <br>It was generated by jvpp_future_facade_gen.py based on $json_filename. - */ -public final class FutureJVpp${plugin_name}FacadeCallback implements $plugin_package.callback.JVpp${plugin_name}GlobalCallback { - - private final java.util.Map<java.lang.Integer, java.util.concurrent.CompletableFuture<? extends io.fd.vpp.jvpp.dto.JVppReply<?>>> requests; - private final $plugin_package.notification.Global${plugin_name}EventCallback notificationCallback; - private static final java.util.logging.Logger LOG = java.util.logging.Logger.getLogger(FutureJVpp${plugin_name}FacadeCallback.class.getName()); - - public FutureJVpp${plugin_name}FacadeCallback( - final java.util.Map<java.lang.Integer, java.util.concurrent.CompletableFuture<? extends io.fd.vpp.jvpp.dto.JVppReply<?>>> requestMap, - final $plugin_package.notification.Global${plugin_name}EventCallback notificationCallback) { - this.requests = requestMap; - this.notificationCallback = notificationCallback; - } - - @Override - @SuppressWarnings("unchecked") - public void onError(io.fd.vpp.jvpp.VppCallbackException reply) { - final java.util.concurrent.CompletableFuture<io.fd.vpp.jvpp.dto.JVppReply<?>> completableFuture; - - synchronized(requests) { - completableFuture = (java.util.concurrent.CompletableFuture<io.fd.vpp.jvpp.dto.JVppReply<?>>) requests.get(reply.getCtxId()); - } - - if(completableFuture != null) { - completableFuture.completeExceptionally(reply); - - synchronized(requests) { - requests.remove(reply.getCtxId()); - } - } - } - - @Override - @SuppressWarnings("unchecked") - public void onControlPingReply(final io.fd.vpp.jvpp.dto.ControlPingReply reply) { - java.util.concurrent.CompletableFuture<io.fd.vpp.jvpp.dto.JVppReply<?>> completableFuture; - - final int replyId = reply.context; - synchronized(requests) { - completableFuture = (java.util.concurrent.CompletableFuture<io.fd.vpp.jvpp.dto.JVppReply<?>>) requests.get(replyId); - - if(completableFuture != null) { - // Finish dump call - if (completableFuture instanceof io.fd.vpp.jvpp.future.AbstractFutureJVppInvoker.CompletableDumpFuture) { - completableFuture.complete(((io.fd.vpp.jvpp.future.AbstractFutureJVppInvoker.CompletableDumpFuture) completableFuture).getReplyDump()); - // Remove future mapped to dump call context id - requests.remove(((io.fd.vpp.jvpp.future.AbstractFutureJVppInvoker.CompletableDumpFuture) completableFuture).getContextId()); - } else { - // reply to regular control ping, complete the future - completableFuture.complete(reply); - } - requests.remove(replyId); - } else { - // future not yet created by writer, create new future, complete it and put to map under ping id - completableFuture = new java.util.concurrent.CompletableFuture<>(); - completableFuture.complete(reply); - requests.put(replyId, completableFuture); - } - } - } - -$methods -} -""") - - -def _generate_future_jvpp_callback_methods(model): - methods = [] - for msg in model.messages: - if is_control_ping(msg) or is_control_ping_reply(msg): - # Skip control_ping managed by jvpp registry. - continue - if is_dump(msg) or is_request(msg): - continue - - # Generate callbacks for all messages except for dumps and requests (handled by vpp, not client). - template = None - request_dto = None - if is_details(msg): - template = _FUTURE_JVPP_FACADE_DETAILS_CALLBACK_TEMPLATE - request_dto = msg.request_java - elif is_reply(msg): - template = _FUTURE_JVPP_FACADE_REPLY_CALLBACK_TEMPLATE - request_dto = msg.request_java - elif is_event(msg): - template = _FUTURE_JVPP_FACADE_EVENT_CALLBACK_TEMPLATE - else: - raise TypeError("Unknown message type %s", msg) - - methods.append(template.substitute( - plugin_package=model.plugin_package, - callback_dto=msg.java_name_upper, - request_dto=request_dto, - callback_dto_field=msg.java_name_lower, - )) - return "".join(methods) - - -_FUTURE_JVPP_FACADE_DETAILS_CALLBACK_TEMPLATE = Template(""" - @Override - @SuppressWarnings("unchecked") - public void on$callback_dto(final $plugin_package.dto.$callback_dto reply) { - io.fd.vpp.jvpp.future.AbstractFutureJVppInvoker.CompletableDumpFuture<$plugin_package.dto.${callback_dto}ReplyDump> completableFuture; - final int replyId = reply.context; - if (LOG.isLoggable(java.util.logging.Level.FINE)) { - LOG.fine(java.lang.String.format("Received $callback_dto event message: %s", reply)); - } - synchronized(requests) { - completableFuture = (io.fd.vpp.jvpp.future.AbstractFutureJVppInvoker.CompletableDumpFuture<$plugin_package.dto.${callback_dto}ReplyDump>) requests.get(replyId); - - if(completableFuture == null) { - // reply received before writer created future, - // create new future, and put into map to notify sender that reply is already received, - // following details replies will add information to this future - completableFuture = new io.fd.vpp.jvpp.future.AbstractFutureJVppInvoker.CompletableDumpFuture<>(replyId, - new $plugin_package.dto.${callback_dto}ReplyDump()); - requests.put(replyId, completableFuture); - } - completableFuture.getReplyDump().$callback_dto_field.add(reply); - } - } -""") - -_FUTURE_JVPP_FACADE_REPLY_CALLBACK_TEMPLATE = Template(""" - @Override - @SuppressWarnings("unchecked") - public void on$callback_dto(final $plugin_package.dto.$callback_dto reply) { - java.util.concurrent.CompletableFuture<io.fd.vpp.jvpp.dto.JVppReply<$plugin_package.dto.$request_dto>> completableFuture; - final int replyId = reply.context; - if (LOG.isLoggable(java.util.logging.Level.FINE)) { - LOG.fine(java.lang.String.format("Received $callback_dto event message: %s", reply)); - } - synchronized(requests) { - completableFuture = - (java.util.concurrent.CompletableFuture<io.fd.vpp.jvpp.dto.JVppReply<$plugin_package.dto.$request_dto>>) requests.get(replyId); - - if(completableFuture != null) { - // received reply on request, complete future created by sender and remove it from map - completableFuture.complete(reply); - requests.remove(replyId); - } else { - // reply received before writer created future, - // create new future, complete it and put into map to - // notify sender that reply is already received - completableFuture = new java.util.concurrent.CompletableFuture<>(); - completableFuture.complete(reply); - requests.put(replyId, completableFuture); - } - } - } -""") - -_FUTURE_JVPP_FACADE_EVENT_CALLBACK_TEMPLATE = Template(""" - @Override - public void on$callback_dto($plugin_package.dto.$callback_dto notification) { - if (LOG.isLoggable(java.util.logging.Level.FINE)) { - LOG.fine(java.lang.String.format("Received $callback_dto event message: %s", notification)); - } - notificationCallback.on$callback_dto(notification); - } -""") diff --git a/extras/japi/java/jvpp/gen/jvppgen/jvpp_ifc_gen.py b/extras/japi/java/jvpp/gen/jvppgen/jvpp_ifc_gen.py deleted file mode 100755 index e2b2922ed20..00000000000 --- a/extras/japi/java/jvpp/gen/jvppgen/jvpp_ifc_gen.py +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env python2 -# -# Copyright (c) 2018 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 - -from jvpp_model import is_request, is_dump, is_event - - -def generate_java_ifc(work_dir, model, logger): - logger.debug("Generating JVpp interface for %s" % model.json_api_files) - messages = filter(_jvpp_ifc_filter, model.messages) - plugin_package = model.plugin_package - methods = [] - for msg in messages: - if msg.has_fields: - methods.append(_JVPP_IFC_METHOD_TEMPLATE.substitute( - name=msg.java_name_lower, - plugin_package=plugin_package, - type=msg.java_name_upper)) - else: - methods.append(_JVPP_IFC_NO_ARG_METHOD_TEMPLATE.substitute(name=msg.java_name_lower)) - - plugin_name = model.plugin_java_name - jvpp_interface = _JVPP_IFC_TEMPLATE.substitute( - plugin_package=plugin_package, - json_filename=model.json_api_files, - plugin_name=plugin_name, - methods="\n".join(methods) - ) - with open("%s/JVpp%s.java" % (work_dir, plugin_name), "w") as f: - f.write(jvpp_interface) - - -def _jvpp_ifc_filter(msg): - return is_request(msg) or is_dump(msg) or is_event(msg) - - -_JVPP_IFC_METHOD_TEMPLATE = Template( - """ int $name($plugin_package.dto.$type request) throws io.fd.vpp.jvpp.VppInvocationException;""") - -_JVPP_IFC_NO_ARG_METHOD_TEMPLATE = Template(""" int $name() throws io.fd.vpp.jvpp.VppInvocationException;""") - -_JVPP_IFC_TEMPLATE = Template("""package $plugin_package; - -/** - * <p>Java representation of plugin's api file. - * <br>It was generated by jvpp_impl_gen.py based on $json_filename. - * <br>(python representation of api file generated by vppapigen) - */ -public interface JVpp${plugin_name} extends io.fd.vpp.jvpp.JVpp { - /** - * Generic dispatch method for sending requests to VPP - * - * @throws io.fd.vpp.jvpp.VppInvocationException if send request had failed - */ - int send(io.fd.vpp.jvpp.dto.JVppRequest request) throws io.fd.vpp.jvpp.VppInvocationException; -$methods -} -""") diff --git a/extras/japi/java/jvpp/gen/jvppgen/jvpp_impl_gen.py b/extras/japi/java/jvpp/gen/jvppgen/jvpp_impl_gen.py deleted file mode 100755 index 376952b620e..00000000000 --- a/extras/japi/java/jvpp/gen/jvppgen/jvpp_impl_gen.py +++ /dev/null @@ -1,173 +0,0 @@ -#!/usr/bin/env python2 -# -# Copyright (c) 2016,2018 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 - -from jvpp_model import is_request, is_dump, is_event - - -def generate_java_impl(work_dir, model, logger): - logger.debug("Generating JVpp implementation for %s" % model.json_api_files) - messages = filter(_jvpp_impl_filter, model.messages) - plugin_package = model.plugin_package - methods = [] - for msg in messages: - if msg.has_fields: - methods.append(_JVPP_IMPL_METHOD_TEMPLATE.substitute( - name=msg.java_name_lower, - plugin_package=plugin_package, - type=msg.java_name_upper)) - else: - methods.append(_JVPP_IMPL_NO_ARG_METHOD_TEMPLATE.substitute( - name=msg.java_name_lower, - type=msg.java_name_upper)) - - plugin_name = model.plugin_java_name - jvpp_impl = _JVPP_IMPL_TEMPLATE.substitute( - plugin_package=plugin_package, - json_filename=model.json_api_files, - plugin_name=model.plugin_java_name, - plugin_name_underscore=model.plugin_name, - methods="\n".join(methods)) - - with open("%s/JVpp%sImpl.java" % (work_dir, plugin_name), "w") as f: - f.write(jvpp_impl) - - -def _jvpp_impl_filter(msg): - return is_request(msg) or is_dump(msg) or is_event(msg) - - -_JVPP_IMPL_TEMPLATE = Template("""package $plugin_package; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardCopyOption; -import java.nio.file.attribute.PosixFilePermission; -import java.nio.file.attribute.PosixFilePermissions; -import java.util.Set; -import java.util.logging.Logger; -import java.util.logging.Level; -import io.fd.vpp.jvpp.callback.JVppCallback; -import io.fd.vpp.jvpp.VppConnection; -import io.fd.vpp.jvpp.JVppRegistry; - -/** - * <p>Default implementation of JVpp interface. - * <br>It was generated by jvpp_impl_gen.py based on $json_filename. - * <br>(python representation of api file generated by vppapigen) - */ -public final class JVpp${plugin_name}Impl implements $plugin_package.JVpp${plugin_name} { - - private final static Logger LOG = Logger.getLogger(JVpp${plugin_name}Impl.class.getName()); - private static final java.lang.String LIBNAME = "libjvpp_${plugin_name_underscore}.so"; - - // FIXME using NativeLibraryLoader makes load fail could not find (WantInterfaceEventsReply). - static { - try { - loadLibrary(); - } catch (Exception e) { - LOG.severe("Can't find jvpp jni library: " + LIBNAME); - throw new ExceptionInInitializerError(e); - } - } - - private static void loadStream(final InputStream is) throws IOException { - final Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rwxr-x---"); - final Path p = Files.createTempFile(LIBNAME, null, PosixFilePermissions.asFileAttribute(perms)); - try { - Files.copy(is, p, StandardCopyOption.REPLACE_EXISTING); - - try { - Runtime.getRuntime().load(p.toString()); - } catch (UnsatisfiedLinkError e) { - throw new IOException("Failed to load library " + p, e); - } - } finally { - try { - Files.deleteIfExists(p); - } catch (IOException e) { - } - } - } - - private static void loadLibrary() throws IOException { - try (final InputStream is = JVpp${plugin_name}Impl.class.getResourceAsStream('/' + LIBNAME)) { - if (is == null) { - throw new IOException("Failed to open library resource " + LIBNAME); - } - loadStream(is); - } - } - - private VppConnection connection; - private JVppRegistry registry; - - private static native void init0(final JVppCallback callback, final long queueAddress, final int clientIndex); - @Override - public void init(final JVppRegistry registry, final JVppCallback callback, final long queueAddress, final int clientIndex) { - this.registry = java.util.Objects.requireNonNull(registry, "registry should not be null"); - this.connection = java.util.Objects.requireNonNull(registry.getConnection(), "connection should not be null"); - connection.checkActive(); - init0(callback, queueAddress, clientIndex); - } - - private static native void close0(); - @Override - public void close() { - close0(); - } - - @Override - public int send(io.fd.vpp.jvpp.dto.JVppRequest request) throws io.fd.vpp.jvpp.VppInvocationException { - return request.send(this); - } - - @Override - public final int controlPing(final io.fd.vpp.jvpp.dto.ControlPing controlPing) throws io.fd.vpp.jvpp.VppInvocationException { - return registry.controlPing(JVpp${plugin_name}Impl.class); - } -$methods -} -""") - -_JVPP_IMPL_METHOD_TEMPLATE = Template(""" - private static native int ${name}0($plugin_package.dto.$type request); - public final int $name($plugin_package.dto.$type request) throws io.fd.vpp.jvpp.VppInvocationException { - java.util.Objects.requireNonNull(request, "Null request object"); - connection.checkActive(); - if (LOG.isLoggable(Level.FINE)) { - LOG.fine(java.lang.String.format("Sending $type event message: %s", request)); - } - int result=${name}0(request); - if (result<0){ - throw new io.fd.vpp.jvpp.VppInvocationException("${name}", result); - } - return result; - }""") - -_JVPP_IMPL_NO_ARG_METHOD_TEMPLATE = Template(""" - private static native int ${name}0() throws io.fd.vpp.jvpp.VppInvocationException; - public final int $name() throws io.fd.vpp.jvpp.VppInvocationException { - connection.checkActive(); - LOG.fine("Sending $type event message"); - int result=${name}0(); - if(result<0){ - throw new io.fd.vpp.jvpp.VppInvocationException("${name}", result); - } - return result; - }""") diff --git a/extras/japi/java/jvpp/gen/jvppgen/jvpp_model.py b/extras/japi/java/jvpp/gen/jvppgen/jvpp_model.py deleted file mode 100755 index 9a3204e3fc6..00000000000 --- a/extras/japi/java/jvpp/gen/jvppgen/jvpp_model.py +++ /dev/null @@ -1,624 +0,0 @@ -#!/usr/bin/env python2 -# -# Copyright (c) 2018 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 json -import pprint -from collections import OrderedDict - -import binascii - -BASE_PACKAGE = "io.fd.vpp.jvpp" - - -class ParseException(Exception): - pass - - -class Type(object): - def __init__(self, name, java_name, java_name_fqn, jni_signature, jni_type, jni_accessor, - host_to_net_function, net_to_host_function): - """ - Initializes Type class. - - :param name: name of type as defined in .api file, e.g. u8, u32[] or mac_entry - :param java_name: corresponding java name, e.g. byte, int[] or MacEntry - :param java_name_fqn: fully qualified java name, e.g. io.fd.vpp.jvpp.core.types.MacEntry - :param jni_signature: JNI Type signature, e.g. B, [I or Lio.fd.vpp.jvpp.core.types.MacEntry; - See https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/types.html#type_signatures - :param jni_type: JNI reference type, e.g. jbyte jintArray, jobject - See https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/types.html#reference_types - :param jni_accessor: Java type do by used in Get<type>Field, Set<type>Field and other functions. - See https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#accessing_fields_of_objects - :param host_to_net_function: name of function host to net byte order swap function - :param net_to_host_function: name of function net to host byte order swap function - """ - self.name = name - self.java_name = java_name - - # Java generation specific properties, TODO(VPP-1186): move to Java specific subclass - self.java_name_fqn = java_name_fqn - - # JNI generation specific properties, TODO(VPP-1186): move to JNI specific subclass - self.jni_signature = jni_signature - - # Native type, see: - # https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/types.html#primitive_types - # and - # https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/types.html#reference_types - self.jni_type = jni_type - - # Java type do by used in Get<type>Field, Set<type>Field and other functions, see: - # https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#accessing_fields_of_objects - self.jni_accessor = jni_accessor - - self.host_to_net_function = host_to_net_function - self.net_to_host_function = net_to_host_function - self.is_swap_needed = host_to_net_function and net_to_host_function - - -class SimpleType(Type): - def __init__(self, name, java_name, jni_signature, jni_type, jni_accessor, - host_to_net_function=None, net_to_host_function=None): - super(SimpleType, self).__init__( - name=name, - java_name=java_name, - java_name_fqn=java_name, - jni_signature=jni_signature, - jni_type=jni_type, - jni_accessor=jni_accessor, - host_to_net_function=host_to_net_function, - net_to_host_function=net_to_host_function - ) - self.vpp_name = name - - def get_host_to_net_function(self, host_ref_name, net_ref_name): - return "%s = %s(%s)" % (net_ref_name, self.host_to_net_function, host_ref_name) - - def __str__(self): - return "SimpleType{name:%s, java_name:%s}" % (self.name, self.java_name) - - -# TODO(VPP-1187): add array host to net functions to reduce number of members and simplify JNI generation -class Array(Type): - def __init__(self, base_type, name=None): - if name is None: - name = base_type.name + _ARRAY_SUFFIX - super(Array, self).__init__( - name=name, - java_name=base_type.java_name + _ARRAY_SUFFIX, - java_name_fqn=base_type.java_name_fqn + _ARRAY_SUFFIX, - jni_signature="[%s" % base_type.jni_signature, - jni_type="%sArray" % base_type.jni_type, - jni_accessor="Object", - host_to_net_function=base_type.host_to_net_function, - net_to_host_function=base_type.net_to_host_function - ) - self.base_type = base_type - - def get_host_to_net_function(self, host_ref_name, net_ref_name): - return self.base_type.get_host_to_net_function(host_ref_name, net_ref_name) - - def __str__(self): - return "Array{name:%s, java_name:%s}" % (self.name, self.java_name) - - -class Enum(Type): - def __init__(self, name, value, constants, definition, plugin_name): - _java_name = _underscore_to_camelcase_upper(name) - - super(Enum, self).__init__( - name=name, - java_name=_java_name, - java_name_fqn="io.fd.vpp.jvpp.%s.types.%s" % (plugin_name, _java_name), - jni_signature="Lio/fd/vpp/jvpp/%s/types/%s;" % (plugin_name, _java_name), - jni_type="jobject", - jni_accessor="Object", - host_to_net_function="_host_to_net_%s" % name, - net_to_host_function="_net_to_host_%s" % name - ) - - self.value = value - self.constants = constants - self.doc = _message_to_javadoc(definition) - self.java_name_lower = _underscore_to_camelcase_lower(name) - self.vpp_name = "%s%s%s" % (_VPP_TYPE_PREFIX, name, _VPP_TYPE_SUFFIX) - # Fully qualified class name used by FindClass function, see: - # https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#FindClass - self.jni_name = "io/fd/vpp/jvpp/%s/types/%s" % (plugin_name, _java_name) - - def get_host_to_net_function(self, host_ref_name, net_ref_name): - return "_host_to_net_%s(env, %s, &(%s))" % (self.name, host_ref_name, net_ref_name) - - -class Class(Type): - def __init__(self, name, crc, fields, definition, plugin_name): - _java_name = _underscore_to_camelcase_upper(name) - - super(Class, self).__init__( - name=name, - java_name=_java_name, - java_name_fqn="io.fd.vpp.jvpp.%s.types.%s" % (plugin_name, _java_name), - jni_signature="Lio/fd/vpp/jvpp/%s/types/%s;" % (plugin_name, _java_name), - jni_type="jobject", - jni_accessor="Object", - host_to_net_function="_host_to_net_%s" % name, - net_to_host_function="_net_to_host_%s" % name - ) - - self.crc = crc - self.fields = fields - self.doc = _message_to_javadoc(definition) - self.java_name_lower = _underscore_to_camelcase_lower(name) - self.vpp_name = "%s%s%s" % (_VPP_TYPE_PREFIX, name, _VPP_TYPE_SUFFIX) - # Fully qualified class name used by FindClass function, see: - # https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#FindClass - self.jni_name = "io/fd/vpp/jvpp/%s/types/%s" % (plugin_name, _java_name) - - def get_host_to_net_function(self, host_ref_name, net_ref_name): - return "_host_to_net_%s(env, %s, &(%s))" % (self.name, host_ref_name, net_ref_name) - - -class Union(Type): - def __init__(self, name, crc, fields, definition, plugin_name): - _java_name = _underscore_to_camelcase_upper(name) - - super(Union, self).__init__( - name=name, - java_name=_java_name, - java_name_fqn="io.fd.vpp.jvpp.%s.types.%s" % (plugin_name, _java_name), - jni_signature="Lio/fd/vpp/jvpp/%s/types/%s;" % (plugin_name, _java_name), - jni_type="jobject", - jni_accessor="Object", - host_to_net_function="_host_to_net_%s" % name, - net_to_host_function="_net_to_host_%s" % name - ) - - self.crc = crc - self.fields = fields - self.doc = _message_to_javadoc(definition) - self.java_name_lower = _underscore_to_camelcase_lower(name) - self.vpp_name = "%s%s%s" % (_VPP_TYPE_PREFIX, name, _VPP_TYPE_SUFFIX) - # Fully qualified class name used by FindClass function, see: - # https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#FindClass - self.jni_name = "io/fd/vpp/jvpp/%s/types/%s" % (plugin_name, _java_name) - - def get_host_to_net_function(self, host_ref_name, net_ref_name): - return "_host_to_net_%s(env, %s, &(%s))" % (self.name, host_ref_name, net_ref_name) - - -class Field(object): - def __init__(self, name, field_type, array_len=None, array_len_field=None): - self.name = name - self.java_name = _underscore_to_camelcase_lower(name) - self.java_name_upper = _underscore_to_camelcase_upper(name) - self.type = field_type - self.array_len = array_len - self.array_len_field = array_len_field - - def __str__(self): - return "Field{name:%s, java_name:%s, type:%s}" % (self.name, self.java_name, self.type) - - -class Message(object): - def __init__(self, name, crc, fields, definition): - self.name = name - self.java_name_upper = _underscore_to_camelcase_upper(name) - self.java_name_lower = _underscore_to_camelcase_lower(name) - self.crc = crc[2:] - self.fields = fields - self.has_fields = fields != [] - self.doc = _message_to_javadoc(definition) - - def __str__(self): - return "Message{name:%s, java_name:%s, crc:%s, fields:%s}" % ( - self.name, self.java_name_upper, self.crc, self.fields) - - -class Event(Message): - def __init__(self, name, crc, fields, definition): - super(Event, self).__init__(name, crc, fields, definition) - - -class Request(Message): - def __init__(self, name, reply, crc, fields, definition): - super(Request, self).__init__(name, crc, fields, definition) - self.reply = reply - self.reply_java = _underscore_to_camelcase_upper(reply) - - def __str__(self): - return "Request{name:%s, reply:%s, crc:%s, fields:%s}" % (self.name, self.reply, self.crc, self.fields) - - -class Reply(Message): - def __init__(self, name, request, crc, fields, definition): - super(Reply, self).__init__(name, crc, fields, definition) - self.request = request - self.request_java = _underscore_to_camelcase_upper(request) - - def __str__(self): - return "Reply{name:%s, request:%s, crc:%s, fields:%s}" % (self.name, self.request, self.crc, self.fields) - - -class Dump(Message): - def __init__(self, name, details, crc, fields, definition): - super(Dump, self).__init__(name, crc, fields, definition) - self.details = details - self.reply_java = _underscore_to_camelcase_upper(details) - - def __str__(self): - return "Dump{name:%s, details:%s, crc:%s, fields:%s}" % (self.name, self.details, self.crc, self.fields) - - -class Details(Message): - def __init__(self, name, dump, crc, fields, definition): - super(Details, self).__init__(name, crc, fields, definition) - self.dump = dump - self.request_java = _underscore_to_camelcase_upper(dump) - - def __str__(self): - return "Details{name:%s, dump:%s, crc:%s, fields:%s}" % (self.name, self.dump, self.crc, self.fields) - - -def is_retval(field): - return field.name == u'retval' - - -def is_array(field): - return field.array_len is not None - - -def is_request(msg): - return hasattr(msg, 'reply') - - -def is_reply(msg): - return hasattr(msg, 'request') - - -def is_dump(msg): - return hasattr(msg, 'details') - - -def is_details(msg): - return hasattr(msg, 'dump') - - -def is_event(msg): - return isinstance(msg, Event) - - -def is_control_ping(msg): - return msg.name == u'control_ping' - - -def is_control_ping_reply(msg): - return msg.name == u'control_ping_reply' - - -def crc(block): - s = str(block).encode() - return binascii.crc32(s) & 0xffffffff - - -class JVppModel(object): - def __init__(self, logger, json_api_files, plugin_name): - self.logger = logger - # TODO(VPP-1188): provide json_file_by_definition map to improve javadoc - self.json_api_files = json_api_files - self.plugin_package = BASE_PACKAGE + "." + plugin_name - self.plugin_name = plugin_name - self.plugin_java_name = _underscore_to_camelcase_upper(plugin_name) - self._load_json_files(json_api_files) - self._parse_services() - self._parse_messages() - self._validate_messages() - - def _load_json_files(self, json_api_files): - types = {} - self._messages = [] - self._services = {} - self._aliases = {} - for file_name in json_api_files: - with open(file_name) as f: - j = json.load(f) - types.update({d[0]: {'type': 'enum', 'data': d} for d in j['enums']}) - types.update({d[0]: {'type': 'type', 'data': d} for d in j['types']}) - types.update({d[0]: {'type': 'union', 'data': d} for d in j['unions']}) - self._messages.extend(j['messages']) - self._services.update(j['services']) - self._aliases.update(j['aliases']) - - self._parse_types(types) - - def _parse_aliases(self, types): - - # model aliases - for alias_name in self._aliases: - alias = self._aliases[alias_name] - alias_type = {"type": "type"} - java_name_lower = _underscore_to_camelcase_lower(alias_name) - vpp_type = alias["type"] - crc_value = '0x%08x' % crc(alias_name) - if "length" in alias: - length = alias["length"] - alias_type["data"] = [ - alias_name, - [ - vpp_type, - java_name_lower, - length - ], - { - "crc": crc_value - } - ] - else: - alias_type["data"] = [ - alias_name, - [ - vpp_type, - java_name_lower - ], - { - "crc": crc_value - } - ] - - types[alias_name] = alias_type - - def _parse_types(self, types): - self._parse_simple_types() - self._parse_aliases(types) - i = 0 - while True: - unresolved = {} - for name, value in types.items(): - if name in self._types_by_name: - continue - - type = value['type'] - data = value['data'][1:] - try: - if type == 'enum': - type = self._parse_enum(name, data) - elif type == 'union': - type = self._parse_union(name, data) - elif type == 'type': - type = self._parse_type(name, data) - else: - self.logger.warning("Unsupported type %s. Ignoring...", type) - continue - - self._types_by_name[name] = type - self._types_by_name[name + _ARRAY_SUFFIX] = Array(type) - except ParseException as e: - self.logger.debug("Failed to parse %s type in iteration %s: %s.", name, i, e) - unresolved[name] = value - if len(unresolved) == 0: - break - if i > 3: - raise ParseException('Unresolved type definitions {}' - .format(unresolved)) - types = unresolved - i += 1 - - self.types = self._types_by_name.values() - - def _parse_simple_types(self): - # Mapping according to: - # http://docs.oracle.com/javase/7/do+'[]'cs/technotes/guides/jni/spec/types.html - # and - # https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#Get_type_Field_routines - # - # Unsigned types are converted to signed java types that have the same size. - # It is the API user responsibility to interpret them correctly. - - self._types_by_name = OrderedDict({ - 'u8': SimpleType('u8', 'byte', 'B', 'jbyte', 'Byte'), - 'i8': SimpleType('i8', 'byte', 'B', 'jbyte', 'Byte'), - 'u16': SimpleType('u16', 'short', 'S', 'jshort', 'Short', - host_to_net_function='clib_host_to_net_u16', - net_to_host_function='clib_net_to_host_u16'), - 'i16': SimpleType('i16', 'short', 'S', 'jshort', 'Short', - host_to_net_function='clib_host_to_net_i16', - net_to_host_function='clib_net_to_host_i16'), - 'u32': SimpleType('u32', 'int', 'I', 'jint', 'Int', - host_to_net_function='clib_host_to_net_u32', - net_to_host_function='clib_net_to_host_u32'), - 'i32': SimpleType('i32', 'int', 'I', 'jint', 'Int', - host_to_net_function='clib_host_to_net_i32', - net_to_host_function='clib_net_to_host_i32'), - 'u64': SimpleType('u64', 'long', 'J', 'jlong', 'Long', - host_to_net_function='clib_host_to_net_u64', - net_to_host_function='clib_net_to_host_u64'), - 'i64': SimpleType('i64', 'long', 'J', 'jlong', 'Long', - host_to_net_function='clib_host_to_net_i64', - net_to_host_function='clib_net_to_host_i64'), - 'f64': SimpleType('f64', 'double', 'D', 'jdouble', 'Double'), - 'string': SimpleType('string', 'String', 'Ljava/lang/String;', 'jstring', 'Object', - host_to_net_function='_host_to_net_string', - net_to_host_function='_net_to_host_string') - }) - - for n, t in self._types_by_name.items(): - self._types_by_name[n + _ARRAY_SUFFIX] = Array(t) - - def _parse_enum(self, name, definition): - self.logger.debug("Parsing enum %s: %s", name, definition) - constants = [] - type_name = None - for item in definition: - if type(item) is dict and 'enumtype' in item: - type_name = item['enumtype'] - continue - constants.append({'name': item[0], 'value': item[1]}) - if not type_name: - raise ParseException("'enumtype' was not defined for %s" % definition) - return Enum(name, Field('value', self._types_by_name[type_name]), constants, definition, self.plugin_name) - - def _parse_union(self, name, definition): - self.logger.debug("Parsing union %s: %s", name, definition) - crc, fields = self._parse_fields(definition) - return Union(name, crc, fields, definition, self.plugin_name) - - def _parse_type(self, name, definition): - self.logger.debug("Parsing type %s: %s", name, definition) - crc, fields = self._parse_fields(definition) - return Class(name, crc, fields, definition, self.plugin_name) - - def _parse_services(self): - self._dumps_by_details = {} - self._requests_by_reply = {} - for name, service in self._services.iteritems(): - if _is_stream(service): - self._dumps_by_details[service['reply']] = name - else: - self._requests_by_reply[service['reply']] = name - - def _parse_messages(self): - # Preserve ordering from JSON file to make debugging easier. - self._messages_by_name = OrderedDict() - for msg in self._messages: - try: - name = msg[0] - definition = msg[1:] - self._messages_by_name[name] = self._parse_message(name, definition) - except ParseException as e: - self.logger.warning("Failed to parse message %s: %s. Skipping message.", name, e) - - def _parse_message(self, name, definition): - self.logger.debug("Parsing message %s: %s", name, definition) - crc, fields = self._parse_fields(definition) - if name in self._services: - service = self._services[name] - reply = service['reply'] - if _is_stream(service): - return Dump(name, reply, crc, filter(_is_request_field, fields), definition) - if reply: - return Request(name, reply, crc, filter(_is_request_field, fields), definition) - else: - return Event(name, crc, filter(_is_request_field, fields), definition) - elif name in self._requests_by_reply: - return Reply(name, self._requests_by_reply[name], crc, filter(_is_reply_field, fields), definition) - elif name in self._dumps_by_details: - return Details(name, self._dumps_by_details[name], crc, filter(_is_reply_field, fields), definition) - else: - # TODO: some messages like combined_counters are not visible in the services. - # Throw exception instead (requires fixing vppagigen). - return Event(name, crc, filter(_is_request_field, fields), definition) - - def _parse_fields(self, definition): - crc = None - fields = [] - for item in definition: - if type(item) == dict and 'crc' in item: - crc = item['crc'] - else: - fields.append(self._parse_field(item, fields)) - if not crc: - raise ParseException("CRC was not defined for %s" % definition) - return crc, fields - - def _parse_field(self, field, fields): - type_name = _extract_type_name(field[0]) - - if type_name in self._types_by_name: - if len(field) > 2: - # Array field - array_len_field = None - if len(field) == 4: - for f in fields: - if f.name == field[3]: - array_len_field = f - if not array_len_field: - raise ParseException("Could not find field %s declared as length of array %s", - field[3], field[1]) - return Field(field[1], self._types_by_name[type_name + _ARRAY_SUFFIX], field[2], array_len_field) - else: - return Field(field[1], self._types_by_name[type_name]) - else: - raise ParseException("Unknown field type %s" % field) - - def _validate_messages(self): - """ - In case if message A is known to be reply for message B, and message B was not correctly parsed, - remove message A from the set of all messages. - """ - to_be_removed = [] - messages = self._messages_by_name - for name, msg in messages.iteritems(): - if (is_request(msg) and msg.reply not in messages) \ - or (is_reply(msg) and msg.request not in messages) \ - or (is_dump(msg) and msg.details not in messages) \ - or (is_details(msg) and msg.dump not in messages): - to_be_removed.append(name) - - for name in to_be_removed: - del messages[name] - - self.messages = self._messages_by_name.values() - - -_ARRAY_SUFFIX = '[]' - - -def _underscore_to_camelcase_upper(name): - return name.title().replace("_", "") - - -def _underscore_to_camelcase_lower(name): - name = name.title().replace("_", "") - return name[0].lower() + name[1:] - - -def _message_to_javadoc(message_definition): - """ Converts JSON message definition to javadoc """ - formatted_message = pprint.pformat(message_definition, indent=4, width=120, depth=None) - return " * " + formatted_message.replace("\n", "\n * ") - - -def _is_stream(service): - """ - Checks if service represents stream, e.g.: - "ip_address_dump": { - "reply": "ip_address_details", - "stream": true - } - :param service: JSON definition of service - :return: value assigned to "stream" or None - """ - return "stream" in service - - -def _extract_type_name(name): - if name.startswith(_VPP_TYPE_PREFIX) and name.endswith(_VPP_TYPE_SUFFIX): - return name[len(_VPP_TYPE_PREFIX): - len(_VPP_TYPE_SUFFIX)] - return name - -_VPP_TYPE_PREFIX = "vl_api_" - -_VPP_TYPE_SUFFIX = "_t" - - -def _is_request_field(field): - # Skip fields that are hidden to the jvpp user (handled by JNI layer) - return field.name not in {'_vl_msg_id', 'client_index', 'context'} - - -def _is_reply_field(field): - # Skip fields that are hidden to the jvpp user: - # _vl_msg_id is handled at JNI layer, - # Unlike in the request case, context is visible to allow matching replies with requests at Java layer. - return field.name not in {'_vl_msg_id'} diff --git a/extras/japi/java/jvpp/gen/jvppgen/notification_gen.py b/extras/japi/java/jvpp/gen/jvppgen/notification_gen.py deleted file mode 100644 index fa86fe4bbf2..00000000000 --- a/extras/japi/java/jvpp/gen/jvppgen/notification_gen.py +++ /dev/null @@ -1,226 +0,0 @@ -#!/usr/bin/env python2 -# -# Copyright (c) 2016,2018 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 - -from jvpp_model import is_control_ping, is_control_ping_reply, is_dump, is_request - - -def generate_notifications(work_dir, model, logger): - """ Generates notification registry interface and implementation """ - logger.debug("Generating Notification interfaces and implementation for %s" % model.json_api_files) - messages = filter(_notification_filter, model.messages) - _generate_global_event_callback(work_dir, model, messages) - _generate_event_registry(work_dir, model, messages) - _generate_event_registry_impl(work_dir, model, messages) - _generate_event_registry_provider(work_dir, model) - - -def _notification_filter(msg): - # Generate callbacks for all messages except for dumps and requests (handled by vpp, not client). - # Also skip control ping managed by jvpp registry. - return (not is_control_ping(msg)) and \ - (not is_control_ping_reply(msg)) and \ - (not is_dump(msg)) and \ - (not is_request(msg)) - - -def _generate_event_registry(work_dir, model, messages): - plugin_name = model.plugin_java_name - plugin_package = model.plugin_package - - register_callback_methods = [] - for msg in messages: - name = _callback_name(msg) - fqn_name = _fqn_callback_name(plugin_package, name) - # TODO create NotificationListenerRegistration and return that instead of AutoCloseable to better indicate - # that the registration should be closed - register_callback_methods.append(" java.lang.AutoCloseable register%s(%s callback);" % (name, fqn_name)) - - with open("%s/%sEventRegistry.java" % (work_dir, plugin_name), "w") as f: - f.write(_EVENT_REGISTRY_TEMPLATE.substitute( - plugin_package=plugin_package, - plugin_name=plugin_name, - json_filename=model.json_api_files, - register_callback_methods="\n".join(register_callback_methods) - )) - -_EVENT_REGISTRY_TEMPLATE = Template(""" -package $plugin_package.notification; - -/** - * <p>Registry for notification callbacks defined in ${plugin_name}. - * <br>It was generated by notification_gen.py based on $json_filename. - */ -public interface ${plugin_name}EventRegistry extends io.fd.vpp.jvpp.notification.EventRegistry { - -$register_callback_methods - - @Override - void close(); -} -""") - - -def _generate_event_registry_impl(work_dir, model, messages): - plugin_name = model.plugin_java_name - plugin_package = model.plugin_package - - register_callback_methods = [] - handler_methods = [] - for msg in messages: - notification = msg.java_name_upper - callback = "%sCallback" % notification - register_callback_methods.append(_REGISTER_CALLBACK_IMPL_TEMPLATE.substitute( - plugin_package=plugin_package, - notification=notification, - callback=callback - )) - handler_methods.append(_HANDLER_IMPL_TEMPLATE.substitute( - plugin_package=plugin_package, - notification=notification, - callback=callback - )) - - with open("%s/%sEventRegistryImpl.java" % (work_dir, plugin_name), "w") as f: - f.write(_EVENT_REGISTRY_IMPL_TEMPLATE.substitute( - plugin_package=plugin_package, - plugin_name=plugin_name, - json_filename=model.json_api_files, - register_callback_methods="".join(register_callback_methods), - handler_methods="".join(handler_methods) - )) - -_REGISTER_CALLBACK_IMPL_TEMPLATE = Template(""" - public java.lang.AutoCloseable register$callback(final $plugin_package.callback.$callback callback){ - if(null != registeredCallbacks.putIfAbsent($plugin_package.dto.$notification.class, callback)){ - throw new IllegalArgumentException("Callback for " + $plugin_package.dto.$notification.class + - "notification already registered"); - } - return () -> registeredCallbacks.remove($plugin_package.dto.$notification.class); - } -""") - -_HANDLER_IMPL_TEMPLATE = Template(""" - @Override - public void on$notification( - final $plugin_package.dto.$notification notification) { - if (LOG.isLoggable(java.util.logging.Level.FINE)) { - LOG.fine(java.lang.String.format("Received $notification event message: %s", notification)); - } - final io.fd.vpp.jvpp.callback.JVppCallback jVppCallback = registeredCallbacks.get($plugin_package.dto.$notification.class); - if (null != jVppCallback) { - (($plugin_package.callback.$callback) registeredCallbacks - .get($plugin_package.dto.$notification.class)) - .on$notification(notification); - } - } -""") - -_EVENT_REGISTRY_IMPL_TEMPLATE = Template(""" -package $plugin_package.notification; - -/** - * <p>Notification registry delegating notification processing to registered callbacks. - * <br>It was generated by notification_gen.py based on $json_filename. - */ -public final class ${plugin_name}EventRegistryImpl implements ${plugin_name}EventRegistry, Global${plugin_name}EventCallback { - - // TODO add a special NotificationCallback interface and only allow those to be registered - private final java.util.concurrent.ConcurrentMap<Class<?>, io.fd.vpp.jvpp.callback.JVppCallback> registeredCallbacks = - new java.util.concurrent.ConcurrentHashMap<>(); - private static java.util.logging.Logger LOG = java.util.logging.Logger.getLogger(${plugin_name}EventRegistryImpl.class.getName()); - - $register_callback_methods - $handler_methods - - @Override - public void close() { - registeredCallbacks.clear(); - } - - @Override - public void onError(io.fd.vpp.jvpp.VppCallbackException ex) { - java.util.logging.Logger LOG = java.util.logging.Logger.getLogger(${plugin_name}EventRegistryImpl.class.getName()); - LOG.log(java.util.logging.Level.WARNING, java.lang.String.format("Received onError exception: call=%s, context=%d, retval=%d%n", ex.getMethodName(), - ex.getCtxId(), ex.getErrorCode()), ex); - } -} -""") - - -def _generate_global_event_callback(work_dir, model, messages): - plugin_name = model.plugin_java_name - plugin_package = model.plugin_package - - callbacks = "" - callback_list = [] - for msg in messages: - fqn_name = _fqn_callback_name(plugin_package, _callback_name(msg)) - callback_list.append(fqn_name) - - if callback_list: - callbacks = " extends %s" % ", ".join(callback_list) - - with open("%s/Global%sEventCallback.java" % (work_dir, plugin_name), "w") as f: - f.write(_GLOBAL_EVENT_CALLBACK_TEMPLATE.substitute( - plugin_package=plugin_package, - plugin_name=plugin_name, - json_filename=model.json_api_files, - callbacks=callbacks - )) - -_GLOBAL_EVENT_CALLBACK_TEMPLATE = Template(""" -package $plugin_package.notification; - -/** - * <p>Aggregated callback interface for notifications only. - * <br>It was generated by notification_gen.py based on $json_filename. - */ -public interface Global${plugin_name}EventCallback$callbacks { - -} -""") - - -def _generate_event_registry_provider(work_dir, model): - plugin_name = model.plugin_java_name - with open("%s/%sEventRegistryProvider.java" % (work_dir, plugin_name), "w") as f: - f.write(_EVENT_REGISTRY_PROVIDER_TEMPLATE.substitute( - plugin_package=model.plugin_package, - plugin_name=plugin_name, - json_filename=model.json_api_files - )) - -_EVENT_REGISTRY_PROVIDER_TEMPLATE = Template(""" -package $plugin_package.notification; - - /** - * Provides ${plugin_name}EventRegistry. - * <br>The file was generated by notification_gen.py based on $json_filename. - */ -public interface ${plugin_name}EventRegistryProvider extends io.fd.vpp.jvpp.notification.EventRegistryProvider { - - @Override - public ${plugin_name}EventRegistry getEventRegistry(); -} -""") - - -def _callback_name(msg): - return "%sCallback" % msg.java_name_upper - - -def _fqn_callback_name(plugin_package, callback_name): - return "%s.callback.%s" % (plugin_package, callback_name) diff --git a/extras/japi/java/jvpp/gen/jvppgen/types_gen.py b/extras/japi/java/jvpp/gen/jvppgen/types_gen.py deleted file mode 100755 index 3767b530347..00000000000 --- a/extras/japi/java/jvpp/gen/jvppgen/types_gen.py +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env python2 -# -# Copyright (c) 2016,2018 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 - -from jvpp_common_gen import generate_hash_code, generate_equals, generate_to_string, generate_fields -from jvpp_model import Class - - -def generate_types(work_dir, model, logger): - logger.debug("Generating custom types for %s " % model.json_api_files) - - for t in model.types: - if not isinstance(t, Class): - continue - logger.debug("Generating DTO for type %s", t) - type_class_name = t.java_name - fields = t.fields - type_class = _TYPE_TEMPLATE.substitute( - plugin_package=model.plugin_package, - c_type_name=t.name, - json_filename=model.json_api_files, - json_definition=t.doc, - java_type_name=type_class_name, - fields=generate_fields(fields), - hash_code=generate_hash_code(fields), - equals=generate_equals(type_class_name, fields), - to_string=generate_to_string(type_class_name, fields) - ) - with open("%s/%s.java" % (work_dir, type_class_name), "w") as f: - f.write(type_class) - -_TYPE_TEMPLATE = Template(""" -package $plugin_package.types; - -/** - * <p>This class represents $c_type_name type definition. - * <br>It was generated by jvpp_types_gen.py based on $json_filename: - * <pre> -$json_definition - * </pre> - */ -public final class $java_type_name { -$fields -$hash_code -$equals -$to_string -} -""") diff --git a/extras/japi/java/jvpp/gen/jvppgen/unions_gen.py b/extras/japi/java/jvpp/gen/jvppgen/unions_gen.py deleted file mode 100755 index f67704f2426..00000000000 --- a/extras/japi/java/jvpp/gen/jvppgen/unions_gen.py +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env python2 -# -# Copyright (c) 2018 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 - -from jvpp_common_gen import generate_hash_code, generate_equals, generate_to_string, generate_fields -from jvpp_model import Union - - -def generate_unions(work_dir, model, logger): - logger.debug("Generating unions for %s " % model.json_api_files) - - for t in model.types: - if not isinstance(t, Union): - continue - logger.debug("Generating DTO for union %s", t) - java_union_name = t.java_name - fields = t.fields - type_class = _UNION_TEMPLATE.substitute( - plugin_package=model.plugin_package, - c_type_name=t.name, - json_filename=model.json_api_files, - json_definition=t.doc, - java_union_name=java_union_name, - fields=generate_fields(fields, access_modifier="private"), - constructors=_generate_constructors(java_union_name, fields), - getters=_generate_getters(fields), - hash_code=generate_hash_code(fields), - equals=generate_equals(java_union_name, fields), - to_string=generate_to_string(java_union_name, fields) - ) - with open("%s/%s.java" % (work_dir, java_union_name), "w") as f: - f.write(type_class) - -_UNION_TEMPLATE = Template(""" -package ${plugin_package}.types; - -/** - * <p>This class represents ${c_type_name} union definition. - * <br>It was generated by unions_gen.py based on ${json_filename}: - * <pre> -${json_definition} - * </pre> - */ -public class ${java_union_name} { - private final int _activeMember; -${fields} - private ${java_union_name}() { - // Constructor for JNI usage. All members can be read. - _activeMember = -1; - } -${constructors} -${getters} -${hash_code} -${equals} -${to_string} -} -""") - - -def _generate_constructors(union_name, fields): - return "".join( - _CONSTRUCTOR_TEMPLATE - .substitute(union_name=union_name, - field_type=f.type.java_name_fqn, - field_name=f.java_name, - field_index=i) for i, f in enumerate(fields)) - -_CONSTRUCTOR_TEMPLATE = Template(""" - public ${union_name}(${field_type} ${field_name}) { - this.${field_name} = java.util.Objects.requireNonNull(${field_name}, "${field_name} should not be null"); - _activeMember = $field_index; - }""") - - -def _generate_getters(fields): - return "".join(_GETTER_TEMPLATE.substitute( - type=f.type.java_name_fqn, - getter_name=f.java_name_upper, - field_name=f.java_name - ) for f in fields) - -_GETTER_TEMPLATE = Template(""" - public ${type} get${getter_name}() { - return ${field_name}; - }""") |