HONEYCOMB-67 Introduce exception handling into JVPP
[vpp.git] / vpp-api / java / jvpp / gen / jvpp_c_gen.py
index a92dd69..082fd5d 100644 (file)
@@ -31,6 +31,13 @@ find_class_invocation_template = Template("""
         return JNI_ERR;
     }""")
 
+find_class_template = Template("""
+    ${ref_name}Class = (jclass)(*env)->NewGlobalRef(env, (*env)->FindClass(env, "${class_name}"));
+    if ((*env)->ExceptionCheck(env)) {
+        (*env)->ExceptionDescribe(env);
+        return JNI_ERR;
+    }""")
+
 class_cache_template = Template("""
 $class_references
 static int cache_class_references(JNIEnv* env) {
@@ -57,6 +64,14 @@ def generate_class_cache(func_list):
                 ref_name=ref_name,
                 class_name=class_name))
 
+    # add exception class to class cache
+    ref_name = 'callbackException'
+    class_name = 'org/openvpp/jvpp/VppCallbackException'
+    class_references.append(class_reference_template.substitute(
+        ref_name=ref_name))
+    find_class_invocations.append(find_class_template.substitute(
+            ref_name=ref_name,
+            class_name=class_name))
     return class_cache_template.substitute(
             class_references="".join(class_references), find_class_invocations="".join(find_class_invocations))
 
@@ -147,6 +162,9 @@ JNIEXPORT jint JNICALL Java_org_openvpp_jvpp_JVppImpl_${java_name}0
     mp->context = clib_host_to_net_u32 (my_context_id);
     $struct_setters
     S;
+    if ((*env)->ExceptionCheck(env)) {
+        return JNI_ERR;
+    }
     return my_context_id;
 }""")
 
@@ -273,6 +291,19 @@ dto_field_setter_templates = {'u8': default_dto_field_setter_template,
                       'u64[]': u64_array_dto_field_setter_template
                       }
 
+# code fragment for checking result of the operation before sending request reply
+callback_err_handler_template = Template("""
+    // for negative result don't send callback message but send error callback
+    if (mp->retval<0) {
+        CallOnError("${handler_name}",mp->context,mp->retval);
+        return;
+    }
+    if (mp->retval == VNET_API_ERROR_IN_PROGRESS) {
+        clib_warning("Result in progress");
+        return;
+    }
+""")
+
 msg_handler_template = Template("""
 /**
  * Handler for ${handler_name} vpe.api message.
@@ -283,6 +314,7 @@ static void vl_api_${handler_name}_t_handler (vl_api_${handler_name}_t * mp)
 {
     vppjni_main_t * jm = &vppjni_main;
     JNIEnv *env = jm->jenv;
+    $err_handler
 
     jmethodID constructor = (*env)->GetMethodID(env, ${class_ref_name}Class, "<init>", "()V");
     jmethodID callbackMethod = (*env)->GetMethodID(env, jm->callbackClass, "on${dto_name}", "(Lorg/openvpp/jvpp/dto/${dto_name};)V");
@@ -304,6 +336,7 @@ def generate_msg_handlers(func_list, inputfile):
             continue
 
         dto_setters = ''
+        err_handler = ''
         # dto setters
         for t in zip(f['c_types'], f['types'], f['args'], f['lengths']):
             c_type = t[0]
@@ -311,6 +344,13 @@ def generate_msg_handlers(func_list, inputfile):
             c_name = t[2]
             field_length = t[3]
 
+            # for retval don't generate setters and generate retval check
+            if util.is_retval_field(c_name):
+                err_handler = callback_err_handler_template.substitute(
+                    handler_name=handler_name
+                )
+                continue
+
             java_field_name = util.underscore_to_camelcase(c_name)
             jni_signature = util.jni_2_signature_mapping[jni_type]
             jni_setter = util.jni_field_accessors[jni_type]
@@ -330,12 +370,13 @@ def generate_msg_handlers(func_list, inputfile):
                     field_length=field_length)
 
         handlers.append(msg_handler_template.substitute(
-                inputfile=inputfile,
-                api_data=util.api_message_to_javadoc(f),
-                handler_name=handler_name,
-                dto_name=dto_name,
-                class_ref_name=ref_name,
-                dto_setters=dto_setters))
+            inputfile=inputfile,
+            api_data=util.api_message_to_javadoc(f),
+            handler_name=handler_name,
+            dto_name=dto_name,
+            class_ref_name=ref_name,
+            dto_setters=dto_setters,
+            err_handler=err_handler))
 
     return "\n".join(handlers)
 
@@ -367,6 +408,8 @@ jvpp_c_template = Template("""/**
  * (python representation of vpe.api generated by vppapigen).
  */
 
+void CallOnError(const char* call, int context, int retval);
+
 // JAVA class reference cache
 $class_cache
 
@@ -399,4 +442,3 @@ def generate_jvpp(func_list, inputfile):
     jvpp_c_file.flush()
     jvpp_c_file.close()
 
-