Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* JNIUtil.java
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.apple.foundationdb;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Utility for loading a dynamic library from the classpath.
*
*/
public class JNIUtil {
private static final String SEPARATOR = "/";
private static final String LOADABLE_PREFIX = "FDB_LIBRARY_PATH_";
private static final String TEMPFILE_PREFIX = "fdbjni";
private static final String TEMPFILE_SUFFIX = ".library";
private static class OS {
private final String name;
private final String arch;
private final boolean canDeleteEager;
OS(String name, String arch, boolean canDeleteEager) {
this.name = name;
this.arch = arch;
this.canDeleteEager = canDeleteEager;
}
public String getName() {
return this.name;
}
public String getArch() {
return this.arch;
}
}
/**
* Attempts a platform specific load of a library using classpath resources. In
* the case that the load fails, a call to {@link System#loadLibrary(String)}
* will be made as a way to use a library not included in a jar.
*
* @param libName the name of the library to attempt to load. This name should be
* undecorated with file extensions and, in the case of *nix, "lib" prefixes.
*/
static void loadLibrary(String libName) throws UnsatisfiedLinkError {
if(libName == null) {
throw new NullPointerException("Library name must not be null");
}
String libPathToLoad = null;
try {
String prop = LOADABLE_PREFIX + libName.toUpperCase();
libPathToLoad = System.getProperty(prop);
} catch(SecurityException e) {
// eat
}
if(libPathToLoad != null) {
System.load(libPathToLoad);
return;
}
OS os = getRunningOS();
String path = getPath(os, libName);
if ((os.getName().equals("linux") && !path.endsWith(".so")) || (os.getName().equals("windows") && !path.endsWith(".dll")) || (os.getName().equals("osx") && !path.endsWith(".jnilib") && !path.endsWith(".dylib"))) {
throw new IllegalStateException("OS sanity check failed. System property os.name reports " + os.getName()+" but System.mapLibraryName is looking for " + getLibName(libName));
}
File exported;
try {
exported = exportResource(path, libName);
}
catch (IOException e) {
throw new UnsatisfiedLinkError(e.getMessage());
}
String filename = exported.getAbsolutePath();
System.load(filename);
if(os.canDeleteEager) {
try {
exported.delete();
} catch(Throwable t) {
// EAT, since we do not care that an eager deletion did not work...
}
}
}
/**
* Export a library from classpath resources to a temporary file.
*
* @param libName the name of the library to attempt to export. This name should be
* undecorated with file extensions and, in the case of *nix, "lib" prefixes.
* @return the exported temporary file
* @throws IOException because {@link File}
*/
public static File exportLibrary(String libName) throws IOException {
OS os = getRunningOS();
String path = getPath(os, libName);
return exportResource(path, libName);
}
/**
* Gets a relative path for a library. The path will be of the form:
* {@code {os}/{arch}/{name}}.
*
* @return a relative path to a resource to be loaded from the classpath
*/
private static String getPath(OS os, String libName) {
return SEPARATOR +
"lib" + SEPARATOR +
os.getName() + SEPARATOR +
os.getArch() + SEPARATOR +
getLibName(libName);
}
/**
* Export a resource from the classpath to a temporary file.
*
* @param path the relative path of the file to load from the classpath
* @param name an optional descriptive name to include in the temporary file's path
*
* @return the absolute path to the exported file
* @throws IOException because {@link File}
*/
private static File exportResource(String path, String name) throws IOException {
InputStream resource = JNIUtil.class.getResourceAsStream(path);
if(resource == null)
throw new IllegalStateException("Embedded library jar:" + path + " not found");
File f = saveStreamAsTempFile(resource, name);
return f;
}
private static File saveStreamAsTempFile(InputStream resource, String name) throws IOException {
File f = File.createTempFile(name.length() > 0 ? name : TEMPFILE_PREFIX, TEMPFILE_SUFFIX);
FileOutputStream outputStream = new FileOutputStream(f);
copyStream(resource, outputStream);
outputStream.flush();
outputStream.close();
f.deleteOnExit();
return f;
}
private static void copyStream(InputStream resource, OutputStream fileOutputStream) throws IOException {
byte[] buffer = new byte[4096];
int bytesRead;
while((bytesRead = resource.read(buffer)) > 0) {
fileOutputStream.write(buffer, 0, bytesRead);
}
}
private static String getLibName(String libName) {
String systemLibName = System.mapLibraryName(libName);
if (systemLibName.endsWith(".dylib")) {
systemLibName = systemLibName.replace("dylib", "jnilib");
}
return systemLibName;
}
private static OS getRunningOS() {
String osname = System.getProperty("os.name").toLowerCase();
String arch = System.getProperty("os.arch");
if (!arch.equals("amd64") && !arch.equals("x86_64") && !arch.equals("aarch64") && !arch.equals("ppc64le")) {
throw new IllegalStateException("Unknown or unsupported arch: " + arch);
}
if (osname.startsWith("windows")) {
return new OS("windows", arch, /* canDeleteEager */ false);
} else if (osname.startsWith("linux")) {
return new OS("linux", arch, /* canDeleteEager */ true);
} else if (osname.startsWith("mac") || osname.startsWith("darwin")) {
return new OS("osx", arch, /* canDeleteEager */ true);
} else {
throw new IllegalStateException("Unknown or unsupported OS: " + osname);
}
}
private JNIUtil() {}
}