<modelVersion>4.0.0</modelVersion>
<artifactId>tcpmd5-jni</artifactId>
<description>Native support for RFC2385-enabled TCP sockets</description>
- <packaging>jar</packaging>
+ <packaging>bundle</packaging>
<name>${project.artifactId}</name>
<prerequisites>
<properties>
<nar.groupId>com.github.maven-nar</nar.groupId>
<nar.version>3.0.0</nar.version>
+ <copy.version>0.2.5</copy.version>
</properties>
<dependencies>
<Export-Package>
org.opendaylight.bgpcep.jni
</Export-Package>
+ <Include-Resource>
+ libtcpmd5-jni.so=target/nar/tcpmd5-jni-${project.version}-amd64-Linux-gpp-jni/lib/amd64-Linux-gpp/jni/libtcpmd5-jni-${project.version}.so
+ </Include-Resource>
</instructions>
</configuration>
</plugin>
+
+ <plugin>
+ <groupId>com.github.goldin</groupId>
+ <artifactId>copy-maven-plugin</artifactId>
+ <version>0.2.5</version>
+ <executions>
+ <execution>
+ <id>copy-native</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <resources>
+ <resource>
+ <targetPath>${project.build.outputDirectory}</targetPath>
+ <file>${project.build.directory}/nar/tcpmd5-jni-${project.version}-amd64-Linux-gpp-jni/lib/amd64-Linux-gpp/jni/libtcpmd5-jni-${project.version}.so</file>
+ <destFileName>libtcpmd5-jni.so</destFileName>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
<plugin>
<!-- Let eclipse know about the generated sources -->
<groupId>org.codehaus.mojo</groupId>
</execution>
</executions>
</plugin>
+
<plugin>
<groupId>${nar.groupId}</groupId>
<artifactId>nar-maven-plugin</artifactId>
<goal>nar-resources</goal>
<goal>nar-javah</goal>
<goal>nar-compile</goal>
- <goal>nar-package</goal>
</goals>
</execution>
</executions>
</goals>
</pluginExecutionFilter>
<action>
- <ignore/>
+ <execute/>
+ </action>
+ </pluginExecution>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>com.github.goldin</groupId>
+ <artifactId>copy-maven-plugin</artifactId>
+ <versionRange>${copy.version}</versionRange>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <execute/>
</action>
</pluginExecution>
</pluginExecutions>
package org.opendaylight.bgpcep.tcpmd5.jni;
import java.io.IOException;
+import java.io.InputStream;
import java.nio.channels.Channel;
+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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
* directly to the underlying operating system.
*/
public final class NativeKeyAccess implements KeyAccess {
+ private static final String LIBNAME = "libtcpmd5-jni.so";
private static final Logger LOG = LoggerFactory.getLogger(NativeKeyAccess.class);
+ private static boolean AVAILABLE = false;
+
+ private static InputStream getLibraryStream() {
+ return Preconditions.checkNotNull(NativeKeyAccess.class.getResourceAsStream('/' + LIBNAME),
+ String.format("Failed to open library resource %s", LIBNAME));
+ }
static {
- NarSystem.loadLibrary();
+ final Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rwxr-x---");
+
+ try (final InputStream is = getLibraryStream()) {
+ try {
+ final Path p = Files.createTempFile(LIBNAME, null, PosixFilePermissions.asFileAttribute(perms));
+
+ LOG.info("Copying {} to {}", is, p);
- int rt = NarSystem.runUnitTests();
- if (rt == 0) {
- LOG.warn("Run-time initialization failed");
- } else {
- LOG.debug("Run-time found {} supported channel classes", rt);
+ try {
+ Files.copy(is, p, StandardCopyOption.REPLACE_EXISTING);
+
+ try {
+ Runtime.getRuntime().load(p.toString());
+
+ LOG.info("Library {} loaded", p);
+
+ int rt = NarSystem.runUnitTests();
+ if (rt == 0) {
+ LOG.warn("Run-time initialization failed");
+ } else {
+ LOG.debug("Run-time found {} supported channel classes", rt);
+ AVAILABLE = true;
+ }
+ } catch (RuntimeException e) {
+ LOG.error("Failed to load native library", e);
+ }
+ } catch (IOException e) {
+ LOG.error("Failed to extract native library", e);
+ } finally {
+ try {
+ Files.deleteIfExists(p);
+ } catch (IOException e) {
+ LOG.warn("Failed to remove temporary file", e);
+ }
+ }
+ } catch (IOException e2) {
+ LOG.error("Failed to create temporary file {}", LIBNAME, e2);
+ }
+ } catch (IOException e1) {
+ LOG.error("Failed to find native library {}", LIBNAME, e1);
}
}
}
public static KeyAccess create(final Channel channel) {
- if (isClassSupported0(channel.getClass())) {
- return new NativeKeyAccess(channel);
- } else {
+ if (!AVAILABLE) {
+ LOG.debug("Native library not available");
return null;
}
+
+ if (!isClassSupported0(channel.getClass())) {
+ LOG.debug("No support available for class {}", channel.getClass());
+ return null;
+ }
+
+ return new NativeKeyAccess(channel);
}
public static boolean isAvailableForClass(final Class<?> clazz) {
- return isClassSupported0(clazz);
+ if (!AVAILABLE) {
+ LOG.debug("Native library not available");
+ return false;
+ }
+
+ if (!isClassSupported0(clazz)) {
+ LOG.debug("No support available for class {}", clazz);
+ return false;
+ }
+
+ return true;
}
@Override
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.bgpcep.tcpmd5.jni;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+
+import org.junit.Test;
+
+public class NativeKeyAccessTest {
+
+ @Test
+ public void testAvailability() throws IOException {
+ final SocketChannel sc = SocketChannel.open();
+
+ assertTrue(NativeKeyAccess.isAvailableForClass(sc.getClass()));
+ }
+
+
+ @Test
+ public void testServerAvailability() throws IOException {
+ final ServerSocketChannel ssc = ServerSocketChannel.open();
+
+ assertTrue(NativeKeyAccess.isAvailableForClass(ssc.getClass()));
+ }
+}