Applied a patch from Alec Wysoker for finding snappy DLL via java.library.path

This commit is contained in:
Taro L. Saito 2011-05-26 11:14:01 +09:00
parent 6771e58b46
commit 85d9cc9084

View File

@ -1,244 +1,244 @@
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
* Copyright 2011 Taro L. Saito * Copyright 2011 Taro L. Saito
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
//-------------------------------------- //--------------------------------------
// snappy-java Project // snappy-java Project
// //
// LoadSnappy.java // LoadSnappy.java
// Since: 2011/03/29 // Since: 2011/03/29
// //
// $URL$ // $URL$
// $Author$ // $Author$
//-------------------------------------- //--------------------------------------
package org.xerial.snappy; package org.xerial.snappy;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.security.DigestInputStream; import java.security.DigestInputStream;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.Properties; import java.util.Properties;
/** /**
* This class loads a native library of Snappy according to the platform of the * This class loads a native library of Snappy according to the platform of the
* user. * user.
* *
* @author leo * @author leo
* *
*/ */
public class LoadSnappy public class LoadSnappy
{ {
private static boolean isLoaded = false; private static boolean isLoaded = false;
public static boolean load() { public static boolean load() {
if (!isLoaded) { if (!isLoaded) {
loadSnappyNativeLibrary(); loadSnappyNativeLibrary();
} }
return isLoaded; return isLoaded;
} }
/** /**
* Computes the MD5 value of the input stream * Computes the MD5 value of the input stream
* *
* @param input * @param input
* @return * @return
* @throws IOException * @throws IOException
* @throws NoSuchAlgorithmException * @throws NoSuchAlgorithmException
*/ */
static String md5sum(InputStream input) throws IOException { static String md5sum(InputStream input) throws IOException {
BufferedInputStream in = new BufferedInputStream(input); BufferedInputStream in = new BufferedInputStream(input);
try { try {
MessageDigest digest = java.security.MessageDigest.getInstance("MD5"); MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
DigestInputStream digestInputStream = new DigestInputStream(in, digest); DigestInputStream digestInputStream = new DigestInputStream(in, digest);
for (; digestInputStream.read() >= 0;) { for (; digestInputStream.read() >= 0;) {
} }
ByteArrayOutputStream md5out = new ByteArrayOutputStream(); ByteArrayOutputStream md5out = new ByteArrayOutputStream();
md5out.write(digest.digest()); md5out.write(digest.digest());
return md5out.toString(); return md5out.toString();
} }
catch (NoSuchAlgorithmException e) { catch (NoSuchAlgorithmException e) {
throw new IllegalStateException("MD5 algorithm is not available: " + e); throw new IllegalStateException("MD5 algorithm is not available: " + e);
} }
finally { finally {
in.close(); in.close();
} }
} }
/** /**
* Extract the specified library file to the target folder * Extract the specified library file to the target folder
* *
* @param libFolderForCurrentOS * @param libFolderForCurrentOS
* @param libraryFileName * @param libraryFileName
* @param targetFolder * @param targetFolder
* @return * @return
*/ */
private static boolean extractAndLoadLibraryFile(String libFolderForCurrentOS, String libraryFileName, private static boolean extractAndLoadLibraryFile(String libFolderForCurrentOS, String libraryFileName,
String targetFolder) { String targetFolder) {
String nativeLibraryFilePath = libFolderForCurrentOS + "/" + libraryFileName; String nativeLibraryFilePath = libFolderForCurrentOS + "/" + libraryFileName;
final String prefix = "snappy-" + getVersion() + "-"; final String prefix = "snappy-" + getVersion() + "-";
String extractedLibFileName = prefix + libraryFileName; String extractedLibFileName = prefix + libraryFileName;
File extractedLibFile = new File(targetFolder, extractedLibFileName); File extractedLibFile = new File(targetFolder, extractedLibFileName);
try { try {
if (extractedLibFile.exists()) { if (extractedLibFile.exists()) {
// test md5sum value // test md5sum value
String md5sum1 = md5sum(LoadSnappy.class.getResourceAsStream(nativeLibraryFilePath)); String md5sum1 = md5sum(LoadSnappy.class.getResourceAsStream(nativeLibraryFilePath));
String md5sum2 = md5sum(new FileInputStream(extractedLibFile)); String md5sum2 = md5sum(new FileInputStream(extractedLibFile));
if (md5sum1.equals(md5sum2)) { if (md5sum1.equals(md5sum2)) {
return loadNativeLibrary(targetFolder, extractedLibFileName); return loadNativeLibrary(targetFolder, extractedLibFileName);
} }
else { else {
// remove old native library file // remove old native library file
boolean deletionSucceeded = extractedLibFile.delete(); boolean deletionSucceeded = extractedLibFile.delete();
if (!deletionSucceeded) { if (!deletionSucceeded) {
throw new IOException("failed to remove existing native library file: " throw new IOException("failed to remove existing native library file: "
+ extractedLibFile.getAbsolutePath()); + extractedLibFile.getAbsolutePath());
} }
} }
} }
// extract file into the current directory // extract file into the current directory
InputStream reader = LoadSnappy.class.getResourceAsStream(nativeLibraryFilePath); InputStream reader = LoadSnappy.class.getResourceAsStream(nativeLibraryFilePath);
FileOutputStream writer = new FileOutputStream(extractedLibFile); FileOutputStream writer = new FileOutputStream(extractedLibFile);
byte[] buffer = new byte[1024]; byte[] buffer = new byte[1024];
int bytesRead = 0; int bytesRead = 0;
while ((bytesRead = reader.read(buffer)) != -1) { while ((bytesRead = reader.read(buffer)) != -1) {
writer.write(buffer, 0, bytesRead); writer.write(buffer, 0, bytesRead);
} }
writer.close(); writer.close();
reader.close(); reader.close();
if (!System.getProperty("os.name").contains("Windows")) { if (!System.getProperty("os.name").contains("Windows")) {
try { try {
Runtime.getRuntime().exec(new String[] { "chmod", "755", extractedLibFile.getAbsolutePath() }) Runtime.getRuntime().exec(new String[] { "chmod", "755", extractedLibFile.getAbsolutePath() })
.waitFor(); .waitFor();
} }
catch (Throwable e) {} catch (Throwable e) {}
} }
return loadNativeLibrary(targetFolder, extractedLibFileName); return loadNativeLibrary(targetFolder, extractedLibFileName);
} }
catch (IOException e) { catch (IOException e) {
System.err.println(e.getMessage()); System.err.println(e.getMessage());
return false; return false;
} }
} }
private static synchronized boolean loadNativeLibrary(String path, String name) { private static synchronized boolean loadNativeLibrary(String path, String name) {
File libPath = new File(path, name); File libPath = new File(path, name);
if (libPath.exists()) { if (libPath.exists()) {
try { try {
System.load(new File(path, name).getAbsolutePath()); System.load(new File(path, name).getAbsolutePath());
return true; return true;
} }
catch (UnsatisfiedLinkError e) { catch (UnsatisfiedLinkError e) {
throw new SnappyError(SnappyErrorCode.FAILED_TO_LOAD_NATIVE_LIBRARY, e); throw new SnappyError(SnappyErrorCode.FAILED_TO_LOAD_NATIVE_LIBRARY, e);
} }
} }
else else
return false; return false;
} }
private static void loadSnappyNativeLibrary() { private static void loadSnappyNativeLibrary() {
if (isLoaded) if (isLoaded)
return; return;
// Try loading the library from org.xerial.snappy.lib.path library path */ // Try loading the library from org.xerial.snappy.lib.path library path */
String snappyNativeLibraryPath = System.getProperty("org.xerial.snappy.lib.path"); String snappyNativeLibraryPath = System.getProperty("org.xerial.snappy.lib.path");
String snappyNativeLibraryName = System.getProperty("org.xerial.snappy.lib.name"); String snappyNativeLibraryName = System.getProperty("org.xerial.snappy.lib.name");
// Resolve the library file name with a suffix (e.g., dll, .so, etc.) // Resolve the library file name with a suffix (e.g., dll, .so, etc.)
if (snappyNativeLibraryName == null) if (snappyNativeLibraryName == null)
snappyNativeLibraryName = System.mapLibraryName("snappy"); snappyNativeLibraryName = System.mapLibraryName("snappy");
if (snappyNativeLibraryPath != null) { if (snappyNativeLibraryPath != null) {
if (loadNativeLibrary(snappyNativeLibraryPath, snappyNativeLibraryName)) { if (loadNativeLibrary(snappyNativeLibraryPath, snappyNativeLibraryName)) {
isLoaded = true; isLoaded = true;
return; return;
} }
} }
// Load the os-dependent library from a jar file // Load the os-dependent library from a jar file
snappyNativeLibraryPath = "/org/xerial/snappy/native/" + OSInfo.getNativeLibFolderPathForCurrentOS(); snappyNativeLibraryPath = "/org/xerial/snappy/native/" + OSInfo.getNativeLibFolderPathForCurrentOS();
if (LoadSnappy.class.getResource(snappyNativeLibraryPath + "/" + snappyNativeLibraryName) == null) { if (LoadSnappy.class.getResource(snappyNativeLibraryPath + "/" + snappyNativeLibraryName) != null) {
// use nested VM version // Temporary library folder. Use the value of java.io.tmpdir
return; String tempFolder = new File(System.getProperty("java.io.tmpdir")).getAbsolutePath();
} // Try extracting the library from jar
if (extractAndLoadLibraryFile(snappyNativeLibraryPath, snappyNativeLibraryName, tempFolder)) {
// Temporary library folder. Use the value of java.io.tmpdir return;
String tempFolder = new File(System.getProperty("java.io.tmpdir")).getAbsolutePath(); }
// Try extracting the library from jar }
if (extractAndLoadLibraryFile(snappyNativeLibraryPath, snappyNativeLibraryName, tempFolder)) { try {
isLoaded = true; System.loadLibrary("snappy");
return; isLoaded = true;
} } catch (UnsatisfiedLinkError e) {
isLoaded = false;
isLoaded = false; }
return; return;
} }
private static void getNativeLibraryFolderForTheCurrentOS() { private static void getNativeLibraryFolderForTheCurrentOS() {
String osName = OSInfo.getOSName(); String osName = OSInfo.getOSName();
String archName = OSInfo.getArchName(); String archName = OSInfo.getArchName();
} }
public static int getMajorVersion() { public static int getMajorVersion() {
String[] c = getVersion().split("\\."); String[] c = getVersion().split("\\.");
return (c.length > 0) ? Integer.parseInt(c[0]) : 1; return (c.length > 0) ? Integer.parseInt(c[0]) : 1;
} }
public static int getMinorVersion() { public static int getMinorVersion() {
String[] c = getVersion().split("\\."); String[] c = getVersion().split("\\.");
return (c.length > 1) ? Integer.parseInt(c[1]) : 0; return (c.length > 1) ? Integer.parseInt(c[1]) : 0;
} }
public static String getVersion() { public static String getVersion() {
URL versionFile = LoadSnappy.class.getResource("/META-INF/maven/org.xerial.snappy/snappy-java/pom.properties"); URL versionFile = LoadSnappy.class.getResource("/META-INF/maven/org.xerial.snappy/snappy-java/pom.properties");
if (versionFile == null) if (versionFile == null)
versionFile = LoadSnappy.class.getResource("/META-INF/maven/org.xerial.snappy/snappy-java/VERSION"); versionFile = LoadSnappy.class.getResource("/META-INF/maven/org.xerial.snappy/snappy-java/VERSION");
String version = "unknown"; String version = "unknown";
try { try {
if (versionFile != null) { if (versionFile != null) {
Properties versionData = new Properties(); Properties versionData = new Properties();
versionData.load(versionFile.openStream()); versionData.load(versionFile.openStream());
version = versionData.getProperty("version", version); version = versionData.getProperty("version", version);
version = version.trim().replaceAll("[^0-9\\.]", ""); version = version.trim().replaceAll("[^0-9\\.]", "");
} }
} }
catch (IOException e) { catch (IOException e) {
System.err.println(e); System.err.println(e);
} }
return version; return version;
} }
} }