diff options
author | 2016-07-26 15:28:22 +0200 | |
---|---|---|
committer | 2016-08-16 21:26:19 +0000 | |
commit | 66ea26b1bc7bbc8d54a3498dbd3d0919c4712fa8 (patch) | |
tree | 16c46e75723099ad859128af6069055e68897300 /vpp-api/java/jvpp | |
parent | f4691cd7befd4cf31a63adffc204d71b1f1548e1 (diff) |
VPP-205: jvpp plugin support.
Splits jvpp into two jars
jvpp-registry.jar - base jvpp functionality
jvpp-core.jar - Java wrapper for vpe.api
Plugins can be generated the same way jvpp-core.jar is.
Example (nsh):
https://gerrit.fd.io/r/#/c/2118/
Change-Id: I2254f90b2c3e423563bb91bf70877979f1e90a7d
Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
Diffstat (limited to 'vpp-api/java/jvpp')
40 files changed, 468 insertions, 2707 deletions
diff --git a/vpp-api/java/jvpp/Readme.txt b/vpp-api/java/jvpp/Readme.txt deleted file mode 100644 index 9b759e09..00000000 --- a/vpp-api/java/jvpp/Readme.txt +++ /dev/null @@ -1,201 +0,0 @@ -= JVpp - -JVpp is JNI based Java API for VPP. - -== Features -It is: - -* Asynchronous -* Fully generated -* Lightweight - -== Architecture -JVpp and JNI - - - JVpp Java - - /----------\ /--------\ /------------\ /------\ - | VppConn* | | JVpp | | Callbacks | | DTOs | - \----+-----/ \----+---/ \------+-----/ \------/ - ^ ^ ^ - | implements | implements | implements - /----+---------\ /----+-------\ /------+-----------\ - | VppConnImpl* +<--------+ JVppImpl | | GlobalCallback | - \--------------/ uses \---+--------/ \-------+----------/ - | ^ - | uses | calls back - | | --------------------------------|-----------------------|--------------------- - | | - | +---------------+ - C JNI | | - v | /------------\ - /---+-------+--\ +---->+ jvpp.h* | - | +-----+ \------------/ - | jvpp.c* | - | +-----+ /------------\ - \--------------/ +---->+ jvpp_gen.h | - \------------/ - -* Components marked with an asterisk contain manually crafted Java code, which in addition -to generated classes form jvpp. Exception applies to Callbacks and DTOs, since there are -manually crafted marker interfaces in callback and dto package (dto/JVppRequest, dto/JVppReply, -dto/JVppDump, dto/JVppReplyDump, callback/JVppCallback) - -Note: jvpp.c calls back the GlobalCallback instance with every response. An instance of the -GlobalCallback is provided to jvpp.c by VppConnImpl while connecting to VPP. - -Part of the JVpp is also Future facade. It is asynchronous API returning Future objects -on top of low level JVpp. - - -Future facade - - /-------------\ /--------------------\ - | FutureJVpp* | +-->+ FutureJVppRegistry | - \-----+-------/ | \----------+---------/ - ^ | ^ - | implements | uses | uses - | | | - /--------+----------\ | /----------+---------\ - | FutureJVppFacade* +----+ | FutureJVppCallback | - \---------+---------/ \----------+---------/ - | | ----------------|-----------------------------|------------------------------- - | uses | implements -JVpp Java | | - | | - /---------\ | | - | JVpp +<--+ | - \----+----/ | - ^ | - | implements v - /----+-------\ /----------+-------\ - | JVppImpl | | GlobalCallback | - \------------/ \------------------/ - - - -Another useful utility of the JVpp is Callback facade. It is asynchronous API -capable of calling specific callback instance (provided when performing a call) -per call. - - -Callback facade - - /--------------\ /----------------------\ - | CallbackJVpp | +-->+ CallbackJVppRegistry | - \-----+--------/ | \----------+-----------/ - ^ | ^ - | implements | uses | uses - | | | - /--------+-----------\ | /----------+-----------\ - | CallbackJVppFacade +-----+ | CallbackJVppCallback | - \---------+----------/ \----------+-----------/ - | | ----------------|-----------------------------|------------------------------- - | uses | implements -JVpp Java | | - | | - /---------\ | | - | JVpp +<--+ | - \----+----/ | - ^ | - | implements v - /----+-------\ /----------+-------\ - | JVppImpl | | GlobalCallback | - \------------/ \------------------/ - - - -== Package structure - -* *org.openvpp.jvpp* - top level package for generated JVpp interface+ implementation and hand-crafted -VppConnection interface + implementation - -** *dto* - package for DTOs generated from VPP API structures + base/marker hand-crafted interfaces -** *callback* - package for low-level JVpp callbacks and a global callback interface implementing each of the low-level JVppcallbacks -** *future* - package for future based facade on top of JVpp and callbacks -** *callfacade* - package for callback based facade on top of JVpp and callbacks. Allowing -users to provide callback per request -** *test* - package for JVpp standalone tests. Can also serve as samples for JVpp. - -C code is structured into 3 files: - -* *jvpp.c* - includes jvpp.h and jvpp_gen.h + contains hand crafted code for: - -** VPP connection open/close -** Rx thread to java thread attach -** Callback instance store -* *jvpp.h* - contains hand-crafted macros and structures used by jvpp.c -* *jvpp_gen.h* - contains JNI compatible handlers for each VPP request and reply - -== Code generators -All of the required code except the base/marker interfaces is generated using -simple python2 code generators. The generators use __defs_vpp_papi.py__ input -file produced by __vppapigen__ from vpe.api file. - -=== JNI compatible C code -Produces __jvpp_gen.h__ file containing JNI compatible handlers for each VPP -request and reply. - -[NOTE] -==== -Source: jvpp_c_gen.py -==== - -=== Request/Reply DTOs -For all the structures in __defs_vpp_papi.py__ a POJO DTO is produced. Logically, -there are 4 types of DTOs: - -* Request - requests that can be sent to VPP and only a single response is expected -* DumpRequest - requests that can be sent to VPP and a stream of responses is expected -* Reply - reply to a simple request or a single response from dump triggered response stream -* ReplyDump - collection of replies from a single dump request -* Notifications/Events - Not implemented yet - -[NOTE] -==== -Source: dto_gen.py -==== - -=== JVpp -Produces __JVpp.java__ and __JVppImpl.java__. This is the layer right above JNI compatible C -code. - -[NOTE] -==== -Source: jvpp_impl_gen.py -==== - -=== Callbacks -Produces callback interface for each VPP reply + a global callback interface called -__JVppGlobalCallback.java__ aggregating all of the callback interfaces. The JNI -compatible C code expects only a single instance of this global callback and calls -it with every reply. - -[NOTE] -==== -Source: callback_gen.py -==== - -=== Future facade -Produces an asynchronous facade on top of JVpp and callbacks, which returns a Future that provides -matching reply once VPP invocation finishes. Sources produced: -__FutureJVpp.java, FutureJVppFacade.java and FutureJVppCallback.java__ - -[NOTE] -==== -Source: jvpp_future_facade_gen.py -==== - -=== Callback facade -Similar to future facade, only this facade takes callback objects as part of the invocation -and the callback is called with result once VPP invocation finishes. Sources produced: -__CallbackJVpp.java, CallbackJVppFacade.java and CallbackJVppCallback.java__ - -[NOTE] -==== -Source: jvpp_callback_facade_gen.py -==== diff --git a/vpp-api/java/jvpp/gen/jvpp_gen.py b/vpp-api/java/jvpp/gen/jvpp_gen.py index 6f531def..551ce7d2 100755 --- a/vpp-api/java/jvpp/gen/jvpp_gen.py +++ b/vpp-api/java/jvpp/gen/jvpp_gen.py @@ -41,7 +41,8 @@ from jvppgen.util import vpp_2_jni_type_mapping parser = argparse.ArgumentParser(description='VPP Java API generator') parser.add_argument('-i', action="store", dest="inputfile") -parser.add_argument('--base_package', action="store", dest="base_package", default='org.openvpp.jvpp') +parser.add_argument('--plugin_name', action="store", dest="plugin_name") +parser.add_argument('--control_ping_class', action="store", dest="control_ping_class", default="ControlPing") args = parser.parse_args() sys.path.append(".") @@ -52,7 +53,10 @@ print "importdir %s" % importdir inputfile = os.path.basename(args.inputfile) inputfile = inputfile.replace('.py', '') print "inputfile %s" % inputfile -base_package = args.base_package +plugin_name = args.plugin_name +print "plugin_name %s" % plugin_name +control_ping_class = args.control_ping_class +print "control_ping_class %s" % control_ping_class sys.path.append(importdir) cfg = importlib.import_module(inputfile, package=None) @@ -133,17 +137,20 @@ def get_definitions(): func_list, func_name = get_definitions() +base_package = 'org.openvpp.jvpp' +plugin_package = base_package + '.' + plugin_name dto_package = 'dto' callback_package = 'callback' notification_package = 'notification' future_package = 'future' # TODO find better package name callback_facade_package = 'callfacade' - -dto_gen.generate_dtos(func_list, base_package, dto_package, args.inputfile) -jvpp_impl_gen.generate_jvpp(func_list, base_package, dto_package, args.inputfile) -callback_gen.generate_callbacks(func_list, base_package, callback_package, dto_package, args.inputfile) -notification_gen.generate_notification_registry(func_list, base_package, notification_package, callback_package, dto_package, args.inputfile) -jvpp_c_gen.generate_jvpp(func_list, args.inputfile) -jvpp_future_facade_gen.generate_jvpp(func_list, base_package, dto_package, callback_package, notification_package, future_package, args.inputfile) -jvpp_callback_facade_gen.generate_jvpp(func_list, base_package, dto_package, callback_package, notification_package, callback_facade_package, args.inputfile) +control_ping_class_fqn = "%s.%s.%s" % (plugin_package, dto_package, control_ping_class) + +dto_gen.generate_dtos(func_list, base_package, plugin_package, plugin_name.title(), dto_package, args.inputfile) +jvpp_impl_gen.generate_jvpp(func_list, base_package, plugin_package, plugin_name, control_ping_class_fqn, dto_package, args.inputfile) +callback_gen.generate_callbacks(func_list, base_package, plugin_package, plugin_name.title(), callback_package, dto_package, args.inputfile) +notification_gen.generate_notification_registry(func_list, base_package, plugin_package, plugin_name.title(), notification_package, callback_package, dto_package, args.inputfile) +jvpp_c_gen.generate_jvpp(func_list, plugin_name, args.inputfile) +jvpp_future_facade_gen.generate_jvpp(func_list, base_package, plugin_package, plugin_name.title(), dto_package, callback_package, notification_package, future_package, args.inputfile) +jvpp_callback_facade_gen.generate_jvpp(func_list, base_package, plugin_package, plugin_name.title(), dto_package, callback_package, notification_package, callback_facade_package, args.inputfile) diff --git a/vpp-api/java/jvpp/gen/jvppgen/callback_gen.py b/vpp-api/java/jvpp/gen/jvppgen/callback_gen.py index eadf3b5c..68f70126 100644 --- a/vpp-api/java/jvpp/gen/jvppgen/callback_gen.py +++ b/vpp-api/java/jvpp/gen/jvppgen/callback_gen.py @@ -22,10 +22,10 @@ from util import remove_suffix callback_suffix = "Callback" callback_template = Template(""" -package $base_package.$callback_package; +package $plugin_package.$callback_package; /** - * <p>Represents callback for vpe.api message. + * <p>Represents callback for plugin's api file message. * <br>It was generated by callback_gen.py based on $inputfile preparsed data: * <pre> $docs @@ -39,19 +39,19 @@ public interface $cls_name extends $base_package.$callback_package.$callback_typ """) global_callback_template = Template(""" -package $base_package.$callback_package; +package $plugin_package.$callback_package; /** * <p>Global aggregated callback interface. * <br>It was generated by callback_gen.py based on $inputfile - * <br>(python representation of vpe.api generated by vppapigen). + * <br>(python representation of api file generated by vppapigen). */ -public interface JVppGlobalCallback extends $callbacks { +public interface JVpp${plugin_name}GlobalCallback extends $base_package.$callback_package.ControlPingCallback, $callbacks { } """) -def generate_callbacks(func_list, base_package, callback_package, dto_package, inputfile): +def generate_callbacks(func_list, base_package, plugin_package, plugin_name, callback_package, dto_package, inputfile): """ Generates callback interfaces """ print "Generating Callback interfaces" @@ -61,10 +61,10 @@ def generate_callbacks(func_list, base_package, callback_package, dto_package, i callbacks = [] for func in func_list: - if util.is_ignored(func['name']): - continue - camel_case_name_with_suffix = util.underscore_to_camelcase_upper(func['name']) + + if util.is_ignored(func['name']) or util.is_control_ping(camel_case_name_with_suffix): + continue if not util.is_reply(camel_case_name_with_suffix) and not util.is_notification(func['name']): continue @@ -76,11 +76,11 @@ def generate_callbacks(func_list, base_package, callback_package, dto_package, i camel_case_name = camel_case_name_with_suffix callback_type = "JVppNotificationCallback" - callbacks.append("{0}.{1}.{2}".format(base_package, callback_package, camel_case_name + callback_suffix)) + callbacks.append("{0}.{1}.{2}".format(plugin_package, callback_package, camel_case_name + callback_suffix)) callback_path = os.path.join(callback_package, camel_case_name + callback_suffix + ".java") callback_file = open(callback_path, 'w') - reply_type = "%s.%s.%s" % (base_package, dto_package, camel_case_name_with_suffix) + reply_type = "%s.%s.%s" % (plugin_package, dto_package, camel_case_name_with_suffix) method = "void on{0}({1} reply);".format(camel_case_name_with_suffix, reply_type) callback_file.write( callback_template.substitute(inputfile=inputfile, @@ -88,15 +88,18 @@ def generate_callbacks(func_list, base_package, callback_package, dto_package, i cls_name=camel_case_name + callback_suffix, callback_method=method, base_package=base_package, + plugin_package=plugin_package, callback_package=callback_package, callback_type=callback_type)) callback_file.flush() callback_file.close() - callback_file = open(os.path.join(callback_package, "JVppGlobalCallback.java"), 'w') + callback_file = open(os.path.join(callback_package, "JVpp%sGlobalCallback.java" % plugin_name), 'w') callback_file.write(global_callback_template.substitute(inputfile=inputfile, callbacks=", ".join(callbacks), base_package=base_package, + plugin_package=plugin_package, + plugin_name=plugin_name, callback_package=callback_package)) callback_file.flush() callback_file.close() diff --git a/vpp-api/java/jvpp/gen/jvppgen/dto_gen.py b/vpp-api/java/jvpp/gen/jvppgen/dto_gen.py index 426cd96b..785e47e9 100644 --- a/vpp-api/java/jvpp/gen/jvppgen/dto_gen.py +++ b/vpp-api/java/jvpp/gen/jvppgen/dto_gen.py @@ -19,7 +19,7 @@ from string import Template import util dto_template = Template(""" -package $base_package.$dto_package; +package $plugin_package.$dto_package; /** * <p>This class represents $description. @@ -39,11 +39,11 @@ field_template = Template(""" public $type $name;\n""") send_template = Template(""" @Override public int send(final $base_package.JVpp jvpp) throws org.openvpp.jvpp.VppInvocationException { - return jvpp.$method_name($args); + return (($plugin_package.JVpp${plugin_name})jvpp).$method_name($args); }\n""") -def generate_dtos(func_list, base_package, dto_package, inputfile): +def generate_dtos(func_list, base_package, plugin_package, plugin_name, dto_package, inputfile): """ Generates dto objects in a dedicated package """ print "Generating DTOs" @@ -55,7 +55,7 @@ def generate_dtos(func_list, base_package, dto_package, inputfile): camel_case_method_name = util.underscore_to_camelcase(func['name']) dto_path = os.path.join(dto_package, camel_case_dto_name + ".java") - if util.is_ignored(func['name']): + if util.is_ignored(func['name']) or util.is_control_ping(camel_case_dto_name): continue fields = "" @@ -72,44 +72,46 @@ def generate_dtos(func_list, base_package, dto_package, inputfile): # Generate request/reply or dump/dumpReply even if structure can be used as notification if not util.is_just_notification(func["name"]): if util.is_reply(camel_case_dto_name): - description = "vpe.api reply DTO" + description = "reply DTO" request_dto_name = get_request_name(camel_case_dto_name, func['name']) if util.is_details(camel_case_dto_name): # FIXME assumption that dump calls end with "Dump" suffix. Not enforced in vpe.api - base_type += "JVppReply<%s.%s.%s>" % (base_package, dto_package, request_dto_name + "Dump") - generate_dump_reply_dto(request_dto_name, base_package, dto_package, camel_case_dto_name, + base_type += "JVppReply<%s.%s.%s>" % (plugin_package, dto_package, request_dto_name + "Dump") + generate_dump_reply_dto(request_dto_name, base_package, plugin_package, dto_package, camel_case_dto_name, camel_case_method_name, func) else: - base_type += "JVppReply<%s.%s.%s>" % (base_package, dto_package, request_dto_name) + base_type += "JVppReply<%s.%s.%s>" % (plugin_package, dto_package, request_dto_name) else: args = "" if fields is "" else "this" methods = send_template.substitute(method_name=camel_case_method_name, base_package=base_package, + plugin_package=plugin_package, + plugin_name=plugin_name, args=args) if util.is_dump(camel_case_dto_name): base_type += "JVppDump" - description = "vpe.api dump request DTO" + description = "dump request DTO" else: base_type += "JVppRequest" - description = "vpe.api request DTO" + description = "request DTO" - write_dto_file(base_package, base_type, camel_case_dto_name, description, dto_package, dto_path, fields, func, + write_dto_file(base_package, plugin_package, base_type, camel_case_dto_name, description, dto_package, dto_path, fields, func, inputfile, methods) # for structures that are also used as notifications, generate dedicated notification DTO if util.is_notification(func["name"]): base_type = "JVppNotification" - description = "vpe.api notification DTO" + description = "notification DTO" camel_case_dto_name = util.add_notification_suffix(camel_case_dto_name) methods = "" dto_path = os.path.join(dto_package, camel_case_dto_name + ".java") - write_dto_file(base_package, base_type, camel_case_dto_name, description, dto_package, dto_path, fields, func, + write_dto_file(base_package, plugin_package, base_type, camel_case_dto_name, description, dto_package, dto_path, fields, func, inputfile, methods) flush_dump_reply_dtos(inputfile) -def write_dto_file(base_package, base_type, camel_case_dto_name, description, dto_package, dto_path, fields, func, +def write_dto_file(base_package, plugin_package, base_type, camel_case_dto_name, description, dto_package, dto_path, fields, func, inputfile, methods): dto_file = open(dto_path, 'w') dto_file.write(dto_template.substitute(inputfile=inputfile, @@ -119,6 +121,7 @@ def write_dto_file(base_package, base_type, camel_case_dto_name, description, dt fields=fields, methods=methods, base_package=base_package, + plugin_package=plugin_package, base_type=base_type, dto_package=dto_package)) dto_file.flush() @@ -141,11 +144,12 @@ def flush_dump_reply_dtos(inputfile): dump_reply_artificial_dto['cls_name'] + ".java") dto_file = open(dto_path, 'w') dto_file.write(dto_template.substitute(inputfile=inputfile, - description="vpe.api dump reply wrapper", + description="dump reply wrapper", docs=dump_reply_artificial_dto['docs'], cls_name=dump_reply_artificial_dto['cls_name'], fields=dump_reply_artificial_dto['fields'], methods=dump_reply_artificial_dto['methods'], + plugin_package=dump_reply_artificial_dto['plugin_package'], base_package=dump_reply_artificial_dto['base_package'], base_type=dump_reply_artificial_dto['base_type'], dto_package=dump_reply_artificial_dto['dto_package'])) @@ -153,11 +157,11 @@ def flush_dump_reply_dtos(inputfile): dto_file.close() -def generate_dump_reply_dto(request_dto_name, base_package, dto_package, camel_case_dto_name, camel_case_method_name, +def generate_dump_reply_dto(request_dto_name, base_package, plugin_package, dto_package, camel_case_dto_name, camel_case_method_name, func): base_type = "JVppReplyDump<%s.%s.%s, %s.%s.%s>" % ( - base_package, dto_package, util.remove_reply_suffix(camel_case_dto_name) + "Dump", - base_package, dto_package, camel_case_dto_name) + plugin_package, dto_package, util.remove_reply_suffix(camel_case_dto_name) + "Dump", + plugin_package, dto_package, camel_case_dto_name) fields = " public java.util.List<%s> %s = new java.util.ArrayList<>();" % (camel_case_dto_name, camel_case_method_name) cls_name = camel_case_dto_name + dump_dto_suffix @@ -171,6 +175,7 @@ def generate_dump_reply_dto(request_dto_name, base_package, dto_package, camel_c 'cls_name': cls_name, 'fields': fields, 'methods': "", + 'plugin_package': plugin_package, 'base_package': base_package, 'base_type': base_type, 'dto_package': dto_package, diff --git a/vpp-api/java/jvpp/gen/jvppgen/jvpp_c_gen.py b/vpp-api/java/jvpp/gen/jvppgen/jvpp_c_gen.py index 1796ac17..cd3a3566 100644 --- a/vpp-api/java/jvpp/gen/jvppgen/jvpp_c_gen.py +++ b/vpp-api/java/jvpp/gen/jvppgen/jvpp_c_gen.py @@ -17,7 +17,7 @@ import os, util from string import Template -def is_manually_generated(f_name): +def is_manually_generated(f_name, plugin_name): return f_name in {'control_ping_reply'} @@ -25,7 +25,7 @@ class_reference_template = Template("""jclass ${ref_name}Class; """) find_class_invocation_template = Template(""" - ${ref_name}Class = (jclass)(*env)->NewGlobalRef(env, (*env)->FindClass(env, "org/openvpp/jvpp/dto/${class_name}")); + ${ref_name}Class = (jclass)(*env)->NewGlobalRef(env, (*env)->FindClass(env, "org/openvpp/jvpp/${plugin_name}/dto/${class_name}")); if ((*env)->ExceptionCheck(env)) { (*env)->ExceptionDescribe(env); return JNI_ERR; @@ -38,53 +38,71 @@ find_class_template = Template(""" return JNI_ERR; }""") +delete_class_invocation_template = Template(""" + if (${ref_name}Class) { + (*env)->DeleteGlobalRef(env, ${ref_name}Class); + }""") + class_cache_template = Template(""" $class_references static int cache_class_references(JNIEnv* env) { $find_class_invocations return 0; +} + +static void delete_class_references(JNIEnv* env) { + $delete_class_invocations }""") -def generate_class_cache(func_list): +def generate_class_cache(func_list, plugin_name): class_references = [] find_class_invocations = [] + delete_class_invocations = [] for f in func_list: c_name = f['name'] class_name = util.underscore_to_camelcase_upper(c_name) ref_name = util.underscore_to_camelcase(c_name) - if util.is_ignored(c_name): + if util.is_ignored(c_name) or util.is_control_ping(class_name): continue if util.is_reply(class_name): class_references.append(class_reference_template.substitute( ref_name=ref_name)) find_class_invocations.append(find_class_invocation_template.substitute( + plugin_name=plugin_name, ref_name=ref_name, class_name=class_name)) + delete_class_invocations.append(delete_class_invocation_template.substitute(ref_name=ref_name)) elif util.is_notification(c_name): class_references.append(class_reference_template.substitute( ref_name=util.add_notification_suffix(ref_name))) find_class_invocations.append(find_class_invocation_template.substitute( + plugin_name=plugin_name, ref_name=util.add_notification_suffix(ref_name), class_name=util.add_notification_suffix(class_name))) + delete_class_invocations.append(delete_class_invocation_template.substitute( + ref_name=util.add_notification_suffix(ref_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)) + ref_name=ref_name)) find_class_invocations.append(find_class_template.substitute( ref_name=ref_name, class_name=class_name)) + delete_class_invocations.append(delete_class_invocation_template.substitute(ref_name=ref_name)) + return class_cache_template.substitute( - class_references="".join(class_references), find_class_invocations="".join(find_class_invocations)) + class_references="".join(class_references), find_class_invocations="".join(find_class_invocations), + delete_class_invocations="".join(delete_class_invocations)) # 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, "org/openvpp/jvpp/dto/${java_name_upper}");""") + jclass requestClass = (*env)->FindClass(env, "org/openvpp/jvpp/${plugin_name}/dto/${java_name_upper}");""") request_field_identifier_template = Template(""" jfieldID ${java_name}FieldId = (*env)->GetFieldID(env, requestClass, "${java_name}", "${jni_signature}"); @@ -178,37 +196,40 @@ struct_setter_templates = {'u8': u8_struct_setter_template, jni_impl_template = Template(""" /** - * JNI binding for sending ${c_name} vpe.api message. + * JNI binding for sending ${c_name} message. * Generated based on $inputfile preparsed data: $api_data */ -JNIEXPORT jint JNICALL Java_org_openvpp_jvpp_JVppImpl_${java_name}0 +JNIEXPORT jint JNICALL Java_org_openvpp_jvpp_${plugin_name}_JVpp${java_plugin_name}Impl_${java_name}0 (JNIEnv * env, jclass clazz$args) { - vppjni_main_t *jm = &vppjni_main; + ${plugin_name}_main_t *plugin_main = &${plugin_name}_main; vl_api_${c_name}_t * mp; - u32 my_context_id; - int rv; - rv = vppjni_sanity_check (jm); - if (rv) return rv; - my_context_id = vppjni_get_context_id (jm); + u32 my_context_id = vppjni_get_context_id (&jvpp_main); $request_class $field_identifiers - M(${c_name_uppercase}, ${c_name}); + + // create message: + mp = vl_msg_api_alloc(sizeof(*mp)); + memset (mp, 0, sizeof (*mp)); + mp->_vl_msg_id = ntohs (VL_API_${c_name_uppercase} + plugin_main->msg_id_base); + mp->client_index = plugin_main->my_client_index; mp->context = clib_host_to_net_u32 (my_context_id); + $struct_setters - S; + // send message: + vl_msg_api_send_shmem (plugin_main->vl_input_queue, (u8 *)&mp); if ((*env)->ExceptionCheck(env)) { return JNI_ERR; } return my_context_id; }""") -def generate_jni_impl(func_list, inputfile): +def generate_jni_impl(func_list, plugin_name, inputfile): jni_impl = [] for f in func_list: f_name = f['name'] camel_case_function_name = util.underscore_to_camelcase(f_name) - if is_manually_generated(f_name) or util.is_reply(camel_case_function_name) \ + if is_manually_generated(f_name, plugin_name) or util.is_reply(camel_case_function_name) \ or util.is_ignored(f_name) or util.is_just_notification(f_name): continue @@ -222,7 +243,9 @@ def generate_jni_impl(func_list, inputfile): arguments = ', jobject request' camel_case_function_name_upper = util.underscore_to_camelcase_upper(f_name) - request_class = request_class_template.substitute(java_name_upper=camel_case_function_name_upper) + request_class = request_class_template.substitute( + java_name_upper=camel_case_function_name_upper, + plugin_name=plugin_name) # field identifiers for t in zip(f['types'], f['args']): @@ -261,6 +284,8 @@ def generate_jni_impl(func_list, inputfile): java_name=camel_case_function_name, c_name_uppercase=f_name_uppercase, c_name=f_name, + plugin_name=plugin_name, + java_plugin_name=plugin_name.title(), request_class=request_class, field_identifiers=field_identifiers, struct_setters=struct_setters, @@ -357,7 +382,7 @@ dto_field_setter_templates = {'u8': default_dto_field_setter_template, 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); + call_on_error("${handler_name}", mp->context, mp->retval, plugin_main->callbackClass, plugin_main->callbackObject, callbackExceptionClass); return; } if (mp->retval == VNET_API_ERROR_IN_PROGRESS) { @@ -368,32 +393,34 @@ callback_err_handler_template = Template(""" msg_handler_template = Template(""" /** - * Handler for ${handler_name} vpe.api message. + * Handler for ${handler_name} message. * Generated based on $inputfile preparsed data: $api_data */ static void vl_api_${handler_name}_t_handler (vl_api_${handler_name}_t * mp) { - vppjni_main_t * jm = &vppjni_main; - JNIEnv *env = jm->jenv; + ${plugin_name}_main_t *plugin_main = &${plugin_name}_main; + JNIEnv *env = jvpp_main.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"); + jmethodID callbackMethod = (*env)->GetMethodID(env, plugin_main->callbackClass, "on${dto_name}", "(Lorg/openvpp/jvpp/${plugin_name}/dto/${dto_name};)V"); jobject dto = (*env)->NewObject(env, ${class_ref_name}Class, constructor); $dto_setters - (*env)->CallVoidMethod(env, jm->callback, callbackMethod, dto); + + (*env)->CallVoidMethod(env, plugin_main->callbackObject, callbackMethod, dto); }""") -def generate_msg_handlers(func_list, inputfile): +def generate_msg_handlers(func_list, plugin_name, inputfile): handlers = [] for f in func_list: handler_name = f['name'] dto_name = util.underscore_to_camelcase_upper(handler_name) ref_name = util.underscore_to_camelcase(handler_name) - if is_manually_generated(handler_name) or util.is_ignored(handler_name): + if is_manually_generated(handler_name, plugin_name) or util.is_ignored(handler_name): continue if not util.is_reply(dto_name) and not util.is_notification(handler_name): @@ -455,6 +482,7 @@ def generate_msg_handlers(func_list, inputfile): inputfile=inputfile, api_data=util.api_message_to_javadoc(f), handler_name=handler_name, + plugin_name=plugin_name, dto_name=dto_name, class_ref_name=ref_name, dto_setters=dto_setters, @@ -468,12 +496,13 @@ handler_registration_template = Template("""_(${upercase_name}, ${name}) \\ def generate_handler_registration(func_list): - handler_registration = ["#define foreach_vpe_api_msg \\\n"] + handler_registration = ["#define foreach_api_reply_handler \\\n"] for f in func_list: name = f['name'] camelcase_name = util.underscore_to_camelcase(f['name']) - if (not util.is_reply(camelcase_name) and not util.is_notification(name)) or util.is_ignored(name): + if (not util.is_reply(camelcase_name) and not util.is_notification(name)) or util.is_ignored(name) \ + or util.is_control_ping(camelcase_name): continue handler_registration.append(handler_registration_template.substitute( @@ -486,11 +515,9 @@ def generate_handler_registration(func_list): jvpp_c_template = Template("""/** * This file contains JNI bindings for jvpp Java API. * It was generated by jvpp_c_gen.py based on $inputfile - * (python representation of vpe.api generated by vppapigen). + * (python representation of api file generated by vppapigen). */ -void CallOnError(const char* call, int context, int retval); - // JAVA class reference cache $class_cache @@ -504,16 +531,16 @@ $msg_handlers $handler_registration """) -def generate_jvpp(func_list, inputfile): +def generate_jvpp(func_list, plugin_name, inputfile): """ Generates jvpp C file """ print "Generating jvpp C" - class_cache = generate_class_cache(func_list) - jni_impl = generate_jni_impl(func_list, inputfile) - msg_handlers = generate_msg_handlers(func_list, inputfile) + class_cache = generate_class_cache(func_list, plugin_name) + jni_impl = generate_jni_impl(func_list, plugin_name, inputfile) + msg_handlers = generate_msg_handlers(func_list, plugin_name, inputfile) handler_registration = generate_handler_registration(func_list) - jvpp_c_file = open("jvpp_gen.h", 'w') + jvpp_c_file = open("jvpp_%s_gen.h" % plugin_name, 'w') jvpp_c_file.write(jvpp_c_template.substitute( inputfile=inputfile, class_cache=class_cache, diff --git a/vpp-api/java/jvpp/gen/jvppgen/jvpp_callback_facade_gen.py b/vpp-api/java/jvpp/gen/jvppgen/jvpp_callback_facade_gen.py index 7df17486..ac096a71 100644 --- a/vpp-api/java/jvpp/gen/jvppgen/jvpp_callback_facade_gen.py +++ b/vpp-api/java/jvpp/gen/jvppgen/jvpp_callback_facade_gen.py @@ -20,17 +20,14 @@ import callback_gen import dto_gen jvpp_ifc_template = Template(""" -package $base_package.$callback_facade_package; +package $plugin_package.$callback_facade_package; /** - * <p>Callback Java API representation of vpe.api. + * <p>Callback Java API representation of $plugin_package plugin. * <br>It was generated by jvpp_callback_facade_gen.py based on $inputfile - * <br>(python representation of vpe.api generated by vppapigen). + * <br>(python representation of api file generated by vppapigen). */ -public interface CallbackJVpp extends $base_package.$notification_package.NotificationRegistryProvider, java.lang.AutoCloseable { - - @Override - void close(); +public interface CallbackJVpp${plugin_name} extends $base_package.$notification_package.NotificationRegistryProvider, java.lang.AutoCloseable { // TODO add send @@ -39,20 +36,20 @@ $methods """) jvpp_impl_template = Template(""" -package $base_package.$callback_facade_package; +package $plugin_package.$callback_facade_package; /** - * <p>Default implementation of CallbackJVpp interface. + * <p>Default implementation of Callback${plugin_name}JVpp interface. * <br>It was generated by jvpp_callback_facade_gen.py based on $inputfile - * <br>(python representation of vpe.api generated by vppapigen). + * <br>(python representation of api file generated by vppapigen). */ -public final class CallbackJVppFacade extends $base_package.$notification_package.NotificationRegistryProviderContext implements $base_package.$callback_facade_package.CallbackJVpp { +public final class CallbackJVpp${plugin_name}Facade implements CallbackJVpp${plugin_name} { - private final $base_package.JVpp jvpp; + private final $plugin_package.JVpp${plugin_name} jvpp; private final java.util.Map<Integer, $base_package.$callback_package.JVppCallback> callbacks; - + private final $plugin_package.$notification_package.${plugin_name}NotificationRegistryImpl notificationRegistry = new $plugin_package.$notification_package.${plugin_name}NotificationRegistryImpl(); /** - * <p>Create CallbackJVppFacade object for provided JVpp instance. + * <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 * @@ -60,14 +57,21 @@ public final class CallbackJVppFacade extends $base_package.$notification_packag * * @throws java.io.IOException in case instance cannot connect to JVPP */ - public CallbackJVppFacade(final $base_package.JVpp jvpp) throws java.io.IOException { + public CallbackJVpp${plugin_name}Facade(final $base_package.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<>(); - this.jvpp.connect(new CallbackJVppFacadeCallback(this.callbacks, getNotificationCallback())); + java.util.Objects.requireNonNull(registry, "JVppRegistry should not be null"); + registry.register(jvpp, new CallbackJVpp${plugin_name}FacadeCallback(this.callbacks, notificationRegistry)); + } + + @Override + public $plugin_package.$notification_package.${plugin_name}NotificationRegistry getNotificationRegistry() { + return notificationRegistry; } @Override - public void close() { + public void close() throws Exception { + jvpp.close(); } // TODO add send() @@ -77,17 +81,17 @@ $methods """) method_template = Template( - """ void $name($base_package.$dto_package.$request request, $base_package.$callback_package.$callback callback) throws org.openvpp.jvpp.VppInvocationException;""") + """ void $name($plugin_package.$dto_package.$request request, $plugin_package.$callback_package.$callback callback) throws $base_package.VppInvocationException;""") -method_impl_template = Template(""" public final void $name($base_package.$dto_package.$request request, $base_package.$callback_package.$callback callback) throws org.openvpp.jvpp.VppInvocationException { +method_impl_template = Template(""" public final void $name($plugin_package.$dto_package.$request request, $plugin_package.$callback_package.$callback callback) throws $base_package.VppInvocationException { synchronized (callbacks) { callbacks.put(jvpp.$name(request), callback); } } """) -no_arg_method_template = Template(""" void $name($base_package.$callback_package.$callback callback) throws org.openvpp.jvpp.VppInvocationException;""") -no_arg_method_impl_template = Template(""" public final void $name($base_package.$callback_package.$callback callback) throws org.openvpp.jvpp.VppInvocationException { +no_arg_method_template = Template(""" void $name($plugin_package.$callback_package.$callback callback) throws $base_package.VppInvocationException;""") +no_arg_method_impl_template = Template(""" public final void $name($plugin_package.$callback_package.$callback callback) throws $base_package.VppInvocationException { synchronized (callbacks) { callbacks.put(jvpp.$name(), callback); } @@ -95,7 +99,7 @@ no_arg_method_impl_template = Template(""" public final void $name($base_pack """) -def generate_jvpp(func_list, base_package, dto_package, callback_package, notification_package, callback_facade_package, inputfile): +def generate_jvpp(func_list, base_package, plugin_package, plugin_name, dto_package, callback_package, notification_package, callback_facade_package, inputfile): """ Generates callback facade """ print "Generating JVpp callback facade" @@ -109,12 +113,11 @@ def generate_jvpp(func_list, base_package, dto_package, callback_package, notifi for func in func_list: if util.is_notification(func['name']) or util.is_ignored(func['name']): - # TODO handle notifications continue camel_case_name = util.underscore_to_camelcase(func['name']) camel_case_name_upper = util.underscore_to_camelcase_upper(func['name']) - if util.is_reply(camel_case_name): + if util.is_reply(camel_case_name) or util.is_control_ping(camel_case_name): continue # Strip suffix for dump calls @@ -123,11 +126,13 @@ def generate_jvpp(func_list, base_package, dto_package, callback_package, notifi if len(func['args']) == 0: methods.append(no_arg_method_template.substitute(name=camel_case_name, base_package=base_package, + plugin_package=plugin_package, dto_package=dto_package, callback_package=callback_package, callback=callback_type)) methods_impl.append(no_arg_method_impl_template.substitute(name=camel_case_name, base_package=base_package, + plugin_package=plugin_package, dto_package=dto_package, callback_package=callback_package, callback=callback_type)) @@ -135,32 +140,38 @@ def generate_jvpp(func_list, base_package, dto_package, callback_package, notifi methods.append(method_template.substitute(name=camel_case_name, request=camel_case_name_upper, base_package=base_package, + plugin_package=plugin_package, dto_package=dto_package, callback_package=callback_package, callback=callback_type)) methods_impl.append(method_impl_template.substitute(name=camel_case_name, request=camel_case_name_upper, base_package=base_package, + plugin_package=plugin_package, dto_package=dto_package, callback_package=callback_package, callback=callback_type)) - join = os.path.join(callback_facade_package, "CallbackJVpp.java") + join = os.path.join(callback_facade_package, "CallbackJVpp%s.java" % plugin_name) jvpp_file = open(join, 'w') jvpp_file.write( jvpp_ifc_template.substitute(inputfile=inputfile, methods="\n".join(methods), base_package=base_package, + plugin_package=plugin_package, + plugin_name=plugin_name, dto_package=dto_package, notification_package=notification_package, callback_facade_package=callback_facade_package)) jvpp_file.flush() jvpp_file.close() - jvpp_file = open(os.path.join(callback_facade_package, "CallbackJVppFacade.java"), 'w') + jvpp_file = open(os.path.join(callback_facade_package, "CallbackJVpp%sFacade.java" % plugin_name), 'w') jvpp_file.write(jvpp_impl_template.substitute(inputfile=inputfile, methods="\n".join(methods_impl), base_package=base_package, + plugin_package=plugin_package, + plugin_name=plugin_name, dto_package=dto_package, notification_package=notification_package, callback_package=callback_package, @@ -168,31 +179,31 @@ def generate_jvpp(func_list, base_package, dto_package, callback_package, notifi jvpp_file.flush() jvpp_file.close() - generate_callback(func_list, base_package, dto_package, callback_package, notification_package, callback_facade_package, inputfile) + generate_callback(func_list, base_package, plugin_package, plugin_name, dto_package, callback_package, notification_package, callback_facade_package, inputfile) jvpp_facade_callback_template = Template(""" -package $base_package.$callback_facade_package; +package $plugin_package.$callback_facade_package; /** * <p>Implementation of JVppGlobalCallback interface for Java Callback API. * <br>It was generated by jvpp_callback_facade_gen.py based on $inputfile - * <br>(python representation of vpe.api generated by vppapigen). + * <br>(python representation of api file generated by vppapigen). */ -public final class CallbackJVppFacadeCallback implements $base_package.$callback_package.JVppGlobalCallback { +public final class CallbackJVpp${plugin_name}FacadeCallback implements $plugin_package.$callback_package.JVpp${plugin_name}GlobalCallback { private final java.util.Map<Integer, $base_package.$callback_package.JVppCallback> requests; - private final $base_package.$notification_package.GlobalNotificationCallback notificationCallback; - private static final java.util.logging.Logger LOG = java.util.logging.Logger.getLogger(CallbackJVppFacadeCallback.class.getName()); + private final $plugin_package.$notification_package.Global${plugin_name}NotificationCallback notificationCallback; + private static final java.util.logging.Logger LOG = java.util.logging.Logger.getLogger(CallbackJVpp${plugin_name}FacadeCallback.class.getName()); - public CallbackJVppFacadeCallback(final java.util.Map<Integer, $base_package.$callback_package.JVppCallback> requestMap, - final $base_package.$notification_package.GlobalNotificationCallback notificationCallback) { + public CallbackJVpp${plugin_name}FacadeCallback(final java.util.Map<Integer, $base_package.$callback_package.JVppCallback> requestMap, + final $plugin_package.$notification_package.Global${plugin_name}NotificationCallback notificationCallback) { this.requests = requestMap; this.notificationCallback = notificationCallback; } @Override - public void onError(org.openvpp.jvpp.VppCallbackException reply) { + public void onError($base_package.VppCallbackException reply) { $base_package.$callback_package.JVppCallback failedCall; synchronized(requests) { @@ -209,6 +220,20 @@ public final class CallbackJVppFacadeCallback implements $base_package.$callback } } + @Override + @SuppressWarnings("unchecked") + public void onControlPingReply($base_package.$dto_package.ControlPingReply reply) { + + $base_package.$callback_package.ControlPingCallback callback; + synchronized(requests) { + callback = ($base_package.$callback_package.ControlPingCallback) requests.remove(reply.context); + } + + if(callback != null) { + callback.onControlPingReply(reply); + } + } + $methods } """) @@ -216,11 +241,11 @@ $methods jvpp_facade_callback_method_template = Template(""" @Override @SuppressWarnings("unchecked") - public void on$callback_dto($base_package.$dto_package.$callback_dto reply) { + public void on$callback_dto($plugin_package.$dto_package.$callback_dto reply) { - $base_package.$callback_package.$callback callback; + $plugin_package.$callback_package.$callback callback; synchronized(requests) { - callback = ($base_package.$callback_package.$callback) requests.remove(reply.context); + callback = ($plugin_package.$callback_package.$callback) requests.remove(reply.context); } if(callback != null) { @@ -232,23 +257,23 @@ jvpp_facade_callback_method_template = Template(""" jvpp_facade_callback_notification_method_template = Template(""" @Override @SuppressWarnings("unchecked") - public void on$callback_dto($base_package.$dto_package.$callback_dto notification) { + public void on$callback_dto($plugin_package.$dto_package.$callback_dto notification) { notificationCallback.on$callback_dto(notification); } """) -def generate_callback(func_list, base_package, dto_package, callback_package, notification_package, callback_facade_package, inputfile): +def generate_callback(func_list, base_package, plugin_package, plugin_name, dto_package, callback_package, notification_package, callback_facade_package, inputfile): callbacks = [] for func in func_list: - if util.is_ignored(func['name']): - continue - camel_case_name_with_suffix = util.underscore_to_camelcase_upper(func['name']) + if util.is_ignored(func['name']) or util.is_control_ping(camel_case_name_with_suffix): + continue + if util.is_reply(camel_case_name_with_suffix): - callbacks.append(jvpp_facade_callback_method_template.substitute(base_package=base_package, + callbacks.append(jvpp_facade_callback_method_template.substitute(plugin_package=plugin_package, dto_package=dto_package, callback_package=callback_package, callback=util.remove_reply_suffix(camel_case_name_with_suffix) + callback_gen.callback_suffix, @@ -256,15 +281,17 @@ def generate_callback(func_list, base_package, dto_package, callback_package, no if util.is_notification(func["name"]): with_notification_suffix = util.add_notification_suffix(camel_case_name_with_suffix) - callbacks.append(jvpp_facade_callback_notification_method_template.substitute(base_package=base_package, + callbacks.append(jvpp_facade_callback_notification_method_template.substitute(plugin_package=plugin_package, dto_package=dto_package, callback_package=callback_package, callback=with_notification_suffix + callback_gen.callback_suffix, callback_dto=with_notification_suffix)) - jvpp_file = open(os.path.join(callback_facade_package, "CallbackJVppFacadeCallback.java"), 'w') + jvpp_file = open(os.path.join(callback_facade_package, "CallbackJVpp%sFacadeCallback.java" % plugin_name), 'w') jvpp_file.write(jvpp_facade_callback_template.substitute(inputfile=inputfile, base_package=base_package, + plugin_package=plugin_package, + plugin_name=plugin_name, dto_package=dto_package, notification_package=notification_package, callback_package=callback_package, diff --git a/vpp-api/java/jvpp/gen/jvppgen/jvpp_future_facade_gen.py b/vpp-api/java/jvpp/gen/jvppgen/jvpp_future_facade_gen.py index e1ca4d02..06c1073b 100644 --- a/vpp-api/java/jvpp/gen/jvppgen/jvpp_future_facade_gen.py +++ b/vpp-api/java/jvpp/gen/jvppgen/jvpp_future_facade_gen.py @@ -20,27 +20,28 @@ import dto_gen import util jvpp_facade_callback_template = Template(""" -package $base_package.$future_package; +package $plugin_package.$future_package; /** * <p>Async facade callback setting values to future objects * <br>It was generated by jvpp_future_facade_gen.py based on $inputfile - * <br>(python representation of vpe.api generated by vppapigen). + * <br>(python representation of api file generated by vppapigen). */ -public final class FutureJVppFacadeCallback implements $base_package.$callback_package.JVppGlobalCallback { +public final class FutureJVpp${plugin_name}FacadeCallback implements $plugin_package.$callback_package.JVpp${plugin_name}GlobalCallback { private final java.util.Map<java.lang.Integer, java.util.concurrent.CompletableFuture<? extends $base_package.$dto_package.JVppReply<?>>> requests; - private final $base_package.$notification_package.GlobalNotificationCallback notificationCallback; + private final $plugin_package.$notification_package.Global${plugin_name}NotificationCallback notificationCallback; - public FutureJVppFacadeCallback(final java.util.Map<java.lang.Integer, java.util.concurrent.CompletableFuture<? extends $base_package.$dto_package.JVppReply<?>>> requestMap, - final $base_package.$notification_package.GlobalNotificationCallback notificationCallback) { + public FutureJVpp${plugin_name}FacadeCallback( + final java.util.Map<java.lang.Integer, java.util.concurrent.CompletableFuture<? extends $base_package.$dto_package.JVppReply<?>>> requestMap, + final $plugin_package.$notification_package.Global${plugin_name}NotificationCallback notificationCallback) { this.requests = requestMap; this.notificationCallback = notificationCallback; } @Override @SuppressWarnings("unchecked") - public void onError(org.openvpp.jvpp.VppCallbackException reply) { + public void onError($base_package.VppCallbackException reply) { final java.util.concurrent.CompletableFuture<$base_package.$dto_package.JVppReply<?>> completableFuture; synchronized(requests) { @@ -56,14 +57,9 @@ public final class FutureJVppFacadeCallback implements $base_package.$callback_p } } -$methods -} -""") - -jvpp_facade_callback_method_template = Template(""" @Override @SuppressWarnings("unchecked") - public void on$callback_dto($base_package.$dto_package.$callback_dto reply) { + public void onControlPingReply($base_package.$dto_package.ControlPingReply reply) { final java.util.concurrent.CompletableFuture<$base_package.$dto_package.JVppReply<?>> completableFuture; synchronized(requests) { @@ -71,27 +67,31 @@ jvpp_facade_callback_method_template = Template(""" } if(completableFuture != null) { - completableFuture.complete(reply); + // Finish dump call + if (completableFuture instanceof $base_package.$future_package.AbstractFutureJVppInvoker.CompletableDumpFuture) { + completableFuture.complete((($base_package.$future_package.AbstractFutureJVppInvoker.CompletableDumpFuture) completableFuture).getReplyDump()); + // Remove future mapped to dump call context id + synchronized(requests) { + requests.remove((($base_package.$future_package.AbstractFutureJVppInvoker.CompletableDumpFuture) completableFuture).getContextId()); + } + } else { + completableFuture.complete(reply); + } synchronized(requests) { requests.remove(reply.context); } } } -""") -jvpp_facade_callback_notification_method_template = Template(""" - @Override - public void on$callback_dto($base_package.$dto_package.$callback_dto notification) { - notificationCallback.on$callback_dto(notification); - } +$methods +} """) -# TODO reuse common parts with generic method callback -jvpp_facade_control_ping_method_template = Template(""" +jvpp_facade_callback_method_template = Template(""" @Override @SuppressWarnings("unchecked") - public void on$callback_dto($base_package.$dto_package.$callback_dto reply) { + public void on$callback_dto($plugin_package.$dto_package.$callback_dto reply) { final java.util.concurrent.CompletableFuture<$base_package.$dto_package.JVppReply<?>> completableFuture; synchronized(requests) { @@ -99,16 +99,7 @@ jvpp_facade_control_ping_method_template = Template(""" } if(completableFuture != null) { - // Finish dump call - if (completableFuture instanceof $base_package.$future_package.FutureJVppFacade.CompletableDumpFuture) { - completableFuture.complete((($base_package.$future_package.FutureJVppFacade.CompletableDumpFuture) completableFuture).getReplyDump()); - // Remove future mapped to dump call context id - synchronized(requests) { - requests.remove((($base_package.$future_package.FutureJVppFacade.CompletableDumpFuture) completableFuture).getContextId()); - } - } else { - completableFuture.complete(reply); - } + completableFuture.complete(reply); synchronized(requests) { requests.remove(reply.context); @@ -117,20 +108,27 @@ jvpp_facade_control_ping_method_template = Template(""" } """) +jvpp_facade_callback_notification_method_template = Template(""" + @Override + public void on$callback_dto($plugin_package.$dto_package.$callback_dto notification) { + notificationCallback.on$callback_dto(notification); + } +""") + jvpp_facade_details_callback_method_template = Template(""" @Override @SuppressWarnings("unchecked") - public void on$callback_dto($base_package.$dto_package.$callback_dto reply) { - final FutureJVppFacade.CompletableDumpFuture<$base_package.$dto_package.$callback_dto_reply_dump> completableFuture; + public void on$callback_dto($plugin_package.$dto_package.$callback_dto reply) { + final $base_package.$future_package.AbstractFutureJVppInvoker.CompletableDumpFuture<$plugin_package.$dto_package.$callback_dto_reply_dump> completableFuture; synchronized(requests) { - completableFuture = ($base_package.$future_package.FutureJVppFacade.CompletableDumpFuture<$base_package.$dto_package.$callback_dto_reply_dump>) requests.get(reply.context); + completableFuture = ($base_package.$future_package.AbstractFutureJVppInvoker.CompletableDumpFuture<$plugin_package.$dto_package.$callback_dto_reply_dump>) requests.get(reply.context); } if(completableFuture != null) { - $base_package.$dto_package.$callback_dto_reply_dump replyDump = completableFuture.getReplyDump(); + $plugin_package.$dto_package.$callback_dto_reply_dump replyDump = completableFuture.getReplyDump(); if(replyDump == null) { - replyDump = new $base_package.$dto_package.$callback_dto_reply_dump(); + replyDump = new $plugin_package.$dto_package.$callback_dto_reply_dump(); completableFuture.setReplyDump(replyDump); } @@ -140,7 +138,7 @@ jvpp_facade_details_callback_method_template = Template(""" """) -def generate_jvpp(func_list, base_package, dto_package, callback_package, notification_package, future_facade_package, inputfile): +def generate_jvpp(func_list, base_package, plugin_package, plugin_name, dto_package, callback_package, notification_package, future_facade_package, inputfile): """ Generates JVpp interface and JNI implementation """ print "Generating JVpp future facade" @@ -151,11 +149,11 @@ def generate_jvpp(func_list, base_package, dto_package, callback_package, notifi methods_impl = [] callbacks = [] for func in func_list: + camel_case_name_with_suffix = util.underscore_to_camelcase_upper(func['name']) - if util.is_ignored(func['name']): + if util.is_ignored(func['name']) or util.is_control_ping(camel_case_name_with_suffix): continue - camel_case_name_with_suffix = util.underscore_to_camelcase_upper(func['name']) if not util.is_reply(camel_case_name_with_suffix) and not util.is_notification(func['name']): continue @@ -167,20 +165,21 @@ def generate_jvpp(func_list, base_package, dto_package, callback_package, notifi camel_case_reply_name = get_standard_dump_reply_name(util.underscore_to_camelcase_upper(func['name']), func['name']) callbacks.append(jvpp_facade_details_callback_method_template.substitute(base_package=base_package, + plugin_package=plugin_package, dto_package=dto_package, callback_dto=camel_case_name_with_suffix, callback_dto_field=camel_case_method_name, callback_dto_reply_dump=camel_case_reply_name + dto_gen.dump_dto_suffix, future_package=future_facade_package)) - methods.append(future_jvpp_method_template.substitute(base_package=base_package, + methods.append(future_jvpp_method_template.substitute(plugin_package=plugin_package, dto_package=dto_package, method_name=camel_case_request_method_name + util.underscore_to_camelcase_upper(util.dump_suffix), reply_name=camel_case_reply_name + dto_gen.dump_dto_suffix, request_name=util.remove_reply_suffix(camel_case_reply_name) + util.underscore_to_camelcase_upper(util.dump_suffix))) - methods_impl.append(future_jvpp_method_impl_template.substitute(base_package=base_package, + methods_impl.append(future_jvpp_method_impl_template.substitute(plugin_package=plugin_package, dto_package=dto_package, method_name=camel_case_request_method_name + util.underscore_to_camelcase_upper(util.dump_suffix), @@ -191,36 +190,32 @@ def generate_jvpp(func_list, base_package, dto_package, callback_package, notifi request_name = util.underscore_to_camelcase_upper(util.unconventional_naming_rep_req[func['name']]) \ if func['name'] in util.unconventional_naming_rep_req else util.remove_reply_suffix(camel_case_name_with_suffix) - methods.append(future_jvpp_method_template.substitute(base_package=base_package, + methods.append(future_jvpp_method_template.substitute(plugin_package=plugin_package, dto_package=dto_package, method_name=camel_case_request_method_name, reply_name=camel_case_name_with_suffix, request_name=request_name)) - methods_impl.append(future_jvpp_method_impl_template.substitute(base_package=base_package, + methods_impl.append(future_jvpp_method_impl_template.substitute(plugin_package=plugin_package, dto_package=dto_package, method_name=camel_case_request_method_name, reply_name=camel_case_name_with_suffix, request_name=request_name)) - # Callback handler is a bit special and a different template has to be used - if util.is_control_ping(camel_case_name_with_suffix): - callbacks.append(jvpp_facade_control_ping_method_template.substitute(base_package=base_package, - dto_package=dto_package, - callback_dto=camel_case_name_with_suffix, - future_package=future_facade_package)) - else: - callbacks.append(jvpp_facade_callback_method_template.substitute(base_package=base_package, - dto_package=dto_package, - callback_dto=camel_case_name_with_suffix)) + callbacks.append(jvpp_facade_callback_method_template.substitute(base_package=base_package, + plugin_package=plugin_package, + dto_package=dto_package, + callback_dto=camel_case_name_with_suffix)) if util.is_notification(func["name"]): - callbacks.append(jvpp_facade_callback_notification_method_template.substitute(base_package=base_package, + callbacks.append(jvpp_facade_callback_notification_method_template.substitute(plugin_package=plugin_package, dto_package=dto_package, callback_dto=util.add_notification_suffix(camel_case_name_with_suffix))) - jvpp_file = open(os.path.join(future_facade_package, "FutureJVppFacadeCallback.java"), 'w') + jvpp_file = open(os.path.join(future_facade_package, "FutureJVpp%sFacadeCallback.java" % plugin_name), 'w') jvpp_file.write(jvpp_facade_callback_template.substitute(inputfile=inputfile, base_package=base_package, + plugin_package=plugin_package, + plugin_name=plugin_name, dto_package=dto_package, notification_package=notification_package, callback_package=callback_package, @@ -229,18 +224,24 @@ def generate_jvpp(func_list, base_package, dto_package, callback_package, notifi jvpp_file.flush() jvpp_file.close() - jvpp_file = open(os.path.join(future_facade_package, "FutureJVpp.java"), 'w') + jvpp_file = open(os.path.join(future_facade_package, "FutureJVpp%s.java" % plugin_name), 'w') jvpp_file.write(future_jvpp_template.substitute(inputfile=inputfile, base_package=base_package, + plugin_package=plugin_package, + plugin_name=plugin_name, + notification_package=notification_package, methods="".join(methods), future_package=future_facade_package)) jvpp_file.flush() jvpp_file.close() - jvpp_file = open(os.path.join(future_facade_package, "FutureJVppFacade.java"), 'w') + jvpp_file = open(os.path.join(future_facade_package, "FutureJVpp%sFacade.java" % plugin_name), 'w') jvpp_file.write(future_jvpp_facade_template.substitute(inputfile=inputfile, base_package=base_package, + plugin_package=plugin_package, + plugin_name=plugin_name, dto_package=dto_package, + notification_package=notification_package, methods="".join(methods_impl), future_package=future_facade_package)) jvpp_file.flush() @@ -248,35 +249,41 @@ def generate_jvpp(func_list, base_package, dto_package, callback_package, notifi future_jvpp_template = Template(''' -package $base_package.$future_package; +package $plugin_package.$future_package; /** * <p>Async facade extension adding specific methods for each request invocation * <br>It was generated by jvpp_future_facade_gen.py based on $inputfile - * <br>(python representation of vpe.api generated by vppapigen). + * <br>(python representation of api file generated by vppapigen). */ -public interface FutureJVpp extends FutureJVppInvoker { +public interface FutureJVpp${plugin_name} extends $base_package.$future_package.FutureJVppInvoker { $methods + + @Override + public $plugin_package.$notification_package.${plugin_name}NotificationRegistry getNotificationRegistry(); + } ''') future_jvpp_method_template = Template(''' - java.util.concurrent.CompletionStage<$base_package.$dto_package.$reply_name> $method_name($base_package.$dto_package.$request_name request); + java.util.concurrent.CompletionStage<$plugin_package.$dto_package.$reply_name> $method_name($plugin_package.$dto_package.$request_name request); ''') future_jvpp_facade_template = Template(''' -package $base_package.$future_package; +package $plugin_package.$future_package; /** - * <p>Implementation of FutureJVpp based on FutureJVppInvokerFacade + * <p>Implementation of FutureJVpp based on AbstractFutureJVppInvoker * <br>It was generated by jvpp_future_facade_gen.py based on $inputfile - * <br>(python representation of vpe.api generated by vppapigen). + * <br>(python representation of api file generated by vppapigen). */ -public class FutureJVppFacade extends FutureJVppInvokerFacade implements FutureJVpp { +public class FutureJVpp${plugin_name}Facade extends $base_package.$future_package.AbstractFutureJVppInvoker implements FutureJVpp${plugin_name} { + + private final $plugin_package.$notification_package.${plugin_name}NotificationRegistryImpl notificationRegistry = new $plugin_package.$notification_package.${plugin_name}NotificationRegistryImpl(); /** - * <p>Create FutureJVppFacade object for provided JVpp instance. + * <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 * @@ -284,17 +291,24 @@ public class FutureJVppFacade extends FutureJVppInvokerFacade implements FutureJ * * @throws java.io.IOException in case instance cannot connect to JVPP */ - public FutureJVppFacade(final $base_package.JVpp jvpp) throws java.io.IOException { - super(jvpp, new java.util.HashMap<>()); - jvpp.connect(new FutureJVppFacadeCallback(getRequests(), getNotificationCallback())); + public FutureJVpp${plugin_name}Facade(final $base_package.JVppRegistry registry, final $base_package.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(), notificationRegistry)); + } + + @Override + public $plugin_package.$notification_package.${plugin_name}NotificationRegistry getNotificationRegistry() { + return notificationRegistry; } + $methods } ''') future_jvpp_method_impl_template = Template(''' @Override - public java.util.concurrent.CompletionStage<$base_package.$dto_package.$reply_name> $method_name($base_package.$dto_package.$request_name request) { + public java.util.concurrent.CompletionStage<$plugin_package.$dto_package.$reply_name> $method_name($plugin_package.$dto_package.$request_name request) { return send(request); } ''') diff --git a/vpp-api/java/jvpp/gen/jvppgen/jvpp_impl_gen.py b/vpp-api/java/jvpp/gen/jvppgen/jvpp_impl_gen.py index 93ffd0fb..41df4f2a 100644 --- a/vpp-api/java/jvpp/gen/jvppgen/jvpp_impl_gen.py +++ b/vpp-api/java/jvpp/gen/jvppgen/jvpp_impl_gen.py @@ -17,25 +17,14 @@ import os, util from string import Template jvpp_ifc_template = Template(""" -package $base_package; - +package $plugin_package; /** - * <p>Java representation of vpe.api. + * <p>Java representation of plugin's api file. * <br>It was generated by jvpp_impl_gen.py based on $inputfile - * <br>(python representation of vpe.api generated by vppapigen). + * <br>(python representation of api file generated by vppapigen). */ -public interface JVpp extends java.lang.AutoCloseable { - - /** - * Generic connect with $base_package.callback.JVppCallback callback handler - * providing connecting to VPP - * - * @param callback JVppCallback instance providing callback handling - * - * @throws java.io.IOException if connection cannot be initiated - */ - void connect($base_package.callback.JVppCallback callback) throws java.io.IOException; +public interface JVpp${plugin_name} extends $base_package.JVpp { /** * Generic dispatch method for sending requests to VPP @@ -44,52 +33,110 @@ public interface JVpp extends java.lang.AutoCloseable { */ int send($base_package.$dto_package.JVppRequest request) throws org.openvpp.jvpp.VppInvocationException; - @Override - void close(); - $methods } """) jvpp_impl_template = Template(""" -package $base_package; +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 $base_package.callback.JVppCallback; +import $base_package.VppConnection; +import $base_package.JVppRegistry; /** * <p>Default implementation of JVpp interface. * <br>It was generated by jvpp_impl_gen.py based on $inputfile - * <br>(python representation of vpe.api generated by vppapigen). + * <br>(python representation of api file generated by vppapigen). */ -public final class JVppImpl implements $base_package.JVpp { +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 String LIBNAME = "libjvpp_${plugin_name_underscore}.so.0.0.0"; + + // 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 final $base_package.VppConnection connection; + 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) { + } + } + } - public JVppImpl(final $base_package.VppConnection connection) { - this.connection = java.util.Objects.requireNonNull(connection,"Connection is null"); + 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 connect($base_package.callback.JVppCallback callback) throws java.io.IOException { - connection.connect(callback); + 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() { - connection.close(); + close0(); } @Override - public int send($base_package.$dto_package.JVppRequest request) throws org.openvpp.jvpp.VppInvocationException { + public int send($base_package.$dto_package.JVppRequest request) throws org.openvpp.jvpp.VppInvocationException { return request.send(this); } + @Override + public final int controlPing(final org.openvpp.jvpp.dto.ControlPing controlPing) throws org.openvpp.jvpp.VppInvocationException { + return registry.controlPing(JVpp${plugin_name}Impl.class); + } + $methods } """) -method_template = Template(""" int $name($base_package.$dto_package.$request request) throws org.openvpp.jvpp.VppInvocationException;""") +method_template = Template(""" int $name($plugin_package.$dto_package.$request request) throws org.openvpp.jvpp.VppInvocationException;""") method_native_template = Template( - """ private static native int ${name}0($base_package.$dto_package.$request request);""") -method_impl_template = Template(""" public final int $name($base_package.$dto_package.$request request) throws org.openvpp.jvpp.VppInvocationException { + """ private static native int ${name}0($plugin_package.$dto_package.$request request);""") +method_impl_template = Template(""" public final int $name($plugin_package.$dto_package.$request request) throws org.openvpp.jvpp.VppInvocationException { java.util.Objects.requireNonNull(request,"Null request object"); connection.checkActive(); int result=${name}0(request); @@ -113,9 +160,10 @@ no_arg_method_impl_template = Template(""" public final int $name() throws or """) -def generate_jvpp(func_list, base_package, dto_package, inputfile): +def generate_jvpp(func_list, base_package, plugin_package, plugin_name_underscore, control_ping_class, dto_package, inputfile): """ Generates JVpp interface and JNI implementation """ print "Generating JVpp" + plugin_name = util.underscore_to_camelcase_upper(plugin_name_underscore) methods = [] methods_impl = [] @@ -131,43 +179,42 @@ def generate_jvpp(func_list, base_package, dto_package, inputfile): continue if len(func['args']) == 0: - methods.append(no_arg_method_template.substitute(name=camel_case_name, - base_package=base_package, - dto_package=dto_package)) - methods_impl.append( - no_arg_method_native_template.substitute(name=camel_case_name, - base_package=base_package, - dto_package=dto_package)) - methods_impl.append(no_arg_method_impl_template.substitute(name=camel_case_name, - base_package=base_package, - dto_package=dto_package)) + methods.append(no_arg_method_template.substitute(name=camel_case_name)) + methods_impl.append(no_arg_method_native_template.substitute(name=camel_case_name)) + methods_impl.append(no_arg_method_impl_template.substitute(name=camel_case_name)) else: methods.append(method_template.substitute(name=camel_case_name, request=camel_case_name_upper, - base_package=base_package, + plugin_package=plugin_package, dto_package=dto_package)) methods_impl.append(method_native_template.substitute(name=camel_case_name, request=camel_case_name_upper, - base_package=base_package, + plugin_package=plugin_package, dto_package=dto_package)) methods_impl.append(method_impl_template.substitute(name=camel_case_name, request=camel_case_name_upper, - base_package=base_package, + plugin_package=plugin_package, dto_package=dto_package)) - jvpp_file = open("JVpp.java", 'w') + jvpp_file = open("JVpp%s.java" % plugin_name, 'w') jvpp_file.write( jvpp_ifc_template.substitute(inputfile=inputfile, methods="\n".join(methods), base_package=base_package, + plugin_package=plugin_package, + plugin_name=plugin_name, dto_package=dto_package)) jvpp_file.flush() jvpp_file.close() - jvpp_file = open("JVppImpl.java", 'w') + jvpp_file = open("JVpp%sImpl.java" % plugin_name, 'w') jvpp_file.write(jvpp_impl_template.substitute(inputfile=inputfile, methods="\n".join(methods_impl), base_package=base_package, - dto_package=dto_package)) + plugin_package=plugin_package, + plugin_name=plugin_name, + plugin_name_underscore=plugin_name_underscore, + dto_package=dto_package, + control_ping_class=control_ping_class)) jvpp_file.flush() jvpp_file.close() diff --git a/vpp-api/java/jvpp/gen/jvppgen/notification_gen.py b/vpp-api/java/jvpp/gen/jvppgen/notification_gen.py index df6407f8..eb380fc8 100644 --- a/vpp-api/java/jvpp/gen/jvppgen/notification_gen.py +++ b/vpp-api/java/jvpp/gen/jvppgen/notification_gen.py @@ -19,17 +19,15 @@ import callback_gen import util from string import Template -from util import remove_suffix - notification_registry_template = Template(""" -package $base_package.$notification_package; +package $plugin_package.$notification_package; /** - * <p>Registry for notification callbacks. + * <p>Registry for notification callbacks defined in ${plugin_name}. * <br>It was generated by notification_gen.py based on $inputfile - * <br>(python representation of vpe.api generated by vppapigen). + * <br>(python representation of api file generated by vppapigen). */ -public interface NotificationRegistry extends java.lang.AutoCloseable { +public interface ${plugin_name}NotificationRegistry extends $base_package.$notification_package.NotificationRegistry { $register_callback_methods @@ -39,27 +37,27 @@ public interface NotificationRegistry extends java.lang.AutoCloseable { """) global_notification_callback_template = Template(""" -package $base_package.$notification_package; +package $plugin_package.$notification_package; /** * <p>Aggregated callback interface for notifications only. * <br>It was generated by notification_gen.py based on $inputfile - * <br>(python representation of vpe.api generated by vppapigen). + * <br>(python representation of api file generated by vppapigen). */ -public interface GlobalNotificationCallback extends $callbacks { +public interface Global${plugin_name}NotificationCallback$callbacks { } """) notification_registry_impl_template = Template(""" -package $base_package.$notification_package; +package $plugin_package.$notification_package; /** * <p>Notification registry delegating notification processing to registered callbacks. * <br>It was generated by notification_gen.py based on $inputfile - * <br>(python representation of vpe.api generated by vppapigen). + * <br>(python representation of api file generated by vppapigen). */ -public final class NotificationRegistryImpl implements NotificationRegistry, GlobalNotificationCallback { +public final class ${plugin_name}NotificationRegistryImpl implements ${plugin_name}NotificationRegistry, Global${plugin_name}NotificationCallback { // TODO add a special NotificationCallback interface and only allow those to be registered private final java.util.concurrent.ConcurrentMap<Class<? extends $base_package.$dto_package.JVppNotification>, $base_package.$callback_package.JVppNotificationCallback> registeredCallbacks = @@ -76,30 +74,45 @@ public final class NotificationRegistryImpl implements NotificationRegistry, Glo """) register_callback_impl_template = Template(""" - public java.lang.AutoCloseable register$callback(final $base_package.$callback_package.$callback callback){ - if(null != registeredCallbacks.putIfAbsent($base_package.$dto_package.$notification.class, callback)){ - throw new IllegalArgumentException("Callback for " + $base_package.$dto_package.$notification.class + + public java.lang.AutoCloseable register$callback(final $plugin_package.$callback_package.$callback callback){ + if(null != registeredCallbacks.putIfAbsent($plugin_package.$dto_package.$notification.class, callback)){ + throw new IllegalArgumentException("Callback for " + $plugin_package.$dto_package.$notification.class + "notification already registered"); } - return () -> registeredCallbacks.remove($base_package.$dto_package.$notification.class); + return () -> registeredCallbacks.remove($plugin_package.$dto_package.$notification.class); } """) handler_impl_template = Template(""" @Override public void on$notification( - final $base_package.$dto_package.$notification notification) { - final $base_package.$callback_package.JVppNotificationCallback JVppNotificationCallback = registeredCallbacks.get($base_package.$dto_package.$notification.class); - if (null != JVppNotificationCallback) { - (($base_package.$callback_package.$callback) registeredCallbacks - .get($base_package.$dto_package.$notification.class)) + final $plugin_package.$dto_package.$notification notification) { + final $base_package.$callback_package.JVppNotificationCallback jVppNotificationCallback = registeredCallbacks.get($plugin_package.$dto_package.$notification.class); + if (null != jVppNotificationCallback) { + (($plugin_package.$callback_package.$callback) registeredCallbacks + .get($plugin_package.$dto_package.$notification.class)) .on$notification(notification); } } """) +notification_provider_template = Template(""" +package $plugin_package.$notification_package; + + /** + * Provides ${plugin_name}NotificationRegistry. + * <br>The file was generated by notification_gen.py based on $inputfile + * <br>(python representation of api file generated by vppapigen). + */ +public interface ${plugin_name}NotificationRegistryProvider extends $base_package.$notification_package.NotificationRegistryProvider { -def generate_notification_registry(func_list, base_package, notification_package, callback_package, dto_package, inputfile): + @Override + public ${plugin_name}NotificationRegistry getNotificationRegistry(); +} +""") + + +def generate_notification_registry(func_list, base_package, plugin_package, plugin_name, notification_package, callback_package, dto_package, inputfile): """ Generates notification registry interface and implementation """ print "Generating Notification interfaces and implementation" @@ -118,47 +131,69 @@ def generate_notification_registry(func_list, base_package, notification_package camel_case_name_with_suffix = util.underscore_to_camelcase_upper(func['name']) notification_dto = util.add_notification_suffix(camel_case_name_with_suffix) callback_ifc = notification_dto + callback_gen.callback_suffix - fully_qualified_callback_ifc = "{0}.{1}.{2}".format(base_package, callback_package, callback_ifc) + fully_qualified_callback_ifc = "{0}.{1}.{2}".format(plugin_package, callback_package, callback_ifc) callbacks.append(fully_qualified_callback_ifc) # 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{0}({1} callback);" .format(callback_ifc, fully_qualified_callback_ifc)) - register_callback_methods_impl.append(register_callback_impl_template.substitute(base_package=base_package, + register_callback_methods_impl.append(register_callback_impl_template.substitute(plugin_package=plugin_package, callback_package=callback_package, dto_package=dto_package, notification=notification_dto, callback=callback_ifc)) handler_methods.append(handler_impl_template.substitute(base_package=base_package, + plugin_package=plugin_package, callback_package=callback_package, dto_package=dto_package, notification=notification_dto, callback=callback_ifc)) - if(callbacks): - callback_file = open(os.path.join(notification_package, "NotificationRegistry.java"), 'w') - callback_file.write(notification_registry_template.substitute(inputfile=inputfile, - register_callback_methods="\n ".join(register_callback_methods), - base_package=base_package, - notification_package=notification_package)) - callback_file.flush() - callback_file.close() - - callback_file = open(os.path.join(notification_package, "GlobalNotificationCallback.java"), 'w') - callback_file.write(global_notification_callback_template.substitute(inputfile=inputfile, - callbacks=", ".join(callbacks), - base_package=base_package, - notification_package=notification_package)) - callback_file.flush() - callback_file.close() - - callback_file = open(os.path.join(notification_package, "NotificationRegistryImpl.java"), 'w') - callback_file.write(notification_registry_impl_template.substitute(inputfile=inputfile, - callback_package=callback_package, - dto_package=dto_package, - register_callback_methods="".join(register_callback_methods_impl), - handler_methods="".join(handler_methods), - base_package=base_package, - notification_package=notification_package)) - callback_file.flush() - callback_file.close() + + + callback_file = open(os.path.join(notification_package, "%sNotificationRegistry.java" % plugin_name), 'w') + callback_file.write(notification_registry_template.substitute(inputfile=inputfile, + register_callback_methods="\n ".join(register_callback_methods), + base_package=base_package, + plugin_package=plugin_package, + plugin_name=plugin_name, + notification_package=notification_package)) + callback_file.flush() + callback_file.close() + + callback_file = open(os.path.join(notification_package, "Global%sNotificationCallback.java" % plugin_name), 'w') + + global_notification_callback_callbacks = "" + if (callbacks): + global_notification_callback_callbacks = " extends " + ", ".join(callbacks) + + callback_file.write(global_notification_callback_template.substitute(inputfile=inputfile, + callbacks=global_notification_callback_callbacks, + plugin_package=plugin_package, + plugin_name=plugin_name, + notification_package=notification_package)) + callback_file.flush() + callback_file.close() + + callback_file = open(os.path.join(notification_package, "%sNotificationRegistryImpl.java" % plugin_name), 'w') + callback_file.write(notification_registry_impl_template.substitute(inputfile=inputfile, + callback_package=callback_package, + dto_package=dto_package, + register_callback_methods="".join(register_callback_methods_impl), + handler_methods="".join(handler_methods), + base_package=base_package, + plugin_package=plugin_package, + plugin_name=plugin_name, + notification_package=notification_package)) + callback_file.flush() + callback_file.close() + + callback_file = open(os.path.join(notification_package, "%sNotificationRegistryProvider.java" % plugin_name), 'w') + callback_file.write(notification_provider_template.substitute(inputfile=inputfile, + base_package=base_package, + plugin_package=plugin_package, + plugin_name=plugin_name, + notification_package=notification_package)) + callback_file.flush() + callback_file.close() + diff --git a/vpp-api/java/jvpp/gen/jvppgen/util.py b/vpp-api/java/jvpp/gen/jvppgen/util.py index f22132df..0018e014 100644 --- a/vpp-api/java/jvpp/gen/jvppgen/util.py +++ b/vpp-api/java/jvpp/gen/jvppgen/util.py @@ -120,15 +120,18 @@ jni_field_accessors = { 'jfloatArray': 'ObjectField' } -# TODO watch out for unsigned types +# Mapping according to: # http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html -vpp_2_jni_type_mapping = {'u8': 'jbyte', # fixme +# +# Unsigned types are converted to signed java types that have the same size. +# It is the API user responsibility to interpret them correctly. +vpp_2_jni_type_mapping = {'u8': 'jbyte', 'i8': 'jbyte', 'u16': 'jshort', 'i16': 'jshort', - 'u32': 'jint', # fixme + 'u32': 'jint', 'i32': 'jint', - 'u64': 'jlong', # fixme + 'u64': 'jlong', 'i64': 'jlong', 'f64': 'jdouble' } @@ -179,7 +182,7 @@ def remove_suffix(camel_case_name_with_suffix, suffix): def is_control_ping(camel_case_name_with_suffix): - return "controlping" in camel_case_name_with_suffix.lower() + return camel_case_name_with_suffix.lower().startswith("controlping"); def api_message_to_javadoc(api_message): """ Converts vpe.api message description to javadoc """ diff --git a/vpp-api/java/jvpp/jvpp.c b/vpp-api/java/jvpp/jvpp.c deleted file mode 100644 index 37aef803..00000000 --- a/vpp-api/java/jvpp/jvpp.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#define _GNU_SOURCE /* for strcasestr(3) */ -#include <vnet/vnet.h> - -#define vl_api_version(n,v) static u32 vpe_api_version = (v); -#include <vpp-api/vpe.api.h> -#undef vl_api_version - -#include <jni.h> -#include <jvpp/jvpp.h> -#include <jvpp/org_openvpp_jvpp_VppJNIConnection.h> -#include <jvpp/org_openvpp_jvpp_JVppImpl.h> - -#include <vpp-api/vpe_msg_enum.h> -#define vl_typedefs /* define message structures */ -#include <vpp-api/vpe_all_api_h.h> -#undef vl_typedefs - -#define vl_endianfun -#include <vpp-api/vpe_all_api_h.h> -#undef vl_endianfun - -/* instantiate all the print functions we know about */ -#define vl_print(handle, ...) -#define vl_printfun -#include <vpp-api/vpe_all_api_h.h> -#undef vl_printfun - -#ifndef VPPJNI_DEBUG -#define VPPJNI_DEBUG 0 -#endif - -#if VPPJNI_DEBUG == 1 - #define DEBUG_LOG(...) clib_warning(__VA_ARGS__) -#else - #define DEBUG_LOG(...) -#endif - -#include "gen/target/jvpp_gen.h" - -static int connect_to_vpe(char *name); - -/* - * The Java runtime isn't compile w/ -fstack-protector, - * so we have to supply missing external references for the - * regular vpp libraries. Weak reference in case folks get religion - * at a later date... - */ -void __stack_chk_guard (void) __attribute__((weak)); -void __stack_chk_guard (void) { } - -void vl_client_add_api_signatures (vl_api_memclnt_create_t *mp) -{ - /* - * Send the main API signature in slot 0. This bit of code must - * match the checks in ../vpe/api/api.c: vl_msg_api_version_check(). - */ - mp->api_versions[0] = clib_host_to_net_u32 (vpe_api_version); -} - -/* cleanup handler for RX thread */ -static void cleanup_rx_thread(void *arg) -{ - vppjni_main_t * jm = &vppjni_main; - - vppjni_lock (jm, 99); - - int getEnvStat = (*jm->jvm)->GetEnv(jm->jvm, (void **)&(jm->jenv), JNI_VERSION_1_8); - if (getEnvStat == JNI_EVERSION) { - clib_warning ("Unsupported JNI version\n"); - jm->retval = VNET_API_ERROR_UNSUPPORTED_JNI_VERSION; - goto out; - } else if (getEnvStat != JNI_EDETACHED) { - (*jm->jvm)->DetachCurrentThread(jm->jvm); - } -out: - vppjni_unlock (jm); -} - -JNIEXPORT jint JNICALL Java_org_openvpp_jvpp_VppJNIConnection_clientConnect - (JNIEnv *env, jclass obj, jstring clientName, jobject callback) -{ - int rv; - const char *client_name; - void vl_msg_reply_handler_hookup(void); - vppjni_main_t * jm = &vppjni_main; - - /* - * Bail out now if we're not running as root - */ - if (geteuid() != 0) - return VNET_API_ERROR_NOT_RUNNING_AS_ROOT; - - if (jm->is_connected) - return VNET_API_ERROR_ALREADY_CONNECTED; - - client_name = (*env)->GetStringUTFChars(env, clientName, 0); - if (!client_name) - return VNET_API_ERROR_INVALID_VALUE; - - rv = connect_to_vpe ((char *) client_name); - - if (rv < 0) - clib_warning ("connection failed, rv %d", rv); - - (*env)->ReleaseStringUTFChars (env, clientName, client_name); - - if (rv == 0) { - f64 timeout; - clib_time_t clib_time; - clib_time_init (&clib_time); - - /* vl_msg_reply_handler_hookup (); */ - jm->is_connected = 1; - - jm->callback = (*env)->NewGlobalRef(env, callback); - jm->callbackClass = (jclass)(*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, callback)); - - { - // call control ping first to attach rx thread to java thread - vl_api_control_ping_t * mp; - M(CONTROL_PING, control_ping); - S; - - // wait for results: Current time + 10 seconds is the timeout - timeout = clib_time_now (&clib_time) + 10.0; - rv = VNET_API_ERROR_RESPONSE_NOT_READY; - while (clib_time_now (&clib_time) < timeout) { - if (jm->result_ready == 1) { - rv = (jm->retval); - break; - } - } - - if (rv != 0) { - clib_warning ("first control ping failed: %d", rv); - } - } - } - DEBUG_LOG ("clientConnect result: %d", rv); - return rv; -} - -JNIEXPORT void JNICALL Java_org_openvpp_jvpp_VppJNIConnection_clientDisconnect - (JNIEnv *env, jclass clazz) -{ - vppjni_main_t * jm = &vppjni_main; - jm->is_connected = 0; // TODO make thread safe - vl_client_disconnect_from_vlib(); -} - -/** -* Send error reply to the requestor -* const char* call pointer to the request name -* int context call context identifier -* int retval result of the operation -*/ -void CallOnError(const char* call, int context, int retval) -{ - DEBUG_LOG("\nCallOnError : callback=%s,retval=%d,context=%d\n",call,clib_net_to_host_u32(retval), clib_net_to_host_u32(context)); - vppjni_main_t * jm = &vppjni_main; - JNIEnv *env = jm->jenv; - if (!env) printf( "CallOnError : env is null!\n"); - if (!jm->callbackClass) { - DEBUG_LOG( "CallOnError : jm->callbackClass is null!\n"); - return; - } - - jmethodID excConstructor = (*env)->GetMethodID(env, callbackExceptionClass, "<init>", "(Ljava/lang/String;II)V"); - if (!excConstructor) { - DEBUG_LOG( "CallOnError : excConstructor is null!\n"); - return; - } - jmethodID callbackExcMethod = (*env)->GetMethodID(env, jm->callbackClass, "onError", "(Lorg/openvpp/jvpp/VppCallbackException;)V"); - if (!callbackExcMethod) { - DEBUG_LOG( "CallOnError : callbackExcMethod is null!\n"); - return; - } - - jobject excObject = (*env)->NewObject(env, callbackExceptionClass, excConstructor,(*env)->NewStringUTF(env, call), clib_net_to_host_u32(context), clib_net_to_host_u32(retval)); - if (!excObject) { - DEBUG_LOG( "CallOnError : excObject is null!\n"); - return; - } - - (*env)->CallVoidMethod(env, jm->callback, callbackExcMethod, excObject); - DEBUG_LOG( "CallOnError : Response sent\n"); -} - -// control ping needs to be very first thing called -// to attach rx thread to java thread -static void vl_api_control_ping_reply_t_handler -(vl_api_control_ping_reply_t * mp) -{ - vppjni_main_t * jm = &vppjni_main; - - char was_thread_connected = 0; - - // attach to java thread if not attached - int getEnvStat = (*jm->jvm)->GetEnv(jm->jvm, (void **)&(jm->jenv), JNI_VERSION_1_8); - if (getEnvStat == JNI_EDETACHED) { - if ((*jm->jvm)->AttachCurrentThread(jm->jvm, (void **)&(jm->jenv), NULL) != 0) { - clib_warning("Failed to attach thread\n"); - jm->retval = VNET_API_ERROR_FAILED_TO_ATTACH_TO_JAVA_THREAD; - goto out; - } - - // workaround as we can't use pthread_cleanup_push - pthread_key_create(&jm->cleanup_rx_thread_key, cleanup_rx_thread); - // destructor is only called if the value of key is non null - pthread_setspecific(jm->cleanup_rx_thread_key, (void *)1); - was_thread_connected = 1; - } else if (getEnvStat == JNI_EVERSION) { - clib_warning ("Unsupported JNI version\n"); - jm->retval = VNET_API_ERROR_UNSUPPORTED_JNI_VERSION; - goto out; - } - - if (was_thread_connected == 0) { - JNIEnv *env = jm->jenv; - - if (mp->retval<0){ - CallOnError("controlPing", mp->context, mp->retval); - } else { - jmethodID constructor = (*env)->GetMethodID(env, controlPingReplyClass, "<init>", "()V"); - jmethodID callbackMethod = (*env)->GetMethodID(env, jm->callbackClass, "onControlPingReply", "(Lorg/openvpp/jvpp/dto/ControlPingReply;)V"); - - jobject dto = (*env)->NewObject(env, controlPingReplyClass, constructor); - - jfieldID contextFieldId = (*env)->GetFieldID(env, controlPingReplyClass, "context", "I"); - (*env)->SetIntField(env, dto, contextFieldId, clib_net_to_host_u32(mp->context)); - - jfieldID clientIndexFieldId = (*env)->GetFieldID(env, controlPingReplyClass, "clientIndex", "I"); - (*env)->SetIntField(env, dto, clientIndexFieldId, clib_net_to_host_u32(mp->client_index)); - - jfieldID vpePidFieldId = (*env)->GetFieldID(env, controlPingReplyClass, "vpePid", "I"); - (*env)->SetIntField(env, dto, vpePidFieldId, clib_net_to_host_u32(mp->vpe_pid)); - - (*env)->CallVoidMethod(env, jm->callback, callbackMethod, dto); - } - } - - out: - jm->result_ready = 1; -} - -jint JNI_OnLoad(JavaVM *vm, void *reserved) { - vppjni_main_t * jm = &vppjni_main; - JNIEnv* env; - if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_8) != JNI_OK) { - return JNI_EVERSION; - } - - if (cache_class_references(env) != 0) { - return JNI_ERR; - } - - jm->jvm = vm; - return JNI_VERSION_1_8; -} - -void JNI_OnUnload(JavaVM *vm, void *reserved) { - vppjni_main_t * jm = &vppjni_main; - JNIEnv* env; - if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_8) != JNI_OK) { - return; - } - - // cleanup: - (*env)->DeleteGlobalRef(env, jm->callbackClass); - (*env)->DeleteGlobalRef(env, jm->callback); - - jm->callbackClass = NULL; - jm->callback = NULL; - jm->jenv = NULL; - jm->jvm = NULL; -} - -static int connect_to_vpe(char *name) -{ - vppjni_main_t * jm = &vppjni_main; - api_main_t * am = &api_main; - - if (vl_client_connect_to_vlib("/vpe-api", name, 32) < 0) - return -1; - - jm->my_client_index = am->my_client_index; - jm->vl_input_queue = am->shmem_hdr->vl_input_queue; - -#define _(N,n) \ - vl_msg_api_set_handlers(VL_API_##N, #n, \ - vl_api_##n##_t_handler, \ - vl_noop_handler, \ - vl_api_##n##_t_endian, \ - vl_api_##n##_t_print, \ - sizeof(vl_api_##n##_t), 1); - foreach_vpe_api_msg; -#undef _ - - return 0; -} diff --git a/vpp-api/java/jvpp/jvpp.h b/vpp-api/java/jvpp/jvpp.h deleted file mode 100644 index 15f9057f..00000000 --- a/vpp-api/java/jvpp/jvpp.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef __included_vppjni_h__ -#define __included_vppjni_h__ - -#include <vnet/vnet.h> -#include <vnet/ip/ip.h> -#include <vnet/api_errno.h> -#include <vlibapi/api.h> -#include <vlibmemory/api.h> -#include <jni.h> - -typedef struct { - /* Unique identifier used for matching replays with requests */ - volatile u32 context_id; - - /* Spinlock */ - volatile u32 lock; - u32 tag; - - /* Used for first control ping */ - // TODO better names? - volatile u32 result_ready; - volatile i32 retval; - - /* JNI Native Method Interface pointer for message handlers */ - JNIEnv *jenv; - - /* thread cleanup */ - pthread_key_t cleanup_rx_thread_key; - - /* JNI Invoke Interface pointer for attachment of rx thread to java thread */ - JavaVM *jvm; - - /* Callback object and class references enabling asynchronous Java calls */ - jobject callback; - jclass callbackClass; - - /* Connected indication */ - volatile u8 is_connected; - - /* Convenience */ - unix_shared_memory_queue_t * vl_input_queue; - u32 my_client_index; - -} vppjni_main_t; - -vppjni_main_t vppjni_main __attribute__((aligned (64))); - -static inline u32 vppjni_get_context_id (vppjni_main_t * jm) -{ - return __sync_add_and_fetch (&jm->context_id, 1); -} - -static inline void vppjni_lock (vppjni_main_t * jm, u32 tag) -{ - while (__sync_lock_test_and_set (&jm->lock, 1)) - ; - jm->tag = tag; -} - -static inline void vppjni_unlock (vppjni_main_t * jm) -{ - jm->tag = 0; - CLIB_MEMORY_BARRIER(); - jm->lock = 0; -} - -static inline int vppjni_sanity_check (vppjni_main_t * jm) -{ - if (!jm->is_connected) - return VNET_API_ERROR_NOT_CONNECTED; - return 0; -} - -// TODO remove macros (code is now fully autogenerated) - -/* M: construct, but don't yet send a message */ -#define M(T,t) \ -do { \ - jm->result_ready = 0; \ - mp = vl_msg_api_alloc(sizeof(*mp)); \ - memset (mp, 0, sizeof (*mp)); \ - mp->_vl_msg_id = ntohs (VL_API_##T); \ - mp->client_index = jm->my_client_index; \ - } while(0); - -#define M2(T,t,n) \ -do { \ - jm->result_ready = 0; \ - mp = vl_msg_api_alloc(sizeof(*mp)+(n)); \ - memset (mp, 0, sizeof (*mp)); \ - mp->_vl_msg_id = ntohs (VL_API_##T); \ - mp->client_index = jm->my_client_index; \ - } while(0); - -/* S: send a message */ -#define S (vl_msg_api_send_shmem (jm->vl_input_queue, (u8 *)&mp)) - -#endif /* __included_vppjni_h__ */ diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/VppBaseCallException.java b/vpp-api/java/jvpp/org/openvpp/jvpp/VppBaseCallException.java deleted file mode 100644 index 792af2c6..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/VppBaseCallException.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openvpp.jvpp; - -/** - * Base exception representing failed operation of JVpp request call - */ -public abstract class VppBaseCallException extends Exception { - private final String methodName; - private final int errorCode; - - /** - * Constructs an VppCallbackException with the specified api method name and error code. - * - * @param methodName name of a method, which invocation or execution failed - * @param errorCode negative error code value associated with this failure - * @throws NullPointerException if apiMethodName is null - */ - public VppBaseCallException(final String methodName, final int errorCode) { - super(String.format("vppApi.%s failed with error code: %d", methodName, errorCode)); - this.methodName = java.util.Objects.requireNonNull(methodName, "apiMethodName is null!"); - this.errorCode = errorCode; - if(errorCode >= 0) { - throw new IllegalArgumentException("Error code must be < 0. Was " + errorCode + - " for " + methodName ); - } - } - - /** - * Returns name of a method, which invocation failed. - * - * @return method name - */ - public String getMethodName() { - return methodName; - } - - /** - * Returns the error code associated with this failure. - * - * @return a negative integer error code - */ - public int getErrorCode() { - return errorCode; - } -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/VppCallbackException.java b/vpp-api/java/jvpp/org/openvpp/jvpp/VppCallbackException.java deleted file mode 100644 index 3d2a1cb2..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/VppCallbackException.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openvpp.jvpp; - -/** - * Callback Exception representing failed operation of JVpp request call - */ -public class VppCallbackException extends VppBaseCallException { - private final int ctxId; - - /** - * Constructs an VppCallbackException with the specified api method name and error code. - * - * @param methodName name of a method, which invocation failed. - * @param ctxId api request context identifier - * @param errorCode negative error code value associated with this failure - * @throws NullPointerException if apiMethodName is null - */ - public VppCallbackException(final String methodName, final int ctxId, final int errorCode ){ - super(methodName, errorCode); - this.ctxId = ctxId; - } - - /** - * Returns api request context identifier. - * - * @return value of context identifier - */ - public int getCtxId() { - return ctxId; - } - -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/VppConnection.java b/vpp-api/java/jvpp/org/openvpp/jvpp/VppConnection.java deleted file mode 100644 index 19733985..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/VppConnection.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openvpp.jvpp; - -import java.io.IOException; - -/** - * Representation of a management connection to VPP. - * Connection is initiated when instance is created, closed with close(). - */ -public interface VppConnection extends AutoCloseable { - - /** - * Open VppConnection for communication with VPP - * - * @param callback instance handling responses - * - * @throws IOException if connection is not established - */ - void connect(final org.openvpp.jvpp.callback.JVppCallback callback) throws IOException; - - /** - * Check if this instance connection is active. - * - * @throws IllegalStateException if this instance was disconnected. - */ - void checkActive(); - - /** - * Closes Vpp connection. - */ - @Override - void close(); -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/VppInvocationException.java b/vpp-api/java/jvpp/org/openvpp/jvpp/VppInvocationException.java deleted file mode 100644 index 298bcd0a..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/VppInvocationException.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openvpp.jvpp; - -/** - * Exception thrown when Vpp jAPI method invocation failed. - */ -public class VppInvocationException extends VppBaseCallException { - /** - * Constructs an VppApiInvocationFailedException with the specified api method name and error code. - * - * @param methodName name of a method, which invocation failed. - * @param errorCode negative error code value associated with this failure - * @throws NullPointerException if apiMethodName is null - */ - public VppInvocationException(final String methodName, final int errorCode) { - super(methodName, errorCode); - } -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/VppJNIConnection.java b/vpp-api/java/jvpp/org/openvpp/jvpp/VppJNIConnection.java deleted file mode 100644 index 7401bcad..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/VppJNIConnection.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openvpp.jvpp; - -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.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.logging.Logger; -import org.openvpp.jvpp.callback.JVppCallback; - -/** - * JNI based representation of a management connection to VPP - */ -public final class VppJNIConnection implements VppConnection { - private final static Logger LOG = Logger.getLogger(VppJNIConnection.class.getName()); - private static final String LIBNAME = "libjvpp.so.0.0.0"; - - static { - try { - loadLibrary(); - } catch (Exception e) { - LOG.severe("Can't find vpp 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 = VppJNIConnection.class.getResourceAsStream('/' + LIBNAME)) { - if (is == null) { - throw new IOException("Failed to open library resource " + LIBNAME); - } - loadStream(is); - } - } - - private final String clientName; - private volatile boolean disconnected = false; - - /** - * Create VPPJNIConnection instance for client connecting to VPP. - * - * @param clientName client name instance to be used for communication. Single connection per clientName is allowed. - */ - public VppJNIConnection(final String clientName) { - this.clientName = Objects.requireNonNull(clientName,"Null clientName"); - } - - /** - * Guarded by VppJNIConnection.class - */ - private static final Map<String, VppJNIConnection> connections = new HashMap<>(); - - /** - * Initiate VPP connection for current instance - * - * Multiple instances are allowed since this class is not a singleton - * (VPP allows multiple management connections). - * - * However only a single connection per clientName is allowed. - * - * @param callback global callback to receive response calls from vpp - * - * @throws IOException in case the connection could not be established - */ - public void connect(final JVppCallback callback) throws IOException { - synchronized (VppJNIConnection.class) { - if(connections.containsKey(clientName)) { - throw new IOException("Client " + clientName + " already connected"); - } - - final int ret = clientConnect(clientName, callback); - if (ret != 0) { - throw new IOException("Connection returned error " + ret); - } - connections.put(clientName, this); - } - } - - @Override - public final void checkActive() { - if (disconnected) { - throw new IllegalStateException("Disconnected client " + clientName); - } - } - - @Override - public synchronized final void close() { - if (!disconnected) { - disconnected = true; - try { - clientDisconnect(); - } finally { - synchronized (VppJNIConnection.class) { - connections.remove(clientName); - } - } - } - } - - private static native int clientConnect(String clientName, JVppCallback callback); - private static native void clientDisconnect(); -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/callback/JVppCallback.java b/vpp-api/java/jvpp/org/openvpp/jvpp/callback/JVppCallback.java deleted file mode 100644 index f681e379..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/callback/JVppCallback.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openvpp.jvpp.callback; -import org.openvpp.jvpp.VppCallbackException; - -/** - * Base JVppCallback interface - */ -public interface JVppCallback { - /** - * onError callback handler used to report failing operation - * @param ex VppCallbackException object containing details about failing operation - */ - void onError(VppCallbackException ex); -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/callback/JVppNotificationCallback.java b/vpp-api/java/jvpp/org/openvpp/jvpp/callback/JVppNotificationCallback.java deleted file mode 100644 index 72a75c83..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/callback/JVppNotificationCallback.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openvpp.jvpp.callback; - -/** -* Notification callback -*/ -public interface JVppNotificationCallback { - -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppDump.java b/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppDump.java deleted file mode 100644 index 295bbba8..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppDump.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openvpp.jvpp.dto; - -/** -* Base interface for all dump requests -*/ -public interface JVppDump extends JVppRequest { - -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppNotification.java b/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppNotification.java deleted file mode 100644 index 7d0fecb7..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppNotification.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openvpp.jvpp.dto; - -/** -* Base interface for all notification DTOs -*/ -public interface JVppNotification { -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppReply.java b/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppReply.java deleted file mode 100644 index 2f4964c4..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppReply.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openvpp.jvpp.dto; - -/** -* Base interface for all reply DTOs -*/ -public interface JVppReply<REQ extends JVppRequest> { - -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppReplyDump.java b/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppReplyDump.java deleted file mode 100644 index 4aecedc1..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppReplyDump.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openvpp.jvpp.dto; - -/** -* Base interface for all dump replies -*/ -public interface JVppReplyDump<REQ extends JVppRequest, RESP extends JVppReply<REQ>> - extends JVppReply<REQ> { - -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppRequest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppRequest.java deleted file mode 100644 index 273e444f..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppRequest.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openvpp.jvpp.dto; - -import org.openvpp.jvpp.JVpp; -import org.openvpp.jvpp.VppInvocationException; - -/** -* Base interface for all request DTOs -*/ -public interface JVppRequest { - - /** - * Invoke current operation asynchronously on VPP - * - * @return context id of this request. Can be used to track incomming response - */ - int send(JVpp jvpp) throws VppInvocationException; - -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppInvoker.java b/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppInvoker.java deleted file mode 100644 index 1683bd75..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppInvoker.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openvpp.jvpp.future; - - -import org.openvpp.jvpp.dto.JVppReply; -import org.openvpp.jvpp.dto.JVppRequest; - -import java.util.concurrent.CompletionStage; -import org.openvpp.jvpp.notification.NotificationRegistryProvider; - -/** -* Future facade on top of JVpp -*/ -public interface FutureJVppInvoker extends NotificationRegistryProvider, AutoCloseable { - - /** - * Invoke asynchronous operation on VPP - * - * @return CompletionStage with future result of an async VPP call - * @throws org.openvpp.jvpp.VppInvocationException when send request failed with details - */ - <REQ extends JVppRequest, REPLY extends JVppReply<REQ>> CompletionStage<REPLY> send(REQ req); - -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppInvokerFacade.java b/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppInvokerFacade.java deleted file mode 100644 index a60e1b28..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppInvokerFacade.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openvpp.jvpp.future; - - -import org.openvpp.jvpp.JVpp; -import org.openvpp.jvpp.VppInvocationException; -import org.openvpp.jvpp.dto.*; - -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import org.openvpp.jvpp.notification.NotificationRegistryProviderContext; - -/** -* Future facade on top of JVpp -*/ -public class FutureJVppInvokerFacade extends NotificationRegistryProviderContext implements FutureJVppInvoker { - - private final JVpp jvpp; - - /** - * Guarded by self - */ - private final Map<Integer, CompletableFuture<? extends JVppReply<?>>> requests; - - public FutureJVppInvokerFacade(final JVpp jvpp, - final Map<Integer, CompletableFuture<? extends JVppReply<?>>> requestMap) { - this.jvpp = Objects.requireNonNull(jvpp, "Null jvpp"); - // Request map represents the shared state between this facade and it's callback - // where facade puts futures in and callback completes + removes them - // TODO what if the call never completes ? - this.requests = Objects.requireNonNull(requestMap, "Null requestMap"); - } - - protected final Map<Integer, CompletableFuture<? extends JVppReply<?>>> getRequests() { - return this.requests; - } - - // TODO use Optional in Future, java8 - - @Override - @SuppressWarnings("unchecked") - public <REQ extends JVppRequest, REPLY extends JVppReply<REQ>> CompletionStage<REPLY> send(REQ req) { - synchronized(requests) { - try { - final CompletableFuture<REPLY> replyCompletableFuture; - final int contextId = jvpp.send(req); - - if(req instanceof JVppDump) { - replyCompletableFuture = (CompletableFuture<REPLY>) new CompletableDumpFuture<>(contextId); - } else { - replyCompletableFuture = new CompletableFuture<>(); - } - - requests.put(contextId, replyCompletableFuture); - if(req instanceof JVppDump) { - requests.put(jvpp.send(new ControlPing()), replyCompletableFuture); - } - return replyCompletableFuture; - } catch (VppInvocationException ex) { - final CompletableFuture<REPLY> replyCompletableFuture = new CompletableFuture<>(); - replyCompletableFuture.completeExceptionally(ex); - return replyCompletableFuture; - } - } - } - - static final class CompletableDumpFuture<T extends JVppReplyDump<?, ?>> extends CompletableFuture<T> { - // The reason why this is not final is the instantiation of ReplyDump DTOs - // Their instantiation must be generated, so currently the DTOs are created in callback and set when first dump reponses - // is handled in the callback. - private T replyDump; - private final long contextId; - - CompletableDumpFuture(final long contextId) { - this.contextId = contextId; - } - - long getContextId() { - return contextId; - } - - T getReplyDump() { - return replyDump; - } - - void setReplyDump(final T replyDump) { - this.replyDump = replyDump; - } - } - - @Override - public void close() throws Exception { - // NOOP - } -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/notification/NotificationRegistryProvider.java b/vpp-api/java/jvpp/org/openvpp/jvpp/notification/NotificationRegistryProvider.java deleted file mode 100644 index 50b72be5..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/notification/NotificationRegistryProvider.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.openvpp.jvpp.notification; - -/** - * Provides notification registry - */ -public interface NotificationRegistryProvider { - - /** - * Get current notification registry instance - */ - NotificationRegistry getNotificationRegistry(); -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/notification/NotificationRegistryProviderContext.java b/vpp-api/java/jvpp/org/openvpp/jvpp/notification/NotificationRegistryProviderContext.java deleted file mode 100644 index 8e703812..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/notification/NotificationRegistryProviderContext.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.openvpp.jvpp.notification; - -/** - * Base class for notification aware JVpp facades - */ -public abstract class NotificationRegistryProviderContext implements NotificationRegistryProvider { - - private final NotificationRegistryImpl notificationRegistry = new NotificationRegistryImpl(); - - public final NotificationRegistry getNotificationRegistry() { - return notificationRegistry; - } - - /** - * Get instance of notification callback. Can be used to propagate notifications from JVpp facade - */ - protected final GlobalNotificationCallback getNotificationCallback() { - return notificationRegistry; - } -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackApiTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackApiTest.java deleted file mode 100644 index 8c976db2..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackApiTest.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openvpp.jvpp.test; - -import org.openvpp.jvpp.JVpp; -import org.openvpp.jvpp.JVppImpl; -import org.openvpp.jvpp.VppCallbackException; -import org.openvpp.jvpp.VppJNIConnection; -import org.openvpp.jvpp.callback.GetNodeIndexCallback; -import org.openvpp.jvpp.callback.ShowVersionCallback; -import org.openvpp.jvpp.callback.SwInterfaceCallback; -import org.openvpp.jvpp.dto.*; - -public class CallbackApiTest { - - private static class TestCallback implements GetNodeIndexCallback, ShowVersionCallback, SwInterfaceCallback { - - @Override - public void onGetNodeIndexReply(final GetNodeIndexReply msg) { - System.out.printf("Received GetNodeIndexReply: context=%d, nodeIndex=%d\n", - msg.context, msg.nodeIndex); - } - @Override - public void onShowVersionReply(final ShowVersionReply msg) { - System.out.printf("Received ShowVersionReply: context=%d, program=%s, version=%s, " + - "buildDate=%s, buildDirectory=%s\n", - msg.context, new String(msg.program), new String(msg.version), - new String(msg.buildDate), new String(msg.buildDirectory)); - } - - @Override - public void onSwInterfaceDetails(final SwInterfaceDetails msg) { - System.out.printf("Received SwInterfaceDetails: interfaceName=%s, l2AddressLength=%d, adminUpDown=%d, " + - "linkUpDown=%d, linkSpeed=%d, linkMtu=%d\n", - new String(msg.interfaceName), msg.l2AddressLength, msg.adminUpDown, - msg.linkUpDown, msg.linkSpeed, (int)msg.linkMtu); - } - - @Override - public void onError(VppCallbackException ex) { - System.out.printf("Received onError exception: call=%s, context=%d, retval=%d\n", ex.getMethodName(), ex.getCtxId(), ex.getErrorCode()); - } - } - - private static void testCallbackApi() throws Exception { - System.out.println("Testing Java callback API"); - JVpp jvpp = new JVppImpl(new VppJNIConnection("CallbackApiTest")); - jvpp.connect(new TestCallback()); - System.out.println("Successfully connected to VPP"); - - System.out.println("Sending ShowVersion request..."); - jvpp.send(new ShowVersion()); - - System.out.println("Sending GetNodeIndex request..."); - GetNodeIndex getNodeIndexRequest = new GetNodeIndex(); - getNodeIndexRequest.nodeName = "node0".getBytes(); - jvpp.send(getNodeIndexRequest); - - System.out.println("Sending SwInterfaceDump request..."); - SwInterfaceDump swInterfaceDumpRequest = new SwInterfaceDump(); - swInterfaceDumpRequest.nameFilterValid = 0; - swInterfaceDumpRequest.nameFilter = "".getBytes(); - jvpp.send(swInterfaceDumpRequest); - - Thread.sleep(5000); - - System.out.println("Disconnecting..."); - jvpp.close(); - Thread.sleep(1000); - } - - public static void main(String[] args) throws Exception { - testCallbackApi(); - } -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackJVppFacadeNotificationTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackJVppFacadeNotificationTest.java deleted file mode 100644 index 430ce881..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackJVppFacadeNotificationTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openvpp.jvpp.test; - -import org.openvpp.jvpp.JVpp; -import org.openvpp.jvpp.JVppImpl; -import org.openvpp.jvpp.VppCallbackException; -import org.openvpp.jvpp.VppJNIConnection; -import org.openvpp.jvpp.callback.WantInterfaceEventsCallback; -import org.openvpp.jvpp.callfacade.CallbackJVppFacade; -import org.openvpp.jvpp.dto.WantInterfaceEventsReply; - -public class CallbackJVppFacadeNotificationTest { - - private static void testCallbackFacade() throws Exception { - System.out.println("Testing CallbackJVppFacade for notifications"); - - JVpp jvpp = new JVppImpl(new VppJNIConnection("CallbackApiTest")); - - CallbackJVppFacade jvppCallbackFacade = new CallbackJVppFacade(jvpp); - System.out.println("Successfully connected to VPP"); - - final AutoCloseable notificationListenerReg = - jvppCallbackFacade.getNotificationRegistry().registerSwInterfaceSetFlagsNotificationCallback( - NotificationUtils::printNotification - ); - - jvppCallbackFacade.wantInterfaceEvents(NotificationUtils.getEnableInterfaceNotificationsReq(), - new WantInterfaceEventsCallback() { - @Override - public void onWantInterfaceEventsReply(final WantInterfaceEventsReply reply) { - System.out.println("Interface events started"); - } - - @Override - public void onError(final VppCallbackException ex) { - System.out.printf("Received onError exception: call=%s, context=%d, retval=%d\n", - ex.getMethodName(), ex.getCtxId(), ex.getErrorCode()); - } - }); - - System.out.println("Changing interface configuration"); - NotificationUtils.getChangeInterfaceState().send(jvpp); - - Thread.sleep(1000); - - jvppCallbackFacade.wantInterfaceEvents(NotificationUtils.getDisableInterfaceNotificationsReq(), - new WantInterfaceEventsCallback() { - @Override - public void onWantInterfaceEventsReply(final WantInterfaceEventsReply reply) { - System.out.println("Interface events stopped"); - } - - @Override - public void onError(final VppCallbackException ex) { - System.out.printf("Received onError exception: call=%s, context=%d, retval=%d\n", - ex.getMethodName(), ex.getCtxId(), ex.getErrorCode()); - } - }); - - notificationListenerReg.close(); - - Thread.sleep(2000); - - System.out.println("Disconnecting..."); - jvpp.close(); - Thread.sleep(1000); - } - - public static void main(String[] args) throws Exception { - testCallbackFacade(); - } -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackJVppFacadeTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackJVppFacadeTest.java deleted file mode 100644 index bb06c761..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackJVppFacadeTest.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openvpp.jvpp.test; - -import org.openvpp.jvpp.JVpp; -import org.openvpp.jvpp.JVppImpl; -import org.openvpp.jvpp.VppCallbackException; -import org.openvpp.jvpp.VppJNIConnection; -import org.openvpp.jvpp.callback.GetNodeIndexCallback; -import org.openvpp.jvpp.callback.ShowVersionCallback; -import org.openvpp.jvpp.callfacade.CallbackJVppFacade; -import org.openvpp.jvpp.dto.GetNodeIndex; -import org.openvpp.jvpp.dto.GetNodeIndexReply; -import org.openvpp.jvpp.dto.ShowVersionReply; - -/** - * CallbackJVppFacade together with CallbackJVppFacadeCallback allow for setting different callback for each request. - * This is more convenient than the approach shown in CallbackApiTest. - */ -public class CallbackJVppFacadeTest { - - private static ShowVersionCallback showVersionCallback1; - private static ShowVersionCallback showVersionCallback2; - private static GetNodeIndexCallback getNodeIndexCallback; - - static { - getNodeIndexCallback = new GetNodeIndexCallback() { - @Override - public void onGetNodeIndexReply(final GetNodeIndexReply msg) { - System.out.printf("Received GetNodeIndexReply: context=%d, nodeIndex=%d\n", - msg.context, msg.nodeIndex); - } - - @Override - public void onError(VppCallbackException ex) { - System.out.printf("Received onError exception in getNodeIndexCallback: call=%s, reply=%d, context=%d\n", ex.getMethodName(), ex.getErrorCode(), ex.getCtxId()); - } - }; - showVersionCallback2 = new ShowVersionCallback() { - @Override - public void onShowVersionReply(final ShowVersionReply msg) { - System.out.printf("ShowVersionCallback1 received ShowVersionReply: context=%d, program=%s," + - "version=%s, buildDate=%s, buildDirectory=%s\n", msg.context, new String(msg.program), - new String(msg.version), new String(msg.buildDate), new String(msg.buildDirectory)); - } - - @Override - public void onError(VppCallbackException ex) { - System.out.printf("Received onError exception in showVersionCallback2: call=%s, reply=%d, context=%d\n", ex.getMethodName(), ex.getErrorCode(), ex.getCtxId()); - } - - }; - showVersionCallback1 = new ShowVersionCallback() { - @Override - public void onShowVersionReply(final ShowVersionReply msg) { - System.out.printf("ShowVersionCallback1 received ShowVersionReply: context=%d, program=%s," + - "version=%s, buildDate=%s, buildDirectory=%s\n", msg.context, new String(msg.program), - new String(msg.version), new String(msg.buildDate), new String(msg.buildDirectory)); - } - - @Override - public void onError(VppCallbackException ex) { - System.out.printf("Received onError exception in showVersionCallback1: call=%s, reply=%d, context=%d\n", ex.getMethodName(), ex.getErrorCode(), ex.getCtxId()); - } - }; - } - - private static void testCallbackFacade() throws Exception { - System.out.println("Testing CallbackJVppFacade"); - - JVpp jvpp = new JVppImpl(new VppJNIConnection("CallbackApiTest")); - - CallbackJVppFacade jvppCallbackFacade = new CallbackJVppFacade(jvpp); - System.out.println("Successfully connected to VPP"); - - jvppCallbackFacade.showVersion(showVersionCallback1); - jvppCallbackFacade.showVersion(showVersionCallback2); - - GetNodeIndex getNodeIndexRequest = new GetNodeIndex(); - getNodeIndexRequest.nodeName = "dummyNode".getBytes(); - jvppCallbackFacade.getNodeIndex(getNodeIndexRequest, getNodeIndexCallback); - - Thread.sleep(2000); - - System.out.println("Disconnecting..."); - jvpp.close(); - Thread.sleep(1000); - } - - public static void main(String[] args) throws Exception { - testCallbackFacade(); - } -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackNotificationApiTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackNotificationApiTest.java deleted file mode 100644 index 5bf2b212..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackNotificationApiTest.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openvpp.jvpp.test; - -import static org.openvpp.jvpp.test.NotificationUtils.getChangeInterfaceState; -import static org.openvpp.jvpp.test.NotificationUtils.getDisableInterfaceNotificationsReq; -import static org.openvpp.jvpp.test.NotificationUtils.getEnableInterfaceNotificationsReq; -import static org.openvpp.jvpp.test.NotificationUtils.printNotification; - -import org.openvpp.jvpp.JVpp; -import org.openvpp.jvpp.JVppImpl; -import org.openvpp.jvpp.VppCallbackException; -import org.openvpp.jvpp.VppJNIConnection; -import org.openvpp.jvpp.callback.SwInterfaceSetFlagsCallback; -import org.openvpp.jvpp.callback.SwInterfaceSetFlagsNotificationCallback; -import org.openvpp.jvpp.callback.WantInterfaceEventsCallback; -import org.openvpp.jvpp.dto.SwInterfaceSetFlagsNotification; -import org.openvpp.jvpp.dto.SwInterfaceSetFlagsReply; -import org.openvpp.jvpp.dto.WantInterfaceEventsReply; - -public class CallbackNotificationApiTest { - - private static class TestCallback implements SwInterfaceSetFlagsNotificationCallback, - WantInterfaceEventsCallback, SwInterfaceSetFlagsCallback { - - @Override - public void onSwInterfaceSetFlagsNotification( - final SwInterfaceSetFlagsNotification msg) { - printNotification(msg); - } - - @Override - public void onWantInterfaceEventsReply(final WantInterfaceEventsReply wantInterfaceEventsReply) { - System.out.println("Interface notification stream updated"); - } - - @Override - public void onSwInterfaceSetFlagsReply(final SwInterfaceSetFlagsReply swInterfaceSetFlagsReply) { - System.out.println("Interface flags set successfully"); - } - - @Override - public void onError(VppCallbackException ex) { - System.out.printf("Received onError exception in getNodeIndexCallback: call=%s, reply=%d, context=%d\n", - ex.getMethodName(), ex.getErrorCode(), ex.getCtxId()); - - } - } - - private static void testCallbackApi() throws Exception { - System.out.println("Testing Java callback API for notifications"); - JVpp jvpp = new JVppImpl( new VppJNIConnection("CallbackApiTest")); - jvpp.connect( new TestCallback()); - System.out.println("Successfully connected to VPP"); - - getEnableInterfaceNotificationsReq().send(jvpp); - System.out.println("Interface notifications started"); - // TODO test ifc dump which also triggers interface flags send - - System.out.println("Changing interface configuration"); - getChangeInterfaceState().send(jvpp); - - // Notification is received - Thread.sleep(500); - - getDisableInterfaceNotificationsReq().send(jvpp); - System.out.println("Interface events stopped"); - - Thread.sleep(2000); - - System.out.println("Disconnecting..."); - jvpp.close(); - Thread.sleep(1000); - } - - public static void main(String[] args) throws Exception { - testCallbackApi(); - } -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/ControlPingTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/ControlPingTest.java deleted file mode 100644 index 514bb3ef..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/test/ControlPingTest.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openvpp.jvpp.test; - -import org.openvpp.jvpp.JVpp; -import org.openvpp.jvpp.JVppImpl; -import org.openvpp.jvpp.VppCallbackException; -import org.openvpp.jvpp.VppJNIConnection; -import org.openvpp.jvpp.callback.ControlPingCallback; -import org.openvpp.jvpp.dto.ControlPing; -import org.openvpp.jvpp.dto.ControlPingReply; - -public class ControlPingTest { - - private static void testControlPing() throws Exception { - System.out.println("Testing ControlPing using Java callback API"); - - JVpp jvpp = new JVppImpl( new VppJNIConnection("ControlPingTest")); - jvpp.connect( new ControlPingCallback() { - @Override - public void onControlPingReply(final ControlPingReply reply) { - System.out.printf("Received ControlPingReply: context=%d, clientIndex=%d vpePid=%d\n", - reply.context, reply.clientIndex, reply.vpePid); - } - - @Override - public void onError(VppCallbackException ex) { - System.out.printf("Received onError exception: call=%s, reply=%d, context=%d ", ex.getMethodName(), ex.getErrorCode(), ex.getCtxId()); - } - - }); - System.out.println("Successfully connected to VPP"); - Thread.sleep(1000); - - jvpp.send(new ControlPing()); - - Thread.sleep(2000); - - System.out.println("Disconnecting..."); - jvpp.close(); - Thread.sleep(1000); - } - - public static void main(String[] args) throws Exception { - testControlPing(); - } -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/CreateSubInterfaceTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/CreateSubInterfaceTest.java deleted file mode 100644 index b3dc1f49..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/test/CreateSubInterfaceTest.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openvpp.jvpp.test; - -import org.openvpp.jvpp.JVppImpl; -import org.openvpp.jvpp.VppJNIConnection; -import org.openvpp.jvpp.dto.CreateSubif; -import org.openvpp.jvpp.dto.CreateSubifReply; -import org.openvpp.jvpp.dto.SwInterfaceDetailsReplyDump; -import org.openvpp.jvpp.dto.SwInterfaceDump; -import org.openvpp.jvpp.future.FutureJVppFacade; - -import static java.util.Objects.requireNonNull; - -/** - * <p>Tests sub-interface creation.<br> Equivalent to:<br> - * - * <pre>{@code - * vppctl create sub GigabitEthernet0/9/0 1 dot1q 100 inner-dot1q any - * } - * </pre> - * - * To verify invoke:<br> - * <pre>{@code - * vpp_api_test json - * vat# sw_interface_dump - * } - */ -public class CreateSubInterfaceTest { - - - private static SwInterfaceDump createSwInterfaceDumpRequest(final String ifaceName) { - SwInterfaceDump request = new SwInterfaceDump(); - request.nameFilter = ifaceName.getBytes(); - request.nameFilterValid = 1; - return request; - } - - private static void requireSingleIface(final SwInterfaceDetailsReplyDump response, final String ifaceName) { - if (response.swInterfaceDetails.size() != 1) { - throw new IllegalStateException( - String.format("Expected one interface matching filter %s but was %d", ifaceName, - response.swInterfaceDetails.size())); - } - } - - private static CreateSubif createSubifRequest(final int swIfIndex, final int subId) { - CreateSubif request = new CreateSubif(); - request.swIfIndex = swIfIndex; // super interface id - request.subId = subId; - request.noTags = 0; - request.oneTag = 0; - request.twoTags = 1; - request.dot1Ad = 0; - request.exactMatch = 1; - request.defaultSub = 0; - request.outerVlanIdAny = 0; - request.innerVlanIdAny = 1; - request.outerVlanId = 100; - request.innerVlanId = 0; - return request; - } - - private static void print(CreateSubifReply reply) { - System.out.printf("CreateSubifReply: context=%d, swIfIndex=%d\n", - reply.context, - reply.swIfIndex); - } - - private static void testCreateSubInterface() throws Exception { - System.out.println("Testing sub-interface creation using Java callback API"); - final JVppImpl jvpp = new JVppImpl(new VppJNIConnection("SubIfaceTest")); - final FutureJVppFacade jvppFacade = new FutureJVppFacade(jvpp); - - System.out.println("Successfully connected to VPP"); - Thread.sleep(1000); - - final String ifaceName = "GigabitEthernet0/9/0"; - - final SwInterfaceDetailsReplyDump swInterfaceDetails = - jvppFacade.swInterfaceDump(createSwInterfaceDumpRequest(ifaceName)).toCompletableFuture().get(); - - requireNonNull(swInterfaceDetails, "swInterfaceDump returned null"); - requireNonNull(swInterfaceDetails.swInterfaceDetails, "swInterfaceDetails is null"); - requireSingleIface(swInterfaceDetails, ifaceName); - - final int swIfIndex = swInterfaceDetails.swInterfaceDetails.get(0).swIfIndex; - final int subId = 1; - - final CreateSubifReply createSubifReply = - jvppFacade.createSubif(createSubifRequest(swIfIndex, subId)).toCompletableFuture().get(); - print(createSubifReply); - - final String subIfaceName = "GigabitEthernet0/9/0." + subId; - final SwInterfaceDetailsReplyDump subIface = - jvppFacade.swInterfaceDump(createSwInterfaceDumpRequest(subIfaceName)).toCompletableFuture().get(); - requireNonNull(swInterfaceDetails, "swInterfaceDump returned null"); - requireNonNull(subIface.swInterfaceDetails, "swInterfaceDump returned null"); - requireSingleIface(swInterfaceDetails, ifaceName); - - System.out.println("Disconnecting..."); - jvpp.close(); - Thread.sleep(1000); - } - - public static void main(String[] args) throws Exception { - testCreateSubInterface(); - } -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/FutureApiNotificationTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/FutureApiNotificationTest.java deleted file mode 100644 index c48f86d4..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/test/FutureApiNotificationTest.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openvpp.jvpp.test; - -import static org.openvpp.jvpp.test.NotificationUtils.getChangeInterfaceState; -import static org.openvpp.jvpp.test.NotificationUtils.getDisableInterfaceNotificationsReq; -import static org.openvpp.jvpp.test.NotificationUtils.getEnableInterfaceNotificationsReq; - -import org.openvpp.jvpp.VppJNIConnection; -import org.openvpp.jvpp.future.FutureJVppFacade; - -public class FutureApiNotificationTest { - - private static void testFutureApi() throws Exception { - System.out.println("Testing Java future API for notifications"); - - final org.openvpp.jvpp.JVppImpl impl = - new org.openvpp.jvpp.JVppImpl(new VppJNIConnection("FutureApiTest")); - final FutureJVppFacade jvppFacade = new FutureJVppFacade(impl); - System.out.println("Successfully connected to VPP"); - - final AutoCloseable notificationListenerReg = - jvppFacade.getNotificationRegistry().registerSwInterfaceSetFlagsNotificationCallback(NotificationUtils::printNotification); - - jvppFacade.wantInterfaceEvents(getEnableInterfaceNotificationsReq()).toCompletableFuture().get(); - System.out.println("Interface events started"); - - System.out.println("Changing interface configuration"); - jvppFacade.swInterfaceSetFlags(getChangeInterfaceState()).toCompletableFuture().get(); - - Thread.sleep(1000); - - jvppFacade.wantInterfaceEvents(getDisableInterfaceNotificationsReq()).toCompletableFuture().get(); - System.out.println("Interface events stopped"); - - notificationListenerReg.close(); - - System.out.println("Disconnecting..."); - // TODO we should consider adding jvpp.close(); to the facade - impl.close(); - } - - public static void main(String[] args) throws Exception { - testFutureApi(); - } -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/FutureApiTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/FutureApiTest.java deleted file mode 100644 index 0000bcd9..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/test/FutureApiTest.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openvpp.jvpp.test; - -import org.openvpp.jvpp.VppJNIConnection; -import org.openvpp.jvpp.dto.*; -import org.openvpp.jvpp.future.FutureJVppFacade; - -import java.util.Objects; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; - -public class FutureApiTest { - - private static void testShowVersion(final FutureJVppFacade jvpp) { - System.out.println("Sending ShowVersion request..."); - try { - Objects.requireNonNull(jvpp,"jvpp is null"); - final Future<ShowVersionReply> replyFuture = jvpp.showVersion(new ShowVersion()).toCompletableFuture(); - Objects.requireNonNull(replyFuture,"replyFuture is null"); - final ShowVersionReply reply = replyFuture.get(); - Objects.requireNonNull(reply,"reply is null"); - System.out.printf("Received ShowVersionReply: context=%d, program=%s, " + - "version=%s, buildDate=%s, buildDirectory=%s\n", - reply.context, new String(reply.program), new String(reply.version), - new String(reply.buildDate), new String(reply.buildDirectory)); - } catch (Exception e) { - System.err.printf("ShowVersion request failed:"+e.getCause()); - e.printStackTrace(); - } - } - - /** - * This test will fail with some error code if node 'node0' is not defined. - * TODO: consider adding error messages specific for given api calls - */ - private static void testGetNodeIndex(final FutureJVppFacade jvpp) { - System.out.println("Sending GetNodeIndex request..."); - try { - Objects.requireNonNull(jvpp,"jvpp is null"); - final GetNodeIndex request = new GetNodeIndex(); - request.nodeName = "node0".getBytes(); - final Future<GetNodeIndexReply> replyFuture = jvpp.getNodeIndex(request).toCompletableFuture(); - Objects.requireNonNull(replyFuture,"replyFuture is null"); - final GetNodeIndexReply reply = replyFuture.get(); - Objects.requireNonNull(reply,"reply is null"); - System.out.printf("Received GetNodeIndexReply: context=%d, nodeIndex=%d\n", - reply.context, reply.nodeIndex); - } catch (ExecutionException e) { - System.err.printf("GetNodeIndex request failed:"+e.getCause()); - } catch (Exception e) { - System.err.printf("GetNodeIndex request failed:"+e.getCause()); - e.printStackTrace(); - } - } - - private static void testSwInterfaceDump(final FutureJVppFacade jvpp) { - System.out.println("Sending SwInterfaceDump request..."); - try { - Objects.requireNonNull(jvpp,"SwInterfaceDetailsReplyDump is null!"); - final SwInterfaceDump request = new SwInterfaceDump(); - request.nameFilterValid = 0; - request.nameFilter = "".getBytes(); - final Future<SwInterfaceDetailsReplyDump> replyFuture = jvpp.swInterfaceDump(request).toCompletableFuture(); - Objects.requireNonNull(replyFuture,"replyFuture is null"); - final SwInterfaceDetailsReplyDump reply = replyFuture.get(); - Objects.requireNonNull(reply.swInterfaceDetails, "SwInterfaceDetailsReplyDump.swInterfaceDetails is null!"); - for (SwInterfaceDetails details : reply.swInterfaceDetails) { - Objects.requireNonNull(details, "reply.swInterfaceDetails contains null element!"); - System.out.printf("Received SwInterfaceDetails: interfaceName=%s, l2AddressLength=%d, adminUpDown=%d, " + - "linkUpDown=%d, linkSpeed=%d, linkMtu=%d\n", - new String(details.interfaceName), details.l2AddressLength, details.adminUpDown, - details.linkUpDown, details.linkSpeed, (int) details.linkMtu); - } - } catch(NullPointerException e) { - throw new IllegalStateException(e.getMessage()); - } catch (Exception e) { - System.err.printf("SwInterfaceDump request failed:"+e.getCause()); - e.printStackTrace(); - } - } - - private static void testFutureApi() throws Exception { - System.out.println("Testing Java future API"); - - final org.openvpp.jvpp.JVppImpl impl = - new org.openvpp.jvpp.JVppImpl(new VppJNIConnection("FutureApiTest")); - final FutureJVppFacade jvppFacade = new FutureJVppFacade(impl); - System.out.println("Successfully connected to VPP"); - testShowVersion(jvppFacade); - testGetNodeIndex(jvppFacade); - testSwInterfaceDump(jvppFacade); - - System.out.println("Disconnecting..."); - // TODO we should consider adding jvpp.close(); to the facade - impl.close(); - } - - public static void main(String[] args) throws Exception { - testFutureApi(); - } -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/L2AclTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/L2AclTest.java deleted file mode 100644 index 802df631..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/test/L2AclTest.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openvpp.jvpp.test; - -import java.util.Arrays; -import javax.xml.bind.DatatypeConverter; -import org.openvpp.jvpp.JVppImpl; -import org.openvpp.jvpp.VppJNIConnection; -import org.openvpp.jvpp.dto.ClassifyAddDelSession; -import org.openvpp.jvpp.dto.ClassifyAddDelSessionReply; -import org.openvpp.jvpp.dto.ClassifyAddDelTable; -import org.openvpp.jvpp.dto.ClassifyAddDelTableReply; -import org.openvpp.jvpp.dto.ClassifySessionDetails; -import org.openvpp.jvpp.dto.ClassifySessionDetailsReplyDump; -import org.openvpp.jvpp.dto.ClassifySessionDump; -import org.openvpp.jvpp.dto.ClassifyTableByInterface; -import org.openvpp.jvpp.dto.ClassifyTableByInterfaceReply; -import org.openvpp.jvpp.dto.ClassifyTableIds; -import org.openvpp.jvpp.dto.ClassifyTableIdsReply; -import org.openvpp.jvpp.dto.ClassifyTableInfo; -import org.openvpp.jvpp.dto.ClassifyTableInfoReply; -import org.openvpp.jvpp.dto.InputAclSetInterface; -import org.openvpp.jvpp.dto.InputAclSetInterfaceReply; -import org.openvpp.jvpp.future.FutureJVppFacade; - -/** - * <p>Tests L2 ACL creation and read.<br> Equivalent to the following vppctl commands:<br> - * - * <pre>{@code - * vppctl classify table mask l2 src - * vppctl classify session acl-hit-next deny opaque-index 0 table-index 0 match l2 src 01:02:03:04:05:06 - * vppctl set int input acl intfc local0 l2-table 0 - * vppctl sh class table verbose - * } - * </pre> - */ -public class L2AclTest { - - private static final int LOCAL0_IFACE_ID = 0; - - private static ClassifyAddDelTable createClassifyTable() { - ClassifyAddDelTable request = new ClassifyAddDelTable(); - request.isAdd = 1; - request.tableIndex = ~0; // default - request.nbuckets = 2; - request.memorySize = 2 << 20; - request.nextTableIndex = ~0; // default - request.missNextIndex = ~0; // default - request.skipNVectors = 0; - request.matchNVectors = 1; - request.mask = - new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, 0x00, 0x00, 0x00, 0x00}; - return request; - } - - private static ClassifyTableInfo createClassifyTableInfoRequest(final int tableId) { - ClassifyTableInfo request = new ClassifyTableInfo(); - request.tableId = tableId; - return request; - } - - private static ClassifyAddDelSession createClassifySession(final int tableIndex) { - ClassifyAddDelSession request = new ClassifyAddDelSession(); - request.isAdd = 1; - request.tableIndex = tableIndex; - request.hitNextIndex = 0; // deny - request.opaqueIndex = 0; - request.advance = 0; // default - // match 01:02:03:04:05:06 mac address - request.match = - new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04, - (byte) 0x05, (byte) 0x06, 0x00, 0x00, 0x00, 0x00}; - return request; - } - - private static ClassifySessionDump createClassifySessionDumpRequest(final int newTableIndex) { - ClassifySessionDump request = new ClassifySessionDump(); - request.tableId = newTableIndex; - return request; - } - - private static InputAclSetInterface aclSetInterface() { - InputAclSetInterface request = new InputAclSetInterface(); - request.isAdd = 1; - request.swIfIndex = LOCAL0_IFACE_ID; - request.ip4TableIndex = ~0; // skip - request.ip6TableIndex = ~0; // skip - request.l2TableIndex = 0; - return request; - } - - private static ClassifyTableByInterface createClassifyTableByInterfaceRequest() { - ClassifyTableByInterface request = new ClassifyTableByInterface(); - request.swIfIndex = LOCAL0_IFACE_ID; - return request; - } - - private static void print(ClassifyAddDelTableReply reply) { - System.out.printf("ClassifyAddDelTableReply: context=%d, " + - "newTableIndex=%d, skipNVectors=%d, matchNVectors=%d\n", - reply.context, reply.newTableIndex, reply.skipNVectors, reply.matchNVectors); - } - - private static void print(ClassifyTableIdsReply reply) { - System.out.printf("ClassifyTableIdsReply: context=%d, count=%d, ids.length=%d\n", - reply.context, reply.count, reply.ids.length); - Arrays.stream(reply.ids).forEach(System.out::println); - } - - private static void print(final ClassifyTableInfoReply reply) { - final StringBuilder builder = new StringBuilder("ClassifyTableInfoReply:\n"); - builder.append("context: ").append(reply.context).append('\n'); - builder.append("tableId: ").append(reply.tableId).append('\n'); - builder.append("nbuckets: ").append(reply.nbuckets).append('\n'); - builder.append("matchNVectors: ").append(reply.matchNVectors).append('\n'); - builder.append("skipNVectors: ").append(reply.skipNVectors).append('\n'); - builder.append("activeSessions: ").append(reply.activeSessions).append('\n'); - builder.append("nextTableIndex: ").append(reply.nextTableIndex).append('\n'); - builder.append("missNextIndex: ").append(reply.missNextIndex).append('\n'); - builder.append("maskLength: ").append(reply.maskLength).append('\n'); - builder.append("mask: ").append(DatatypeConverter.printHexBinary(reply.mask)).append('\n'); - System.out.println(builder.toString()); - } - - private static void print(ClassifyAddDelSessionReply reply) { - System.out.printf("ClassifyAddDelSessionReply: context=%d\n", - reply.context); - } - - private static void print(final ClassifySessionDetailsReplyDump reply) { - if (reply.classifySessionDetails == null) { - System.out.println("ClassifySessionDetailsReplyDump: classifySessionDetails == NULL"); - } - for (final ClassifySessionDetails details : reply.classifySessionDetails) { - final StringBuilder builder = new StringBuilder("ClassifySessionDetails:\n"); - builder.append("context: ").append(details.context).append('\n'); - builder.append("tableId: ").append(details.tableId).append('\n'); - builder.append("hitNextIndex: ").append(details.hitNextIndex).append('\n'); - builder.append("advance: ").append(details.advance).append('\n'); - builder.append("opaqueIndex: ").append(details.opaqueIndex).append('\n'); - builder.append("matchLength: ").append(details.matchLength).append('\n'); - builder.append("match: ").append(DatatypeConverter.printHexBinary(details.match)).append('\n'); - System.out.println(builder.toString()); - } - } - - private static void print(final InputAclSetInterfaceReply reply) { - System.out.printf("InputAclSetInterfaceReply: context=%d\n", reply.context); - } - - private static void print(final ClassifyTableByInterfaceReply reply) { - System.out.printf("ClassifyAddDelTableReply: context=%d, swIfIndex=%d, l2TableId=%d, ip4TableId=%d," + - "ip6TableId=%d\n", reply.context, reply.swIfIndex, reply.l2TableId, reply.ip4TableId, reply.ip6TableId); - } - - private static void testL2Acl() throws Exception { - System.out.println("Testing L2 ACLs using Java callback API"); - final JVppImpl jvpp = new JVppImpl(new VppJNIConnection("L2AclTest")); - final FutureJVppFacade jvppFacade = new FutureJVppFacade(jvpp); - - System.out.println("Successfully connected to VPP"); - Thread.sleep(1000); - - final ClassifyAddDelTableReply classifyAddDelTableReply = - jvppFacade.classifyAddDelTable(createClassifyTable()).toCompletableFuture().get(); - print(classifyAddDelTableReply); - - final ClassifyTableIdsReply classifyTableIdsReply = - jvppFacade.classifyTableIds(new ClassifyTableIds()).toCompletableFuture().get(); - print(classifyTableIdsReply); - - final ClassifyTableInfoReply classifyTableInfoReply = - jvppFacade.classifyTableInfo(createClassifyTableInfoRequest(classifyAddDelTableReply.newTableIndex)) - .toCompletableFuture().get(); - print(classifyTableInfoReply); - - final ClassifyAddDelSessionReply classifyAddDelSessionReply = - jvppFacade.classifyAddDelSession(createClassifySession(classifyAddDelTableReply.newTableIndex)) - .toCompletableFuture().get(); - print(classifyAddDelSessionReply); - - final ClassifySessionDetailsReplyDump classifySessionDetailsReplyDump = - jvppFacade.classifySessionDump(createClassifySessionDumpRequest(classifyAddDelTableReply.newTableIndex)) - .toCompletableFuture().get(); - print(classifySessionDetailsReplyDump); - - final InputAclSetInterfaceReply inputAclSetInterfaceReply = - jvppFacade.inputAclSetInterface(aclSetInterface()).toCompletableFuture().get(); - print(inputAclSetInterfaceReply); - - final ClassifyTableByInterfaceReply classifyTableByInterfaceReply = - jvppFacade.classifyTableByInterface(createClassifyTableByInterfaceRequest()).toCompletableFuture().get(); - print(classifyTableByInterfaceReply); - - System.out.println("Disconnecting..."); - jvpp.close(); - Thread.sleep(1000); - } - - public static void main(String[] args) throws Exception { - testL2Acl(); - } -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/NotificationUtils.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/NotificationUtils.java deleted file mode 100644 index 9c24d572..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/test/NotificationUtils.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.openvpp.jvpp.test; - -import java.io.PrintStream; -import org.openvpp.jvpp.dto.SwInterfaceSetFlags; -import org.openvpp.jvpp.dto.SwInterfaceSetFlagsNotification; -import org.openvpp.jvpp.dto.WantInterfaceEvents; - -final class NotificationUtils { - - private NotificationUtils() {} - - static PrintStream printNotification(final SwInterfaceSetFlagsNotification msg) { - return System.out.printf("Received interface notification: ifc: %d, admin: %d, link: %d, deleted: %d\n", - msg.swIfIndex, msg.adminUpDown, msg.linkUpDown, msg.deleted); - } - - static SwInterfaceSetFlags getChangeInterfaceState() { - final SwInterfaceSetFlags swInterfaceSetFlags = new SwInterfaceSetFlags(); - swInterfaceSetFlags.swIfIndex = 0; - swInterfaceSetFlags.adminUpDown = 1; - swInterfaceSetFlags.deleted = 0; - return swInterfaceSetFlags; - } - - static WantInterfaceEvents getEnableInterfaceNotificationsReq() { - WantInterfaceEvents wantInterfaceEvents = new WantInterfaceEvents(); - wantInterfaceEvents.pid = 1; - wantInterfaceEvents.enableDisable = 1; - return wantInterfaceEvents; - } - - static WantInterfaceEvents getDisableInterfaceNotificationsReq() { - WantInterfaceEvents wantInterfaceEvents = new WantInterfaceEvents(); - wantInterfaceEvents.pid = 1; - wantInterfaceEvents.enableDisable = 0; - return wantInterfaceEvents; - } -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/OnErrorCallbackTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/OnErrorCallbackTest.java deleted file mode 100644 index 46d85583..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/test/OnErrorCallbackTest.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openvpp.jvpp.test; - -import org.openvpp.jvpp.JVpp; -import org.openvpp.jvpp.JVppImpl; -import org.openvpp.jvpp.VppCallbackException; -import org.openvpp.jvpp.VppJNIConnection; -import org.openvpp.jvpp.callback.GetNodeIndexCallback; -import org.openvpp.jvpp.callback.ShowVersionCallback; -import org.openvpp.jvpp.dto.*; - -public class OnErrorCallbackTest { - - private static class TestCallback implements GetNodeIndexCallback, ShowVersionCallback{ - - @Override - public void onGetNodeIndexReply(final GetNodeIndexReply msg) { - System.out.printf("Received GetNodeIndexReply: context=%d, nodeIndex=%d\n", - msg.context, msg.nodeIndex); - } - @Override - public void onShowVersionReply(final ShowVersionReply msg) { - System.out.printf("Received ShowVersionReply: context=%d, program=%s, version=%s, " + - "buildDate=%s, buildDirectory=%s\n", - msg.context, new String(msg.program), new String(msg.version), - new String(msg.buildDate), new String(msg.buildDirectory)); - } - - @Override - public void onError(VppCallbackException ex) { - System.out.printf("Received onError exception: call=%s, context=%d, retval=%d\n", ex.getMethodName(), ex.getCtxId(), ex.getErrorCode()); - } - } - - private static void testCallbackApi() throws Exception { - System.out.println("Testing Java callback API"); - JVpp jvpp = new JVppImpl(new VppJNIConnection("CallbackApiTest")); - jvpp.connect(new TestCallback()); - System.out.println("Successfully connected to VPP"); - - System.out.println("Sending ShowVersion request..."); - jvpp.send(new ShowVersion()); - - System.out.println("Sending GetNodeIndex request..."); - GetNodeIndex getNodeIndexRequest = new GetNodeIndex(); - getNodeIndexRequest.nodeName = "dummyNode".getBytes(); - jvpp.send(getNodeIndexRequest); - - Thread.sleep(5000); - - System.out.println("Disconnecting..."); - jvpp.close(); - Thread.sleep(1000); - } - - public static void main(String[] args) throws Exception { - testCallbackApi(); - } -} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/Readme.txt b/vpp-api/java/jvpp/org/openvpp/jvpp/test/Readme.txt deleted file mode 100644 index e0aa4f4d..00000000 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/test/Readme.txt +++ /dev/null @@ -1,17 +0,0 @@ -This package contains basic tests for jvpp. To run the tests: - -- Make sure VPP is running -- From VPP's build-root/ folder execute: - - sudo java -cp build-vpp-native/vpp-api/java/jvpp-16.09.jar org.openvpp.jvpp.test.[test name] - -Available tests: -ControlPingTest - Simple test executing a single control ping using low level JVpp APIs -CallbackApiTest - Similar to ControlPingTest, invokes more complex calls (e.g. interface dump) using low level JVpp APIs -CallbackNotificationApiTest - Tests interface notifications using low level JVpp APIs -FutureApiTest - Execution of more complex calls using Future based JVpp facade -FutureApiNotificationTest - Tests interface notifications using Future based JVpp facade -CallbackJVppFacadeTest - Execution of more complex calls using Callback based JVpp facade -CallbackJVppFacadeNotificationTest - Tests interface notifications using Callback based JVpp facade -L2AclTest - Tests L2 ACL creation -CreateSubInterfaceTest - Tests sub-interface creation -OnErrorCallbackTest - simple test failing with onError |