More robust native library discovery in Mac OS X
Motivation: Some JDK versions of Mac OS X generates a JNI dynamic library with '.jnilib' extension rather than with '.dynlib' extension. However, System.mapLibraryName() always returns 'lib<name>.dynlib'. As a result, NativeLibraryLoader fails to load the native library whose extension is .jnilib. Modification: Try to find both '.jnilib' and '.dynlib' resources on OS X. Result: Dynamic libraries are loaded correctly in Mac OS X, and thus we can continue the OpenSslEngine work.
This commit is contained in:
parent
e26bbfd4a7
commit
2bc0eac704
@ -24,6 +24,7 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class to load JNI resources.
|
* Helper class to load JNI resources.
|
||||||
@ -33,9 +34,13 @@ public final class NativeLibraryLoader {
|
|||||||
|
|
||||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(NativeLibraryLoader.class);
|
private static final InternalLogger logger = InternalLoggerFactory.getInstance(NativeLibraryLoader.class);
|
||||||
|
|
||||||
|
private static final String NATIVE_RESOURCE_HOME = "META-INF/native/";
|
||||||
|
private static final String OSNAME;
|
||||||
private static final File WORKDIR;
|
private static final File WORKDIR;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
OSNAME = SystemPropertyUtil.get("os.name", "").toLowerCase(Locale.US).replaceAll("[^a-z0-9]+", "");
|
||||||
|
|
||||||
String workdir = SystemPropertyUtil.get("io.netty.native.workdir");
|
String workdir = SystemPropertyUtil.get("io.netty.native.workdir");
|
||||||
if (workdir != null) {
|
if (workdir != null) {
|
||||||
File f = new File(workdir);
|
File f = new File(workdir);
|
||||||
@ -52,25 +57,124 @@ public final class NativeLibraryLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
WORKDIR = f;
|
WORKDIR = f;
|
||||||
logger.debug("-Dio.netty.netty.workdir: {}", WORKDIR);
|
logger.debug("-Dio.netty.netty.workdir: " + WORKDIR);
|
||||||
} else {
|
} else {
|
||||||
WORKDIR = PlatformDependent.tmpdir();
|
WORKDIR = tmpdir();
|
||||||
logger.debug("-Dio.netty.netty.workdir: {} (io.netty.tmpdir)", WORKDIR);
|
logger.debug("-Dio.netty.netty.workdir: " + WORKDIR + " (io.netty.tmpdir)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static File tmpdir() {
|
||||||
|
File f;
|
||||||
|
try {
|
||||||
|
f = toDirectory(SystemPropertyUtil.get("io.netty.tmpdir"));
|
||||||
|
if (f != null) {
|
||||||
|
logger.debug("-Dio.netty.tmpdir: " + f);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
f = toDirectory(SystemPropertyUtil.get("java.io.tmpdir"));
|
||||||
|
if (f != null) {
|
||||||
|
logger.debug("-Dio.netty.tmpdir: " + f + " (java.io.tmpdir)");
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This shouldn't happen, but just in case ..
|
||||||
|
if (isWindows()) {
|
||||||
|
f = toDirectory(System.getenv("TEMP"));
|
||||||
|
if (f != null) {
|
||||||
|
logger.debug("-Dio.netty.tmpdir: " + f + " (%TEMP%)");
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
String userprofile = System.getenv("USERPROFILE");
|
||||||
|
if (userprofile != null) {
|
||||||
|
f = toDirectory(userprofile + "\\AppData\\Local\\Temp");
|
||||||
|
if (f != null) {
|
||||||
|
logger.debug("-Dio.netty.tmpdir: " + f + " (%USERPROFILE%\\AppData\\Local\\Temp)");
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
f = toDirectory(userprofile + "\\Local Settings\\Temp");
|
||||||
|
if (f != null) {
|
||||||
|
logger.debug("-Dio.netty.tmpdir: " + f + " (%USERPROFILE%\\Local Settings\\Temp)");
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
f = toDirectory(System.getenv("TMPDIR"));
|
||||||
|
if (f != null) {
|
||||||
|
logger.debug("-Dio.netty.tmpdir: " + f + " ($TMPDIR)");
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
// Environment variable inaccessible
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last resort.
|
||||||
|
if (isWindows()) {
|
||||||
|
f = new File("C:\\Windows\\Temp");
|
||||||
|
} else {
|
||||||
|
f = new File("/tmp");
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.warn("Failed to get the temporary directory; falling back to: " + f);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||||
|
private static File toDirectory(String path) {
|
||||||
|
if (path == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
File f = new File(path);
|
||||||
|
if (!f.exists()) {
|
||||||
|
f.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!f.isDirectory()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return f.getAbsoluteFile();
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isWindows() {
|
||||||
|
return OSNAME.startsWith("windows");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isOSX() {
|
||||||
|
return OSNAME.startsWith("macosx") || OSNAME.startsWith("osx");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the given library with the specified {@link java.lang.ClassLoader}
|
* Load the given library with the specified {@link java.lang.ClassLoader}
|
||||||
*/
|
*/
|
||||||
public static void load(String name, ClassLoader loader) {
|
public static void load(String name, ClassLoader loader) {
|
||||||
String libname = System.mapLibraryName(name);
|
String libname = System.mapLibraryName(name);
|
||||||
String path = "META-INF/native/" + libname;
|
String path = NATIVE_RESOURCE_HOME + libname;
|
||||||
|
|
||||||
URL url = loader.getResource(path);
|
URL url = loader.getResource(path);
|
||||||
|
if (url == null && isOSX()) {
|
||||||
|
if (path.endsWith(".jnilib")) {
|
||||||
|
url = loader.getResource(NATIVE_RESOURCE_HOME + "lib" + name + ".dynlib");
|
||||||
|
} else {
|
||||||
|
url = loader.getResource(NATIVE_RESOURCE_HOME + "lib" + name + ".jnilib");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (url == null) {
|
if (url == null) {
|
||||||
// Fall back to normal loading of JNI stuff
|
// Fall back to normal loading of JNI stuff
|
||||||
System.loadLibrary(name);
|
System.loadLibrary(name);
|
||||||
} else {
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int index = libname.lastIndexOf('.');
|
int index = libname.lastIndexOf('.');
|
||||||
String prefix = libname.substring(0, index);
|
String prefix = libname.substring(0, index);
|
||||||
String suffix = libname.substring(index, libname.length());
|
String suffix = libname.substring(index, libname.length());
|
||||||
@ -123,7 +227,6 @@ public final class NativeLibraryLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private NativeLibraryLoader() {
|
private NativeLibraryLoader() {
|
||||||
// Utility
|
// Utility
|
||||||
|
Loading…
Reference in New Issue
Block a user