2 * 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 package org.openvpp.jvpp;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.nio.file.Files;
22 import java.nio.file.Path;
23 import java.nio.file.StandardCopyOption;
24 import java.nio.file.attribute.PosixFilePermission;
25 import java.nio.file.attribute.PosixFilePermissions;
26 import java.util.HashMap;
29 import java.util.logging.Logger;
30 import org.openvpp.jvpp.callback.JVppCallback;
33 * JNI based representation of a management connection to VPP
35 public final class VppJNIConnection implements VppConnection {
36 private final static Logger LOG = Logger.getLogger(VppJNIConnection.class.getName());
37 private static final String LIBNAME = "libjvpp.so.0.0.0";
42 } catch (Exception e) {
43 LOG.severe("Can't find vpp jni library: " + LIBNAME);
44 throw new ExceptionInInitializerError(e);
48 private static void loadStream(final InputStream is) throws IOException {
49 final Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rwxr-x---");
50 final Path p = Files.createTempFile(LIBNAME, null, PosixFilePermissions.asFileAttribute(perms));
52 Files.copy(is, p, StandardCopyOption.REPLACE_EXISTING);
55 Runtime.getRuntime().load(p.toString());
56 } catch (UnsatisfiedLinkError e) {
57 throw new IOException("Failed to load library " + p, e);
61 Files.deleteIfExists(p);
62 } catch (IOException e) {
67 private static void loadLibrary() throws IOException {
68 try (final InputStream is = VppJNIConnection.class.getResourceAsStream('/' + LIBNAME)) {
70 throw new IOException("Failed to open library resource " + LIBNAME);
76 private final String clientName;
77 private volatile boolean disconnected = false;
79 private VppJNIConnection(final String clientName) {
80 if (clientName == null) {
81 throw new NullPointerException("Null clientName");
83 this.clientName = clientName;
87 * Guarded by VppJNIConnection.class
89 private static final Map<String, VppJNIConnection> connections = new HashMap<>();
92 * Create a new Vpp connection identified by clientName parameter.
94 * Multiple instances are allowed since this class is not a singleton
95 * (VPP allows multiple management connections).
97 * However only a single connection per clientName is allowed.
99 * @param clientName identifier of vpp connection
100 * @param callback global callback to receive response calls from vpp
102 * @return new Vpp connection
103 * @throws IOException in case the connection could not be established, or there already is a connection with the same name
105 public static VppJNIConnection create(final String clientName, final JVppCallback callback) throws IOException {
106 synchronized (VppJNIConnection.class) {
107 if(connections.containsKey(clientName)) {
108 throw new IOException("Client " + clientName + " already connected");
111 final VppJNIConnection vppJNIConnection = new VppJNIConnection(clientName);
112 final int ret = clientConnect(clientName, callback);
114 throw new IOException("Connection returned error " + ret);
116 connections.put(clientName, vppJNIConnection);
117 return vppJNIConnection;
122 public final void checkActive() {
124 throw new IllegalStateException("Disconnected client " + clientName);
129 public synchronized final void close() {
135 synchronized (VppJNIConnection.class) {
136 connections.remove(clientName);
142 private static native int clientConnect(String clientName, JVppCallback callback);
143 private static native void clientDisconnect();