From 8c8d55a9de3f68435467d5fc1d11f57edf2cf365 Mon Sep 17 00:00:00 2001 From: lukepalmer Date: Sun, 28 Feb 2016 23:27:35 -0500 Subject: [PATCH] Load multiple native libraries --- .travis.yml | 6 ++ AUTHORS | 3 +- jzmq-jni/pom.xml | 16 ++++ .../java/org/zeromq/EmbeddedLibraryTools.java | 87 +++++++++---------- .../org/zeromq/EmbeddedLibraryToolsTest.java | 46 ++++++++++ .../resources/NATIVE/testarch/Linux/foo.dll | 0 .../NATIVE/testarch/Linux/libjzmq.so | 0 .../resources/NATIVE/testarch/Linux/libzmq.so | 0 pom.xml | 2 +- 9 files changed, 112 insertions(+), 48 deletions(-) create mode 100644 jzmq-jni/src/test/resources/NATIVE/testarch/Linux/foo.dll create mode 100644 jzmq-jni/src/test/resources/NATIVE/testarch/Linux/libjzmq.so create mode 100644 jzmq-jni/src/test/resources/NATIVE/testarch/Linux/libzmq.so diff --git a/.travis.yml b/.travis.yml index 15962d0a..6c8e5494 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,8 @@ +addons: +# hostname monkeying needed for openjdk, see travis-ci/travis-ci#5227 for details + hosts: + - myshorthost + hostname: myshorthost before_install: - sudo add-apt-repository ppa:trevorbernard/zeromq -y - sudo apt-get update -y @@ -30,3 +35,4 @@ script: mvn test jdk: - openjdk6 - openjdk7 + - oraclejdk8 diff --git a/AUTHORS b/AUTHORS index beb3f814..952f4c1a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -5,6 +5,7 @@ Alexej Lotz Asko Kauppi Barak Amar Bernd Prager +Chris Busbey Chris Wong Conrad D. Steenberg Dhruva Krishnamurthy @@ -17,6 +18,7 @@ Gonzalo Diethelm Joe Thornber Jon Dyte Kamil Shakirov +Luke Palmer Martin Hurton Martin Lucina Martin Sustrik @@ -31,7 +33,6 @@ Tero Marttila Terry Wilson Trevor Bernard Vitaly Mayatskikh -Chris Busbey Credits ======= diff --git a/jzmq-jni/pom.xml b/jzmq-jni/pom.xml index 764ff41d..82175976 100644 --- a/jzmq-jni/pom.xml +++ b/jzmq-jni/pom.xml @@ -49,6 +49,22 @@ + + + org.powermock + powermock-easymock-release-full + 1.6.4 + test + pom + + + org.easymock + easymock + 3.4 + test + + + diff --git a/jzmq-jni/src/main/java/org/zeromq/EmbeddedLibraryTools.java b/jzmq-jni/src/main/java/org/zeromq/EmbeddedLibraryTools.java index 14a01c90..cf17ea45 100644 --- a/jzmq-jni/src/main/java/org/zeromq/EmbeddedLibraryTools.java +++ b/jzmq-jni/src/main/java/org/zeromq/EmbeddedLibraryTools.java @@ -1,11 +1,6 @@ package org.zeromq; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; +import java.io.*; import java.net.URL; import java.util.ArrayList; import java.util.Collection; @@ -22,6 +17,9 @@ public class EmbeddedLibraryTools { LOADED_EMBEDDED_LIBRARY = loadEmbeddedLibrary(); } + private EmbeddedLibraryTools() { + } + public static String getCurrentPlatformIdentifier() { String osName = System.getProperty("os.name"); if (osName.toLowerCase().contains("windows")) { @@ -66,7 +64,7 @@ private static void catalogArchive(final File jarfile, final Collection } finally { try { j.close(); - } catch(Exception e) { + } catch (Exception e) { } } @@ -112,54 +110,51 @@ private static boolean loadEmbeddedLibrary() { // attempt to locate embedded native library within JAR at following location: // /NATIVE/${os.arch}/${os.name}/libjzmq.[so|dylib|dll] - String[] allowedExtensions = new String[] { "so", "dylib", "dll" }; + String[] allowedExtensions = new String[]{"so", "dylib", "dll"}; + String[] libs; + final String libsFromProps = System.getProperty("jzmq.libs"); + if (libsFromProps == null) + libs = new String[]{"libsodium", "libzmq", "libjzmq"}; + else + libs = libsFromProps.split(","); StringBuilder url = new StringBuilder(); url.append("/NATIVE/"); - url.append(getCurrentPlatformIdentifier()); - url.append("/libjzmq."); - URL nativeLibraryUrl = null; - // loop through extensions, stopping after finding first one - for (String ext : allowedExtensions) { - nativeLibraryUrl = ZMQ.class.getResource(url.toString() + ext); - if (nativeLibraryUrl != null) - break; - } - - if (nativeLibraryUrl != null) { - - // native library found within JAR, extract and load - - try { - - final File libfile = File.createTempFile("libjzmq-", ".lib"); - libfile.deleteOnExit(); // just in case - - final InputStream in = nativeLibraryUrl.openStream(); - final OutputStream out = new BufferedOutputStream(new FileOutputStream(libfile)); + url.append(getCurrentPlatformIdentifier()).append("/"); + for (String lib : libs) { + URL nativeLibraryUrl = null; + // loop through extensions, stopping after finding first one + for (String ext : allowedExtensions) { + nativeLibraryUrl = ZMQ.class.getResource(url.toString() + lib + "." + ext); + if (nativeLibraryUrl != null) + break; + } - int len = 0; - byte[] buffer = new byte[8192]; - while ((len = in.read(buffer)) > -1) - out.write(buffer, 0, len); - out.close(); - in.close(); + if (nativeLibraryUrl != null) { + // native library found within JAR, extract and load + try { - System.load(libfile.getAbsolutePath()); + final File libfile = File.createTempFile(lib, ".lib"); + libfile.deleteOnExit(); // just in case - libfile.delete(); + final InputStream in = nativeLibraryUrl.openStream(); + final OutputStream out = new BufferedOutputStream(new FileOutputStream(libfile)); - usingEmbedded = true; + int len = 0; + byte[] buffer = new byte[8192]; + while ((len = in.read(buffer)) > -1) + out.write(buffer, 0, len); + out.close(); + in.close(); + System.load(libfile.getAbsolutePath()); - } catch (IOException x) { - // mission failed, do nothing - } + usingEmbedded = true; - } // nativeLibraryUrl exists + } catch (IOException x) { + // mission failed, do nothing + } + } // nativeLibraryUrl exists + } return usingEmbedded; - - } - - private EmbeddedLibraryTools() { } } diff --git a/jzmq-jni/src/test/java/org/zeromq/EmbeddedLibraryToolsTest.java b/jzmq-jni/src/test/java/org/zeromq/EmbeddedLibraryToolsTest.java index 025e7b1f..c9d61300 100644 --- a/jzmq-jni/src/test/java/org/zeromq/EmbeddedLibraryToolsTest.java +++ b/jzmq-jni/src/test/java/org/zeromq/EmbeddedLibraryToolsTest.java @@ -1,14 +1,24 @@ package org.zeromq; +import org.easymock.Capture; +import org.easymock.CaptureType; import org.junit.After; import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import static org.easymock.EasyMock.capture; +import static org.easymock.EasyMock.newCapture; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.powermock.api.easymock.PowerMock.*; /** * Exercises basic manipulations in the EmbeddedLibraryTools for JNI loading. * Does not give full coverage yet as this has to be per-platform. */ +@RunWith(PowerMockRunner.class) public class EmbeddedLibraryToolsTest { private static final String origOsName = System.getProperty("os.name"); @@ -46,6 +56,42 @@ public void rewriteSpacesInPath() { assertPlatformIdentifierEquals("alpha/Digital_Unix"); } + @Test + @PrepareForTest(EmbeddedLibraryTools.class) + public void multiLibLoad() throws Exception { + mockStaticPartial(System.class, "load"); + Capture loadCapture = newCapture(CaptureType.ALL); + System.load(capture(loadCapture)); + expectLastCall().times(2); + replayAll(); + setOsProperties("Linux", "testarch"); + assertTrue(EmbeddedLibraryTools.LOADED_EMBEDDED_LIBRARY); + verifyAll(); + assertTrue(loadCapture.getValues().get(0).contains("libzmq")); + assertTrue(loadCapture.getValues().get(1).contains("libjzmq")); + } + + @Test + @PrepareForTest(EmbeddedLibraryTools.class) + public void libsAsProp() throws Exception { + try { + System.setProperty("jzmq.libs", "foo,libjzmq"); + mockStaticPartial(System.class, "load"); + Capture loadCapture = newCapture(CaptureType.ALL); + System.load(capture(loadCapture)); + expectLastCall().times(2); + replayAll(); + setOsProperties("Linux", "testarch"); + assertTrue(EmbeddedLibraryTools.LOADED_EMBEDDED_LIBRARY); + verifyAll(); + assertTrue(loadCapture.getValues().get(0).contains("foo")); + assertTrue(loadCapture.getValues().get(1).contains("libjzmq")); + } finally { + System.clearProperty("jzmq.libs"); + } + } + + @After public void resetOsProperties() { setOsProperties(origOsName, origOsArch); diff --git a/jzmq-jni/src/test/resources/NATIVE/testarch/Linux/foo.dll b/jzmq-jni/src/test/resources/NATIVE/testarch/Linux/foo.dll new file mode 100644 index 00000000..e69de29b diff --git a/jzmq-jni/src/test/resources/NATIVE/testarch/Linux/libjzmq.so b/jzmq-jni/src/test/resources/NATIVE/testarch/Linux/libjzmq.so new file mode 100644 index 00000000..e69de29b diff --git a/jzmq-jni/src/test/resources/NATIVE/testarch/Linux/libzmq.so b/jzmq-jni/src/test/resources/NATIVE/testarch/Linux/libzmq.so new file mode 100644 index 00000000..e69de29b diff --git a/pom.xml b/pom.xml index baf42132..492a86b3 100644 --- a/pom.xml +++ b/pom.xml @@ -112,7 +112,7 @@ junit junit - 4.11 + 4.12 test