Update japi to support type aliases
[vpp.git] / extras / japi / java / jvpp / gen / jvppgen / jni_msg_handlers_gen.py
1 #!/usr/bin/env python2
2 #
3 # Copyright (c) 2018 Cisco and/or its affiliates.
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16 from string import Template
17
18 from jni_common_gen import generate_c2j_swap
19 from jvpp_model import is_dump, is_request, is_control_ping, is_control_ping_reply, is_retval
20
21
22 def generate_jni_handlers(model):
23     """
24     Generates msg handlers for all messages except for dumps and requests (handled by vpp, not client).
25     :param model: meta-model of VPP API used for jVPP generation.
26     """
27     jni_impl = []
28     for msg in model.messages:
29         msg_name = msg.name
30         if is_control_ping(msg) or is_control_ping_reply(msg):
31             # Skip control ping managed by jvpp registry.
32             continue
33         if is_dump(msg) or is_request(msg):
34             continue
35
36         jni_impl.append(_MSG_HANDLER_TEMPLATE.substitute(
37             c_name=msg_name,
38             json_filename=model.json_api_files,
39             json_definition=msg.doc,
40             plugin_name=model.plugin_name,
41             err_handler=_generate_error_handler(msg),
42             class_ref_name=msg.java_name_lower,
43             dto_name=msg.java_name_upper,
44             dto_setters=generate_c2j_swap(msg, object_ref_name="dto", struct_ref_name="mp", is_alias=False)
45         ))
46     return "".join(jni_impl)
47
48 _MSG_HANDLER_TEMPLATE = Template("""
49 /**
50  * Handler for ${c_name} message.
51  * Generated based on $json_filename:
52 $json_definition
53  */
54 static void vl_api_${c_name}_t_handler (vl_api_${c_name}_t * mp)
55 {
56     ${plugin_name}_main_t *plugin_main = &${plugin_name}_main;
57     JNIEnv *env = jvpp_main.jenv;
58     jthrowable exc;
59 $err_handler
60
61     if (CLIB_DEBUG > 1)
62         clib_warning ("Received ${c_name} event message");
63
64     jmethodID constructor = (*env)->GetMethodID(env, ${class_ref_name}Class, "<init>", "()V");
65
66     // User does not have to provide callbacks for all VPP messages.
67     // We are ignoring messages that are not supported by user.
68     (*env)->ExceptionClear(env); // just in case exception occurred in different place and was not properly cleared
69     jmethodID callbackMethod = (*env)->GetMethodID(env, plugin_main->callbackClass, "on${dto_name}", "(Lio/fd/vpp/jvpp/${plugin_name}/dto/${dto_name};)V");
70     exc = (*env)->ExceptionOccurred(env);
71     if (exc) {
72         clib_warning("Unable to extract on${dto_name} method reference from ${plugin_name} plugin's callbackClass. Ignoring message.\\n");
73         (*env)->ExceptionDescribe(env);
74         (*env)->ExceptionClear(env);
75         return;
76     }
77
78     jobject dto = (*env)->NewObject(env, ${class_ref_name}Class, constructor);
79 $dto_setters
80
81     (*env)->CallVoidMethod(env, plugin_main->callbackObject, callbackMethod, dto);
82     // free DTO as per http://stackoverflow.com/questions/1340938/memory-leak-when-calling-java-code-from-c-using-jni
83     (*env)->DeleteLocalRef(env, dto);
84 }""")
85
86
87 def _generate_error_handler(msg):
88     err_handler = ""
89     for field in msg.fields:
90         if is_retval(field):
91             err_handler = _ERR_HANDLER_TEMPLATE.substitute(name=msg.name)
92     return err_handler
93
94 # Code fragment for checking result of the operation before sending request reply.
95 # Error checking is optional (some messages, e.g. detail messages do not have retval field).
96 _ERR_HANDLER_TEMPLATE = Template("""
97     // for negative result don't send callback message but send error callback
98     if (mp->retval<0) {
99         call_on_error("${name}", mp->context, mp->retval, plugin_main->callbackClass, plugin_main->callbackObject, callbackExceptionClass);
100         return;
101     }
102     if (mp->retval == VNET_API_ERROR_IN_PROGRESS) {
103         clib_warning("Result in progress");
104         return;
105     }""")