Extracted loading of native library out of Native into NativeLibraryLoader.
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
package net.rubygrapefruit.platform;
|
package net.rubygrapefruit.platform;
|
||||||
|
|
||||||
|
import net.rubygrapefruit.platform.internal.NativeLibraryLoader;
|
||||||
import net.rubygrapefruit.platform.internal.NativeLibraryLocator;
|
import net.rubygrapefruit.platform.internal.NativeLibraryLocator;
|
||||||
import net.rubygrapefruit.platform.internal.Platform;
|
import net.rubygrapefruit.platform.internal.Platform;
|
||||||
import net.rubygrapefruit.platform.internal.jni.NativeLibraryFunctions;
|
import net.rubygrapefruit.platform.internal.jni.NativeLibraryFunctions;
|
||||||
@@ -13,7 +14,7 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
public class Native {
|
public class Native {
|
||||||
private static boolean loaded;
|
private static NativeLibraryLoader loader;
|
||||||
private static final Map<Class<?>, Object> integrations = new HashMap<Class<?>, Object>();
|
private static final Map<Class<?>, Object> integrations = new HashMap<Class<?>, Object>();
|
||||||
|
|
||||||
private Native() {
|
private Native() {
|
||||||
@@ -31,19 +32,15 @@ public class Native {
|
|||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
static public void init(File extractDir) throws NativeIntegrationUnavailableException, NativeException {
|
static public void init(File extractDir) throws NativeIntegrationUnavailableException, NativeException {
|
||||||
synchronized (Native.class) {
|
synchronized (Native.class) {
|
||||||
if (!loaded) {
|
if (loader == null) {
|
||||||
Platform platform = Platform.current();
|
Platform platform = Platform.current();
|
||||||
try {
|
try {
|
||||||
File libFile = new NativeLibraryLocator(extractDir).find(platform.getLibraryName());
|
loader = new NativeLibraryLoader(new NativeLibraryLocator(extractDir));
|
||||||
if (libFile == null) {
|
loader.load(platform.getLibraryName());
|
||||||
throw new NativeIntegrationUnavailableException(String.format("Native library is not available for this operating system and architecture."));
|
|
||||||
}
|
|
||||||
System.load(libFile.getCanonicalPath());
|
|
||||||
int nativeVersion = NativeLibraryFunctions.getVersion();
|
int nativeVersion = NativeLibraryFunctions.getVersion();
|
||||||
if (nativeVersion != NativeLibraryFunctions.VERSION) {
|
if (nativeVersion != NativeLibraryFunctions.VERSION) {
|
||||||
throw new NativeException(String.format("Unexpected native library version loaded. Expected %s, was %s.", nativeVersion, NativeLibraryFunctions.VERSION));
|
throw new NativeException(String.format("Unexpected native library version loaded. Expected %s, was %s.", nativeVersion, NativeLibraryFunctions.VERSION));
|
||||||
}
|
}
|
||||||
loaded = true;
|
|
||||||
} catch (NativeException e) {
|
} catch (NativeException e) {
|
||||||
throw e;
|
throw e;
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
@@ -69,7 +66,7 @@ public class Native {
|
|||||||
Object instance = integrations.get(type);
|
Object instance = integrations.get(type);
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
try {
|
try {
|
||||||
instance = Platform.current().get(type);
|
instance = Platform.current().get(type, loader);
|
||||||
} catch (NativeException e) {
|
} catch (NativeException e) {
|
||||||
throw e;
|
throw e;
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package net.rubygrapefruit.platform.internal;
|
||||||
|
|
||||||
|
import net.rubygrapefruit.platform.NativeIntegrationUnavailableException;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class NativeLibraryLoader {
|
||||||
|
private final Set<String> loaded = new HashSet<String>();
|
||||||
|
private final NativeLibraryLocator locator;
|
||||||
|
|
||||||
|
public NativeLibraryLoader(NativeLibraryLocator locator) {
|
||||||
|
this.locator = locator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load(String name) throws IOException {
|
||||||
|
if (loaded.contains(name)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
File libFile = locator.find(name);
|
||||||
|
if (libFile == null) {
|
||||||
|
throw new NativeIntegrationUnavailableException(String.format(
|
||||||
|
"Native library is not available for this operating system and architecture."));
|
||||||
|
}
|
||||||
|
System.load(libFile.getCanonicalPath());
|
||||||
|
loaded.add(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,12 +10,11 @@ public abstract class Platform {
|
|||||||
synchronized (Platform.class) {
|
synchronized (Platform.class) {
|
||||||
if (platform == null) {
|
if (platform == null) {
|
||||||
String osName = getOperatingSystem().toLowerCase();
|
String osName = getOperatingSystem().toLowerCase();
|
||||||
String arch = getArchitecture();
|
|
||||||
if (osName.contains("windows")) {
|
if (osName.contains("windows")) {
|
||||||
platform = new Windows();
|
platform = new Windows();
|
||||||
} else if (osName.contains("linux")) {
|
} else if (osName.contains("linux")) {
|
||||||
platform = new Linux();
|
platform = new Linux();
|
||||||
} else if (osName.contains("os x") && (arch.equals("i386") || arch.equals("x86_64") || arch.equals("amd64"))) {
|
} else if (osName.contains("os x")) {
|
||||||
platform = new OsX();
|
platform = new OsX();
|
||||||
} else if (osName.contains("sunos")) {
|
} else if (osName.contains("sunos")) {
|
||||||
platform = new Solaris();
|
platform = new Solaris();
|
||||||
@@ -31,12 +30,28 @@ public abstract class Platform {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends NativeIntegration> T get(Class<T> type) {
|
@Override
|
||||||
throw new NativeIntegrationUnavailableException(String.format("Native integration %s is not supported on this operating system (%s %s)",
|
public String toString() {
|
||||||
type.getSimpleName(), getOperatingSystem(), getArchitecture()));
|
return String.format("%s %s", getOperatingSystem(), getArchitecture());
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract String getLibraryName() throws NativeIntegrationUnavailableException;
|
public <T extends NativeIntegration> T get(Class<T> type, NativeLibraryLoader nativeLibraryLoader) {
|
||||||
|
throw new NativeIntegrationUnavailableException(String.format("Native integration %s is not supported for the current operating system (%s)",
|
||||||
|
type.getSimpleName(), toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLibraryName() {
|
||||||
|
throw new NativeIntegrationUnavailableException(String.format(
|
||||||
|
"Native integration is not available for the current operating system (%s)", toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getOperatingSystem() {
|
||||||
|
return System.getProperty("os.name");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getArchitecture() {
|
||||||
|
return System.getProperty("os.arch");
|
||||||
|
}
|
||||||
|
|
||||||
private static class Windows extends Platform {
|
private static class Windows extends Platform {
|
||||||
@Override
|
@Override
|
||||||
@@ -52,12 +67,11 @@ public abstract class Platform {
|
|||||||
if (getArchitecture().equals("amd64")) {
|
if (getArchitecture().equals("amd64")) {
|
||||||
return "native-platform-windows-amd64.dll";
|
return "native-platform-windows-amd64.dll";
|
||||||
}
|
}
|
||||||
throw new NativeIntegrationUnavailableException(String.format(
|
return super.getLibraryName();
|
||||||
"Native integration is not available for this architecture (%s) on Windows.", getArchitecture()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends NativeIntegration> T get(Class<T> type) {
|
public <T extends NativeIntegration> T get(Class<T> type, NativeLibraryLoader nativeLibraryLoader) {
|
||||||
if (type.equals(Process.class)) {
|
if (type.equals(Process.class)) {
|
||||||
return type.cast(new DefaultProcess());
|
return type.cast(new DefaultProcess());
|
||||||
}
|
}
|
||||||
@@ -70,13 +84,13 @@ public abstract class Platform {
|
|||||||
if (type.equals(FileSystems.class)) {
|
if (type.equals(FileSystems.class)) {
|
||||||
return type.cast(new PosixFileSystems());
|
return type.cast(new PosixFileSystems());
|
||||||
}
|
}
|
||||||
return super.get(type);
|
return super.get(type, nativeLibraryLoader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static abstract class Posix extends Platform {
|
private static abstract class Posix extends Platform {
|
||||||
@Override
|
@Override
|
||||||
public <T extends NativeIntegration> T get(Class<T> type) {
|
public <T extends NativeIntegration> T get(Class<T> type, NativeLibraryLoader nativeLibraryLoader) {
|
||||||
if (type.equals(PosixFile.class)) {
|
if (type.equals(PosixFile.class)) {
|
||||||
return type.cast(new DefaultPosixFile());
|
return type.cast(new DefaultPosixFile());
|
||||||
}
|
}
|
||||||
@@ -89,7 +103,7 @@ public abstract class Platform {
|
|||||||
if (type.equals(SystemInfo.class)) {
|
if (type.equals(SystemInfo.class)) {
|
||||||
return type.cast(new DefaultSystemInfo());
|
return type.cast(new DefaultSystemInfo());
|
||||||
}
|
}
|
||||||
return super.get(type);
|
return super.get(type, nativeLibraryLoader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,11 +112,11 @@ public abstract class Platform {
|
|||||||
|
|
||||||
private static class Linux extends Unix {
|
private static class Linux extends Unix {
|
||||||
@Override
|
@Override
|
||||||
public <T extends NativeIntegration> T get(Class<T> type) {
|
public <T extends NativeIntegration> T get(Class<T> type, NativeLibraryLoader nativeLibraryLoader) {
|
||||||
if (type.equals(FileSystems.class)) {
|
if (type.equals(FileSystems.class)) {
|
||||||
return type.cast(new PosixFileSystems());
|
return type.cast(new PosixFileSystems());
|
||||||
}
|
}
|
||||||
return super.get(type);
|
return super.get(type, nativeLibraryLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -113,14 +127,10 @@ public abstract class Platform {
|
|||||||
if (getArchitecture().equals("i386") || getArchitecture().equals("x86")) {
|
if (getArchitecture().equals("i386") || getArchitecture().equals("x86")) {
|
||||||
return "libnative-platform-linux-i386.so";
|
return "libnative-platform-linux-i386.so";
|
||||||
}
|
}
|
||||||
throw new NativeIntegrationUnavailableException(String.format(
|
return super.getLibraryName();
|
||||||
"Native integration is not available for this architecture (%s) on Linux.", getArchitecture()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getArchitecture() {
|
|
||||||
return System.getProperty("os.arch");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class Solaris extends Unix {
|
private static class Solaris extends Unix {
|
||||||
@Override
|
@Override
|
||||||
@@ -131,28 +141,24 @@ public abstract class Platform {
|
|||||||
|
|
||||||
private static class OsX extends Posix {
|
private static class OsX extends Posix {
|
||||||
@Override
|
@Override
|
||||||
public <T extends NativeIntegration> T get(Class<T> type) {
|
public <T extends NativeIntegration> T get(Class<T> type, NativeLibraryLoader nativeLibraryLoader) {
|
||||||
if (type.equals(FileSystems.class)) {
|
if (type.equals(FileSystems.class)) {
|
||||||
return type.cast(new PosixFileSystems());
|
return type.cast(new PosixFileSystems());
|
||||||
}
|
}
|
||||||
return super.get(type);
|
return super.get(type, nativeLibraryLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getLibraryName() {
|
public String getLibraryName() {
|
||||||
|
String arch = getArchitecture();
|
||||||
|
if (arch.equals("i386") || arch.equals("x86_64") || arch.equals("amd64")) {
|
||||||
return "libnative-platform-osx-universal.dylib";
|
return "libnative-platform-osx-universal.dylib";
|
||||||
}
|
}
|
||||||
|
return super.getLibraryName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Unsupported extends Platform {
|
private static class Unsupported extends Platform {
|
||||||
public String getLibraryName() {
|
|
||||||
throw new NativeIntegrationUnavailableException(String.format(
|
|
||||||
"Native integration is not available for this operating system (%s %s)", getOperatingSystem(),
|
|
||||||
getArchitecture()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getOperatingSystem() {
|
|
||||||
return System.getProperty("os.name");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user