/** * 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 * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * 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.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 enum OS { // Even on Windows, the default compiler from cpptasks (gcc) uses .so as a shared lib extension WINDOWS("win32", "dll"), LINUX("linux", "so"), MAC("darwin", "dylib"), SOLARIS("solaris", "so"); public final String name, libExtension; private OS(String name, String libExtension) { this.name = name; this.libExtension = libExtension; } } private static String arch() { return System.getProperty("os.arch"); } private static OS os() { String osName = System.getProperty("os.name"); if (osName.contains("Linux")) { return OS.LINUX; } else if (osName.contains("Mac")) { return OS.MAC; } else if (osName.contains("Windows")) { return OS.WINDOWS; } else if (osName.contains("Solaris") || osName.contains("SunOS")) { return OS.SOLARIS; } else { throw new UnsupportedOperationException("Unsupported operating system: " + osName); } } private static String resourceName() { OS os = os(); String packagePrefix = Native.class.getPackage().getName().replace('.', '/'); return "/" + packagePrefix + "/" + os.name + "/" + arch() + "/liblz4-java." + os.libExtension; } 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() { 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(); URL libraryUrl = Native.class.getResource(resourceName); if (libraryUrl == null) throw new UnsupportedOperationException("Unsupported OS/arch, cannot find " + resourceName + ". Please try building from source."); try { Path tempFile = null, out; boolean extract = true; try { 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); } } if (extract) copy(libraryUrl, out); System.load(out.toString()); loaded = true; } finally { if (tempFile != null && Files.exists(tempFile)) { if (!loaded) { Files.deleteIfExists(tempFile); } else { // This probably doesn't work on Windows at all. tempFile.toFile().deleteOnExit(); } } } } catch (UnsatisfiedLinkError e) { failedToLoad = true; throw e; } catch (IOException e) { 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); } } }