]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.lz4/src/net/jpountz/util/Native.java
Fixed org.simantics.lz4 to use bundle data area when running in OSGi
[simantics/platform.git] / bundles / org.simantics.lz4 / src / net / jpountz / util / Native.java
index c793f89fd1049157dae96b0304a189bb325655f7..b14b0728f0118bf1056a45b0d5eb24b8135f581e 100644 (file)
@@ -1,6 +1,4 @@
-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
@@ -12,12 +10,18 @@ package net.jpountz.util;
  * 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 {
@@ -62,61 +66,72 @@ 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);
     }
   }