3 # Copyright (c) 2016 Cisco and/or its affiliates.
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
17 from string import Template
19 jvpp_ifc_template = Template("""
20 package $plugin_package;
23 * <p>Java representation of plugin's api file.
24 * <br>It was generated by jvpp_impl_gen.py based on $inputfile
25 * <br>(python representation of api file generated by vppapigen).
27 public interface JVpp${plugin_name} extends $base_package.JVpp {
30 * Generic dispatch method for sending requests to VPP
32 * @throws io.fd.vpp.jvpp.VppInvocationException if send request had failed
34 int send($base_package.$dto_package.JVppRequest request) throws io.fd.vpp.jvpp.VppInvocationException;
40 jvpp_impl_template = Template("""
41 package $plugin_package;
43 import java.io.IOException;
44 import java.io.InputStream;
45 import java.nio.file.Files;
46 import java.nio.file.Path;
47 import java.nio.file.StandardCopyOption;
48 import java.nio.file.attribute.PosixFilePermission;
49 import java.nio.file.attribute.PosixFilePermissions;
51 import java.util.logging.Logger;
52 import $base_package.callback.JVppCallback;
53 import $base_package.VppConnection;
54 import $base_package.JVppRegistry;
57 * <p>Default implementation of JVpp interface.
58 * <br>It was generated by jvpp_impl_gen.py based on $inputfile
59 * <br>(python representation of api file generated by vppapigen).
61 public final class JVpp${plugin_name}Impl implements $plugin_package.JVpp${plugin_name} {
63 private final static Logger LOG = Logger.getLogger(JVpp${plugin_name}Impl.class.getName());
64 private static final String LIBNAME = "libjvpp_${plugin_name_underscore}.so";
66 // FIXME using NativeLibraryLoader makes load fail could not find (WantInterfaceEventsReply).
70 } catch (Exception e) {
71 LOG.severe("Can't find jvpp jni library: " + LIBNAME);
72 throw new ExceptionInInitializerError(e);
76 private static void loadStream(final InputStream is) throws IOException {
77 final Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rwxr-x---");
78 final Path p = Files.createTempFile(LIBNAME, null, PosixFilePermissions.asFileAttribute(perms));
80 Files.copy(is, p, StandardCopyOption.REPLACE_EXISTING);
83 Runtime.getRuntime().load(p.toString());
84 } catch (UnsatisfiedLinkError e) {
85 throw new IOException("Failed to load library " + p, e);
89 Files.deleteIfExists(p);
90 } catch (IOException e) {
95 private static void loadLibrary() throws IOException {
96 try (final InputStream is = JVpp${plugin_name}Impl.class.getResourceAsStream('/' + LIBNAME)) {
98 throw new IOException("Failed to open library resource " + LIBNAME);
104 private VppConnection connection;
105 private JVppRegistry registry;
107 private static native void init0(final JVppCallback callback, final long queueAddress, final int clientIndex);
109 public void init(final JVppRegistry registry, final JVppCallback callback, final long queueAddress, final int clientIndex) {
110 this.registry = java.util.Objects.requireNonNull(registry, "registry should not be null");
111 this.connection = java.util.Objects.requireNonNull(registry.getConnection(), "connection should not be null");
112 connection.checkActive();
113 init0(callback, queueAddress, clientIndex);
116 private static native void close0();
118 public void close() {
123 public int send($base_package.$dto_package.JVppRequest request) throws io.fd.vpp.jvpp.VppInvocationException {
124 return request.send(this);
128 public final int controlPing(final io.fd.vpp.jvpp.dto.ControlPing controlPing) throws io.fd.vpp.jvpp.VppInvocationException {
129 return registry.controlPing(JVpp${plugin_name}Impl.class);
136 method_template = Template(""" int $name($plugin_package.$dto_package.$request request) throws io.fd.vpp.jvpp.VppInvocationException;""")
137 method_native_template = Template(
138 """ private static native int ${name}0($plugin_package.$dto_package.$request request);""")
139 method_impl_template = Template(""" public final int $name($plugin_package.$dto_package.$request request) throws io.fd.vpp.jvpp.VppInvocationException {
140 java.util.Objects.requireNonNull(request,"Null request object");
141 connection.checkActive();
142 int result=${name}0(request);
144 throw new io.fd.vpp.jvpp.VppInvocationException("${name}",result);
150 no_arg_method_template = Template(""" int $name() throws io.fd.vpp.jvpp.VppInvocationException;""")
151 no_arg_method_native_template = Template(""" private static native int ${name}0() throws io.fd.vpp.jvpp.VppInvocationException;""")
152 no_arg_method_impl_template = Template(""" public final int $name() throws io.fd.vpp.jvpp.VppInvocationException {
153 connection.checkActive();
154 int result=${name}0();
156 throw new io.fd.vpp.jvpp.VppInvocationException("${name}",result);
163 def generate_jvpp(func_list, base_package, plugin_package, plugin_name_underscore, dto_package, inputfile):
164 """ Generates JVpp interface and JNI implementation """
165 print "Generating JVpp"
166 plugin_name = util.underscore_to_camelcase_upper(plugin_name_underscore)
170 for func in func_list:
172 # Skip structures that are used only as notifications
173 if util.is_just_notification(func['name']) or util.is_ignored(func['name']):
176 camel_case_name = util.underscore_to_camelcase(func['name'])
177 camel_case_name_upper = util.underscore_to_camelcase_upper(func['name'])
178 if util.is_reply(camel_case_name):
181 if len(func['args']) == 0:
182 methods.append(no_arg_method_template.substitute(name=camel_case_name))
183 methods_impl.append(no_arg_method_native_template.substitute(name=camel_case_name))
184 methods_impl.append(no_arg_method_impl_template.substitute(name=camel_case_name))
186 methods.append(method_template.substitute(name=camel_case_name,
187 request=camel_case_name_upper,
188 plugin_package=plugin_package,
189 dto_package=dto_package))
190 methods_impl.append(method_native_template.substitute(name=camel_case_name,
191 request=camel_case_name_upper,
192 plugin_package=plugin_package,
193 dto_package=dto_package))
194 methods_impl.append(method_impl_template.substitute(name=camel_case_name,
195 request=camel_case_name_upper,
196 plugin_package=plugin_package,
197 dto_package=dto_package))
199 jvpp_file = open("JVpp%s.java" % plugin_name, 'w')
201 jvpp_ifc_template.substitute(inputfile=inputfile,
202 methods="\n".join(methods),
203 base_package=base_package,
204 plugin_package=plugin_package,
205 plugin_name=plugin_name,
206 dto_package=dto_package))
210 jvpp_file = open("JVpp%sImpl.java" % plugin_name, 'w')
211 jvpp_file.write(jvpp_impl_template.substitute(inputfile=inputfile,
212 methods="\n".join(methods_impl),
213 base_package=base_package,
214 plugin_package=plugin_package,
215 plugin_name=plugin_name,
216 plugin_name_underscore=plugin_name_underscore,
217 dto_package=dto_package))