summaryrefslogtreecommitdiffstats
path: root/vpp-api/java/jvpp/org
diff options
context:
space:
mode:
Diffstat (limited to 'vpp-api/java/jvpp/org')
-rw-r--r--vpp-api/java/jvpp/org/openvpp/jvpp/VppConnection.java37
-rw-r--r--vpp-api/java/jvpp/org/openvpp/jvpp/VppJNIConnection.java144
-rw-r--r--vpp-api/java/jvpp/org/openvpp/jvpp/callback/JVppCallback.java23
-rw-r--r--vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppDump.java24
-rw-r--r--vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppReply.java24
-rw-r--r--vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppReplyDump.java25
-rw-r--r--vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppRequest.java33
-rw-r--r--vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVpp.java36
-rw-r--r--vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppFacade.java110
-rw-r--r--vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackApiTest.java87
-rw-r--r--vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackJVppFacadeTest.java67
-rw-r--r--vpp-api/java/jvpp/org/openvpp/jvpp/test/ControlPingTest.java53
-rw-r--r--vpp-api/java/jvpp/org/openvpp/jvpp/test/FutureApiTest.java124
13 files changed, 787 insertions, 0 deletions
diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/VppConnection.java b/vpp-api/java/jvpp/org/openvpp/jvpp/VppConnection.java
new file mode 100644
index 00000000000..72ff62c944b
--- /dev/null
+++ b/vpp-api/java/jvpp/org/openvpp/jvpp/VppConnection.java
@@ -0,0 +1,37 @@
+/*
+ * 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;
+
+/**
+ * Representation of a management connection to VPP.
+ * Connection is initiated when instance is created, closed with close().
+ */
+public interface VppConnection extends AutoCloseable {
+
+ /**
+ * 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/VppJNIConnection.java b/vpp-api/java/jvpp/org/openvpp/jvpp/VppJNIConnection.java
new file mode 100644
index 00000000000..9e07cc768c4
--- /dev/null
+++ b/vpp-api/java/jvpp/org/openvpp/jvpp/VppJNIConnection.java
@@ -0,0 +1,144 @@
+/*
+ * 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.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;
+
+ private VppJNIConnection(final String clientName) {
+ if (clientName == null) {
+ throw new NullPointerException("Null clientName");
+ }
+ this.clientName = clientName;
+ }
+
+ /**
+ * Guarded by VppJNIConnection.class
+ */
+ private static final Map<String, VppJNIConnection> connections = new HashMap<>();
+
+ /**
+ * Create a new Vpp connection identified by clientName parameter.
+ *
+ * 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 clientName identifier of vpp connection
+ * @param callback global callback to receive response calls from vpp
+ *
+ * @return new Vpp connection
+ * @throws IOException in case the connection could not be established, or there already is a connection with the same name
+ */
+ public static VppJNIConnection create(final String clientName, final JVppCallback callback) throws IOException {
+ synchronized (VppJNIConnection.class) {
+ if(connections.containsKey(clientName)) {
+ throw new IOException("Client " + clientName + " already connected");
+ }
+
+ final VppJNIConnection vppJNIConnection = new VppJNIConnection(clientName);
+ final int ret = clientConnect(clientName, callback);
+ if (ret != 0) {
+ throw new IOException("Connection returned error " + ret);
+ }
+ connections.put(clientName, vppJNIConnection);
+ return vppJNIConnection;
+ }
+ }
+
+ @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
new file mode 100644
index 00000000000..c17f2e0aa96
--- /dev/null
+++ b/vpp-api/java/jvpp/org/openvpp/jvpp/callback/JVppCallback.java
@@ -0,0 +1,23 @@
+/*
+ * 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;
+
+/**
+* Base JVppCallback interface
+*/
+public interface JVppCallback {
+}
diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppDump.java b/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppDump.java
new file mode 100644
index 00000000000..295bbba8525
--- /dev/null
+++ b/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppDump.java
@@ -0,0 +1,24 @@
+/*
+ * 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/JVppReply.java b/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppReply.java
new file mode 100644
index 00000000000..2f4964c4de0
--- /dev/null
+++ b/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppReply.java
@@ -0,0 +1,24 @@
+/*
+ * 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
new file mode 100644
index 00000000000..4aecedc19d4
--- /dev/null
+++ b/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppReplyDump.java
@@ -0,0 +1,25 @@
+/*
+ * 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
new file mode 100644
index 00000000000..8cd1534aa13
--- /dev/null
+++ b/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppRequest.java
@@ -0,0 +1,33 @@
+/*
+ * 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;
+
+/**
+* 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);
+
+}
diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVpp.java b/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVpp.java
new file mode 100644
index 00000000000..d860bc2d483
--- /dev/null
+++ b/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVpp.java
@@ -0,0 +1,36 @@
+/*
+ * 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 java.util.concurrent.CompletionStage;
+import org.openvpp.jvpp.dto.JVppReply;
+import org.openvpp.jvpp.dto.JVppRequest;
+
+/**
+* Future facade on top of JVpp
+*/
+public interface FutureJVpp {
+
+ /**
+ * Invoke asynchronous operation on VPP
+ *
+ * @return CompletionStage with future result of an async VPP call
+ */
+ <REQ extends JVppRequest, REPLY extends JVppReply<REQ>> CompletionStage<REPLY> send(REQ req);
+
+}
diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppFacade.java b/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppFacade.java
new file mode 100644
index 00000000000..5b8222c4565
--- /dev/null
+++ b/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppFacade.java
@@ -0,0 +1,110 @@
+/*
+ * 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 java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import org.openvpp.jvpp.JVpp;
+import org.openvpp.jvpp.dto.ControlPing;
+import org.openvpp.jvpp.dto.JVppDump;
+import org.openvpp.jvpp.dto.JVppReply;
+import org.openvpp.jvpp.dto.JVppReplyDump;
+import org.openvpp.jvpp.dto.JVppRequest;
+
+/**
+* Future facade on top of JVpp
+*/
+public final class FutureJVppFacade implements FutureJVpp {
+
+ private final JVpp jvpp;
+
+ /**
+ * Guarded by self
+ */
+ private final Map<Integer, CompletableFuture<? extends JVppReply<?>>> requests;
+
+ public FutureJVppFacade(final JVpp jvpp,
+ final Map<Integer, CompletableFuture<? extends JVppReply<?>>> requestMap) {
+ // TODO use guava's preconditions for nonNull and state checks
+ // However adding guava as a dependency requires better build system for Java in VPP project
+ // Currently it's just invocation of javac
+ if(jvpp == null) {
+ throw new NullPointerException("Null jvpp");
+ }
+ this.jvpp = jvpp;
+ if(requestMap == null) {
+ throw new NullPointerException("Null requestMap");
+ }
+ // 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 = requestMap;
+ }
+
+ // TODO use Optional in Future, java8
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <REQ extends JVppRequest, REPLY extends JVppReply<REQ>> CompletionStage<REPLY> send(REQ req) {
+ synchronized(requests) {
+ final int contextId = jvpp.send(req);
+
+ final CompletableFuture<REPLY> replyCompletableFuture;
+ 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;
+ }
+ }
+
+ static final class CompletableDumpFuture<T extends JVppReplyDump<?, ?>> extends CompletableFuture<T> {
+ // TODO make this final
+ // 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 returned. Because in callback we have method per response, but here where requests are invoked there is only
+ // a single generic send method that does not have enough information to create the DTO
+ // This can be final as soon as we provide specific send methods here
+ 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;
+ }
+ }
+
+}
diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackApiTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackApiTest.java
new file mode 100644
index 00000000000..5ac4b69a52d
--- /dev/null
+++ b/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackApiTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.VppJNIConnection;
+import org.openvpp.jvpp.callback.GetNodeIndexCallback;
+import org.openvpp.jvpp.callback.ShowVersionCallback;
+import org.openvpp.jvpp.callback.SwInterfaceCallback;
+import org.openvpp.jvpp.dto.GetNodeIndex;
+import org.openvpp.jvpp.dto.GetNodeIndexReply;
+import org.openvpp.jvpp.dto.ShowVersion;
+import org.openvpp.jvpp.dto.ShowVersionReply;
+import org.openvpp.jvpp.dto.SwInterfaceDetails;
+import org.openvpp.jvpp.dto.SwInterfaceDump;
+
+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, retval=%d, nodeIndex=%d\n",
+ msg.context, msg.retval, msg.nodeIndex);
+ }
+ @Override
+ public void onShowVersionReply(final ShowVersionReply msg) {
+ System.out.printf("Received ShowVersionReply: context=%d, retval=%d, program=%s, version=%s, " +
+ "buildDate=%s, buildDirectory=%s\n",
+ msg.context, msg.retval, 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);
+ }
+ }
+
+ private static void testCallbackApi() throws Exception {
+ System.out.println("Testing Java callback API");
+ JVpp jvpp = new JVppImpl(VppJNIConnection.create("CallbackApiTest", 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/CallbackJVppFacadeTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackJVppFacadeTest.java
new file mode 100644
index 00000000000..df3b0e7056c
--- /dev/null
+++ b/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackJVppFacadeTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.HashMap;
+import java.util.Map;
+import org.openvpp.jvpp.JVpp;
+import org.openvpp.jvpp.JVppImpl;
+import org.openvpp.jvpp.VppJNIConnection;
+import org.openvpp.jvpp.callback.JVppCallback;
+import org.openvpp.jvpp.callback.ShowVersionCallback;
+import org.openvpp.jvpp.callfacade.CallbackJVppFacade;
+import org.openvpp.jvpp.callfacade.CallbackJVppFacadeCallback;
+
+/**
+ * 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 = msg ->
+ System.out.printf("ShowVersionCallback1 received ShowVersionReply: context=%d, retval=%d, program=%s," +
+ "version=%s, buildDate=%s, buildDirectory=%s\n", msg.context, msg.retval, new String(msg.program),
+ new String(msg.version), new String(msg.buildDate), new String(msg.buildDirectory));
+
+ private static ShowVersionCallback showVersionCallback2 = msg ->
+ System.out.printf("ShowVersionCallback2 received ShowVersionReply: context=%d, retval=%d, program=%s," +
+ "version=%s, buildDate=%s, buildDirectory=%s\n", msg.context, msg.retval, new String(msg.program),
+ new String(msg.version), new String(msg.buildDate), new String(msg.buildDirectory));
+
+ private static void testCallbackFacade() throws Exception {
+ System.out.println("Testing CallbackJVppFacade");
+
+ final Map<Integer, JVppCallback> callbackMap = new HashMap<>();
+ JVpp impl = new JVppImpl(VppJNIConnection.create("CallbackApiTest", new CallbackJVppFacadeCallback(callbackMap)));
+ CallbackJVppFacade jvpp = new CallbackJVppFacade(impl, callbackMap);
+ System.out.println("Successfully connected to VPP");
+
+ jvpp.showVersion(showVersionCallback1);
+ jvpp.showVersion(showVersionCallback2);
+
+
+ Thread.sleep(2000);
+
+ System.out.println("Disconnecting...");
+ impl.close();
+ Thread.sleep(1000);
+ }
+
+ public static void main(String[] args) throws Exception {
+ testCallbackFacade();
+ }
+}
diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/ControlPingTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/ControlPingTest.java
new file mode 100644
index 00000000000..f1bd41de86f
--- /dev/null
+++ b/vpp-api/java/jvpp/org/openvpp/jvpp/test/ControlPingTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.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(VppJNIConnection.create("ControlPingTest", new ControlPingCallback() {
+ @Override
+ public void onControlPingReply(final ControlPingReply reply) {
+ System.out.printf("Received ControlPingReply: context=%d, retval=%d, clientIndex=%d vpePid=%d\n",
+ reply.context, reply.retval, reply.clientIndex, reply.vpePid);
+ }
+ }));
+ 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/FutureApiTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/FutureApiTest.java
new file mode 100644
index 00000000000..b5b36d58015
--- /dev/null
+++ b/vpp-api/java/jvpp/org/openvpp/jvpp/test/FutureApiTest.java
@@ -0,0 +1,124 @@
+/*
+ * 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.HashMap;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Future;
+import org.openvpp.jvpp.VppJNIConnection;
+import org.openvpp.jvpp.dto.GetNodeIndex;
+import org.openvpp.jvpp.dto.GetNodeIndexReply;
+import org.openvpp.jvpp.dto.JVppReply;
+import org.openvpp.jvpp.dto.ShowVersion;
+import org.openvpp.jvpp.dto.ShowVersionReply;
+import org.openvpp.jvpp.dto.SwInterfaceDetails;
+import org.openvpp.jvpp.dto.SwInterfaceDetailsReplyDump;
+import org.openvpp.jvpp.dto.SwInterfaceDump;
+import org.openvpp.jvpp.future.FutureJVppFacade;
+import org.openvpp.jvpp.future.FutureJVppFacadeCallback;
+
+public class FutureApiTest {
+
+ private static void testShowVersion(final FutureJVppFacade jvpp) {
+ System.out.println("Sending ShowVersion request...");
+ try {
+ final Future<JVppReply<ShowVersion>> replyFuture = jvpp.send(new ShowVersion()).toCompletableFuture();
+ final ShowVersionReply reply = (ShowVersionReply) replyFuture.get(); // TODO can we get rid of that cast?
+ System.out.printf("Received ShowVersionReply: context=%d, retval=%d, program=%s, " +
+ "version=%s, buildDate=%s, buildDirectory=%s\n",
+ reply.context, reply.retval, 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:\n");
+ 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 {
+ final GetNodeIndex request = new GetNodeIndex();
+ request.nodeName = "node0".getBytes();
+ final Future<JVppReply<GetNodeIndex>> replyFuture = jvpp.send(request).toCompletableFuture();
+ final GetNodeIndexReply reply = (GetNodeIndexReply) replyFuture.get();
+ System.out.printf("Received GetNodeIndexReply: context=%d, retval=%d, nodeIndex=%d\n",
+ reply.context, reply.retval, reply.nodeIndex);
+ } catch (Exception e) {
+ System.err.printf("GetNodeIndex request failed:\n");
+ e.printStackTrace();
+ }
+ }
+
+ private static void testSwInterfaceDump(final FutureJVppFacade jvpp) {
+ System.out.println("Sending SwInterfaceDump request...");
+ try {
+ final SwInterfaceDump request = new SwInterfaceDump();
+ request.nameFilterValid = 0;
+ request.nameFilter = "".getBytes();
+ final Future<JVppReply<SwInterfaceDump>> replyFuture = jvpp.send(request).toCompletableFuture();
+ final SwInterfaceDetailsReplyDump reply = (SwInterfaceDetailsReplyDump) replyFuture.get();
+
+ if (reply == null) {
+ throw new IllegalStateException("SwInterfaceDetailsReplyDump is null!");
+ }
+ if (reply.swInterfaceDetails == null) {
+ throw new IllegalStateException("SwInterfaceDetailsReplyDump.swInterfaceDetails is null!");
+ }
+
+ for (SwInterfaceDetails details : reply.swInterfaceDetails) {
+ if (details == null) {
+ throw new IllegalStateException("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 (Exception e) {
+ System.err.printf("SwInterfaceDump request failed:\n");
+ e.printStackTrace();
+ }
+ }
+
+ private static void testFutureApi() throws Exception {
+ System.out.println("Testing Java future API");
+
+ final Map<Integer, CompletableFuture<? extends JVppReply<?>>> map = new HashMap<>();
+ final org.openvpp.jvpp.JVppImpl impl =
+ new org.openvpp.jvpp.JVppImpl(VppJNIConnection.create("FutureApiTest", new FutureJVppFacadeCallback(map)));
+ final FutureJVppFacade jvpp = new FutureJVppFacade(impl, map);
+ System.out.println("Successfully connected to VPP");
+
+ testShowVersion(jvpp);
+ testGetNodeIndex(jvpp);
+ testSwInterfaceDump(jvpp);
+
+ 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();
+ }
+}