2 * Copyright (c) 2013 Robert Varga. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.bgpcep.tcpmd5.jni;
10 import java.io.IOException;
11 import java.io.InputStream;
12 import java.nio.channels.Channel;
13 import java.nio.file.Files;
14 import java.nio.file.Path;
15 import java.nio.file.StandardCopyOption;
16 import java.nio.file.attribute.PosixFilePermission;
17 import java.nio.file.attribute.PosixFilePermissions;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
23 import com.google.common.base.Preconditions;
26 * Implementation of KeyAccess using Java Native Interface plugin to talk
27 * directly to the underlying operating system.
29 public final class NativeKeyAccess implements KeyAccess {
30 private static final String LIBNAME = "libtcpmd5-jni.so";
31 private static final Logger LOG = LoggerFactory.getLogger(NativeKeyAccess.class);
32 private static boolean AVAILABLE = false;
34 private static InputStream getLibraryStream() {
35 return Preconditions.checkNotNull(NativeKeyAccess.class.getResourceAsStream('/' + LIBNAME),
36 String.format("Failed to open library resource %s", LIBNAME));
40 final Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rwxr-x---");
42 try (final InputStream is = getLibraryStream()) {
44 final Path p = Files.createTempFile(LIBNAME, null, PosixFilePermissions.asFileAttribute(perms));
46 LOG.info("Copying {} to {}", is, p);
49 Files.copy(is, p, StandardCopyOption.REPLACE_EXISTING);
52 Runtime.getRuntime().load(p.toString());
54 LOG.info("Library {} loaded", p);
56 int rt = NarSystem.runUnitTests();
58 LOG.warn("Run-time initialization failed");
60 LOG.debug("Run-time found {} supported channel classes", rt);
63 } catch (RuntimeException e) {
64 LOG.error("Failed to load native library", e);
66 } catch (IOException e) {
67 LOG.error("Failed to extract native library", e);
70 Files.deleteIfExists(p);
71 } catch (IOException e) {
72 LOG.warn("Failed to remove temporary file", e);
75 } catch (IOException e2) {
76 LOG.error("Failed to create temporary file {}", LIBNAME, e2);
78 } catch (IOException e1) {
79 LOG.error("Failed to find native library {}", LIBNAME, e1);
83 private static native boolean isClassSupported0(Class<?> channel);
84 private static native byte[] getChannelKey0(Channel channel) throws IOException;
85 private static native void setChannelKey0(Channel channel, byte[] key) throws IOException;
87 private final Channel channel;
89 private NativeKeyAccess(final Channel channel) {
90 this.channel = Preconditions.checkNotNull(channel);
93 public static KeyAccess create(final Channel channel) {
95 LOG.debug("Native library not available");
99 if (!isClassSupported0(channel.getClass())) {
100 LOG.debug("No support available for class {}", channel.getClass());
104 return new NativeKeyAccess(channel);
107 public static boolean isAvailableForClass(final Class<?> clazz) {
109 LOG.debug("Native library not available");
113 if (!isClassSupported0(clazz)) {
114 LOG.debug("No support available for class {}", clazz);
122 public byte[] getKey() throws IOException {
123 synchronized (channel) {
124 return getChannelKey0(channel);
129 public void setKey(final byte[] key) throws IOException {
130 synchronized (channel) {
131 setChannelKey0(channel, Preconditions.checkNotNull(key));