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.
/*
* Class NativeUtils is published under the The MIT License:
*
* Copyright (c) 2012 Adam Heinrich
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package net.gdface.utils;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
/**
* 从jar包中加载指定路径下的动态库
*
* @see http://adamheinrich.com/blog/2012/how-to-load-native-jni-library-from-jar
* @see https://github.com/adamheinrich/native-utils
*
*/
public class NativeUtils {
// buffer size used for reading and writing
private static final int BUFFER_SIZE = 8192;
public static final String NATIVE_FOLDER_PATH_PREFIX = "nativeutils";
/**
* Temporary directory which will contain the DLLs.
*/
private static File temporaryDir;
/**
* Private constructor - this class will never be instanced
*/
private NativeUtils() {
}
/**
* Loads library from current JAR archive
* @see #copyToTempFromJar(String, Class)
*/
public static synchronized void loadLibraryFromJar(String path, Class> loadClass) throws IOException {
File temp = copyToTempFromJar(path,loadClass);
System.load(temp.getAbsolutePath());
}
/**
* copy file from current JAR archive to system temporary directory
*
* The file from JAR is copied into system temporary directory and then loaded. The temporary file is deleted after
* exiting.
* Method uses String as filename because the pathname is "abstract", not system-dependent.
*
* @param path The path of file inside JAR as absolute path (beginning with '/'), e.g. /package/File.ext
* @param loadClass class that provide {@link ClassLoader} to load library file by input stream,if null, current class instead.
* @throws IOException If temporary file creation or read/write operation fails
* @throws IllegalArgumentException If the path is not absolute or if the filename is shorter than three characters
* (restriction of {@link File#createTempFile(java.lang.String, java.lang.String)}).
* @throws FileNotFoundException If the file could not be found inside the JAR.
*/
public static synchronized File copyToTempFromJar(String path, Class> loadClass) throws IOException {
if (null == path || !path.startsWith("/")) {
throw new IllegalArgumentException("The path has to be absolute (start with '/').");
}
// Prepare temporary file
if (temporaryDir == null) {
temporaryDir = createTempDirectory(NATIVE_FOLDER_PATH_PREFIX);
temporaryDir.deleteOnExit();
}
File temp = new File(temporaryDir, path);
Class> clazz = loadClass == null ? NativeUtils.class : loadClass;
InputStream is = clazz.getResourceAsStream(path);
try{
copy(is, temp);
temp.deleteOnExit();
return temp;
} catch (IOException e) {
temp.delete();
throw e;
} catch (NullPointerException e) {
temp.delete();
throw new FileNotFoundException("File " + path + " was not found inside JAR.");
} finally {
if(is != null){
is.close();
}
}
}
/**
* @see #copyToTempFromJar(String, Class)
*/
public static File copyToTempFromJar(String path) throws IOException {
return copyToTempFromJar(path, null);
}
/**
* 从jar包中加载指定的动态库
* @param path
* @throws IOException
* @see #loadLibraryFromJar(String, Class)
*/
public static void loadLibraryFromJar(String path) throws IOException {
loadLibraryFromJar(path,null);
}
private static File createTempDirectory(String prefix) throws IOException {
String tempDir = System.getProperty("java.io.tmpdir");
File generatedDir = new File(tempDir, prefix + System.nanoTime());
if (!generatedDir.mkdir())
throw new IOException("Failed to create temp directory " + generatedDir.getName());
return generatedDir;
}
/**
* 从jar包中加载指定名字的动态库
* 先尝试寻找'/lib/${os_prefix}/${name}',找不到再尝试'/${os_prefix}/${name}'
* os_prefix由{@link Platform#getNativeLibraryResourcePrefix()}计算
* @param name 库名
* @throws IOException
* @see #loadLibraryFromJar(String, Class)
*/
public static void loadFromJar(String name) throws IOException {
String prefix = Platform.getNativeLibraryResourcePrefix();
try {
loadLibraryFromJar("/lib/" + prefix +"/" + System.mapLibraryName(name));
} catch (FileNotFoundException e) {
loadLibraryFromJar("/" + prefix +"/" + System.mapLibraryName(name));
}
}
public static File getTemporaryDir() {
return temporaryDir;
}
private static long copy(InputStream in, File target) throws IOException {
target.delete();
File parent = target.getParentFile();
if (parent != null){
parent.mkdirs();
}
OutputStream out = new FileOutputStream(target);
// do the copy
try {
return copy(in, out);
}finally{
out.close();
}
}
/**
* Reads all bytes from an input stream and writes them to an output stream.
*/
private static long copy(InputStream source, OutputStream dest)
throws IOException
{
long nread = 0L;
byte[] buf = new byte[BUFFER_SIZE];
int n;
while ((n = source.read(buf)) > 0) {
dest.write(buf, 0, n);
nread += n;
}
return nread;
}
/**
* 将动态库解析为内部资源路径
* @param libprefix '/'起始的路径前缀,可为{@code null}
* @param name
* @return 资源路径
* @throws IOException
*/
private static String resolveName(String libprefix, String name) throws IOException {
String prefix = Platform.getNativeLibraryResourcePrefix();
if(libprefix == null ){
libprefix = "/";
}
// 如果非'/'开头则抛出异常
if(!libprefix.startsWith("/")){
throw new IllegalArgumentException("libprefix(" + libprefix + ") must starts with '/'");
}
if(!libprefix.endsWith("/")){
libprefix = libprefix.concat("/");
}
return libprefix + prefix +"/" + System.mapLibraryName(name);
}
/**
* 从资源中加载动态库
* 先尝试寻找'/lib/${os_prefix}/${name}',找不到再尝试'/${os_prefix}/${name}'
* @param name 动态库名,参见 {@link System#loadLibrary(String)}
* @param loaderClass
* @throws IOException
*/
public static void loadLibraryFromResource(String name, Class> loaderClass) throws IOException{
if(Platform.isAndroid()){
System.loadLibrary(name);
return;
}
if(null == loaderClass){
loaderClass = NativeUtils.class;
}
String path = resolveName("/lib/", name);
URL url = loaderClass.getResource(path);
if(null == url){
path = resolveName(null, name);
url = loaderClass.getResource(path);
}
Assert.notNull(url, "url","NOT FOUND library:" + path);
if(url.getProtocol().equals("file")){
System.load(url.getPath());
return ;
}
if(url.getProtocol().equals("jar")){
loadFromJar(name);
return;
}
throw new UnsupportedOperationException();
}
}