]> gerrit.simantics Code Review - simantics/platform.git/blob - 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
1 /**
2  * Licensed under the Apache License, Version 2.0 (the "License");
3  * you may not use this file except in compliance with the License.
4  * You may obtain a copy of the License at
5  *
6  *     http://www.apache.org/licenses/LICENSE-2.0
7  *
8  * Unless required by applicable law or agreed to in writing, software
9  * distributed under the License is distributed on an "AS IS" BASIS,
10  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11  * See the License for the specific language governing permissions and
12  * limitations under the License.
13  *
14  * Modified by Tuukka Lehtonen - Semantum Oy
15  *  - allow extracting native library to designated directory
16  */
17 package net.jpountz.util;
18
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.net.URL;
22 import java.nio.file.Files;
23 import java.nio.file.Path;
24 import java.util.Arrays;
25
26 /** FOR INTERNAL USE ONLY */
27 public enum Native {
28   ;
29
30   private enum OS {
31     // Even on Windows, the default compiler from cpptasks (gcc) uses .so as a shared lib extension
32     WINDOWS("win32", "dll"), LINUX("linux", "so"), MAC("darwin", "dylib"), SOLARIS("solaris", "so");
33     public final String name, libExtension;
34
35     private OS(String name, String libExtension) {
36       this.name = name;
37       this.libExtension = libExtension;
38     }
39   }
40
41   private static String arch() {
42     return System.getProperty("os.arch");
43   }
44
45   private static OS os() {
46     String osName = System.getProperty("os.name");
47     if (osName.contains("Linux")) {
48       return OS.LINUX;
49     } else if (osName.contains("Mac")) {
50       return OS.MAC;
51     } else if (osName.contains("Windows")) {
52       return OS.WINDOWS;
53     } else if (osName.contains("Solaris") || osName.contains("SunOS")) {
54       return OS.SOLARIS;
55     } else {
56       throw new UnsupportedOperationException("Unsupported operating system: "
57           + osName);
58     }
59   }
60
61   private static String resourceName() {
62     OS os = os();
63     String packagePrefix = Native.class.getPackage().getName().replace('.', '/');
64
65     return "/" + packagePrefix + "/" + os.name + "/" + arch() + "/liblz4-java." + os.libExtension;
66   }
67
68   private static boolean loaded = false;
69   private static boolean failedToLoad = false;
70
71   public static synchronized boolean isLoaded() {
72     return loaded;
73   }
74
75   public static boolean failedToLoad() {
76     return failedToLoad;
77   }
78
79   public static synchronized void load() {
80     load(NativeParameters.extractionPath);
81   }
82
83   public static synchronized void load(Path extractionPath) {
84     if (loaded)
85       return;
86     if (failedToLoad)
87       throw new UnsatisfiedLinkError("Native LZ4 dynamic library loading failed already. Not retrying.");
88
89     String resourceName = resourceName();
90     URL libraryUrl = Native.class.getResource(resourceName);
91     if (libraryUrl == null)
92       throw new UnsupportedOperationException("Unsupported OS/arch, cannot find " + resourceName + ". Please try building from source.");
93
94     try {
95       Path tempFile = null, out;
96       boolean extract = true;
97
98       try {
99         if (extractionPath == null) {
100           out = tempFile = Files.createTempFile("liblz4-java", "." + os().libExtension);
101         } else {
102           out = extractionPath.resolve("liblz4-java." + os().libExtension);
103           if (Files.exists(out)) {
104             byte[] sourceHash = ChecksumUtil.computeSum(libraryUrl);
105             byte[] targetHash = ChecksumUtil.computeSum(out);
106             extract = !Arrays.equals(sourceHash, targetHash);
107           }
108         }
109         if (extract)
110           copy(libraryUrl, out);
111         System.load(out.toString());
112         loaded = true;
113       } finally {
114         if (tempFile != null && Files.exists(tempFile)) {
115           if (!loaded) {
116             Files.deleteIfExists(tempFile);
117           } else {
118             // This probably doesn't work on Windows at all.
119             tempFile.toFile().deleteOnExit();
120           }
121         }
122       }
123     } catch (UnsatisfiedLinkError e) {
124       failedToLoad = true;
125       throw e;
126     } catch (IOException e) {
127       failedToLoad = true;
128       throw new ExceptionInInitializerError("Cannot unpack liblz4-java");
129     }
130   }
131
132   private static long copy(URL url, Path to) throws IOException {
133     try (InputStream in = url.openStream()) {
134       return Files.copy(in, to);
135     }
136   }
137
138 }