--- /dev/null
+package net.jpountz.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * @author Tuukka Lehtonen
+ */
+public final class ChecksumUtil {
+
+ private static byte[] computeSum(InputStream in) throws IOException {
+ if (in == null)
+ throw new IllegalArgumentException("Input cannot be null!");
+
+ MessageDigest md;
+ try {
+ md = MessageDigest.getInstance("MD5");
+ } catch (NoSuchAlgorithmException e) {
+ throw new Error("MD5 digest must be supported by JVM");
+ }
+ byte[] data = new byte[64 * 1024];
+
+ while (true) {
+ int read = in.read(data);
+ if (read == -1) {
+ return md.digest();
+ }
+ md.update(data, 0, read);
+ }
+ }
+
+ public static byte[] computeSum(Path p) throws IOException {
+ try (InputStream in = Files.newInputStream(p)) {
+ return computeSum(in);
+ }
+ }
+
+ public static byte[] computeSum(URL url) throws IOException {
+ try (InputStream in = url.openStream()) {
+ return computeSum(in);
+ }
+ }
+
+}
-package net.jpountz.util;
-
-/*
+/**
* 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
* 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.
+ *
+ * Modified by Tuukka Lehtonen - Semantum Oy
+ * - allow extracting native library to designated directory
*/
+package net.jpountz.util;
-import java.io.File;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
/** FOR INTERNAL USE ONLY */
public enum Native {
}
private static boolean loaded = false;
+ private static boolean failedToLoad = false;
public static synchronized boolean isLoaded() {
return loaded;
}
+ public static boolean failedToLoad() {
+ return failedToLoad;
+ }
+
public static synchronized void load() {
- if (loaded) {
+ load(NativeParameters.extractionPath);
+ }
+
+ public static synchronized void load(Path extractionPath) {
+ if (loaded)
return;
- }
+ if (failedToLoad)
+ throw new UnsatisfiedLinkError("Native LZ4 dynamic library loading failed already. Not retrying.");
+
String resourceName = resourceName();
- InputStream is = Native.class.getResourceAsStream(resourceName);
- if (is == null) {
+ URL libraryUrl = Native.class.getResource(resourceName);
+ if (libraryUrl == null)
throw new UnsupportedOperationException("Unsupported OS/arch, cannot find " + resourceName + ". Please try building from source.");
- }
- File tempLib;
+
try {
- tempLib = File.createTempFile("liblz4-java", "." + os().libExtension);
- // copy to tempLib
- FileOutputStream out = new FileOutputStream(tempLib);
+ Path tempFile = null, out;
+ boolean extract = true;
+
try {
- byte[] buf = new byte[4096];
- while (true) {
- int read = is.read(buf);
- if (read == -1) {
- break;
+ if (extractionPath == null) {
+ out = tempFile = Files.createTempFile("liblz4-java", "." + os().libExtension);
+ } else {
+ out = extractionPath.resolve("liblz4-java." + os().libExtension);
+ if (Files.exists(out)) {
+ byte[] sourceHash = ChecksumUtil.computeSum(libraryUrl);
+ byte[] targetHash = ChecksumUtil.computeSum(out);
+ extract = !Arrays.equals(sourceHash, targetHash);
}
- out.write(buf, 0, read);
}
- try {
- out.close();
- out = null;
- } catch (IOException e) {
- // ignore
- }
- System.load(tempLib.getAbsolutePath());
+ if (extract)
+ copy(libraryUrl, out);
+ System.load(out.toString());
loaded = true;
} finally {
- try {
- if (out != null) {
- out.close();
- }
- } catch (IOException e) {
- // ignore
- }
- if (tempLib != null && tempLib.exists()) {
+ if (tempFile != null && Files.exists(tempFile)) {
if (!loaded) {
- tempLib.delete();
+ Files.deleteIfExists(tempFile);
} else {
- // try to delete on exit, does it work on Windows?
- tempLib.deleteOnExit();
+ // This probably doesn't work on Windows at all.
+ tempFile.toFile().deleteOnExit();
}
}
}
+ } catch (UnsatisfiedLinkError e) {
+ failedToLoad = true;
+ throw e;
} catch (IOException e) {
- throw new ExceptionInInitializerError("Cannot unpack liblz4-java");
+ failedToLoad = true;
+ throw new ExceptionInInitializerError("Cannot unpack liblz4-java");
+ }
+ }
+
+ private static long copy(URL url, Path to) throws IOException {
+ try (InputStream in = url.openStream()) {
+ return Files.copy(in, to);
}
}