All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.weisj.darklaf.platform.NativeUtil Maven / Gradle / Ivy

There is a newer version: 3.0.2
Show newest version
/*
 * MIT License
 *
 * Copyright (c) 2020 Jannis Weis
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */
package com.github.weisj.darklaf.platform;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.*;

/**
 * A simple library class which helps with loading dynamic libraries stored in the JAR archive. These libraries usually
 * contain implementation of some methods in native code (using JNI - Java Native Interface).
 *
 * @see http://adamheinrich.com/blog/2012/how-to-load-native-jni-library-from-jar
 * @see https://github.com/adamheinrich/native-utils
 */
public class NativeUtil {

    public static final String NATIVE_FOLDER_PATH_PREFIX = "nativeutils";
    /**
     * The minimum length a prefix for a file has to have according to {@link File#createTempFile(String, String)}}.
     */
    private static final int MIN_PREFIX_LENGTH = 3;
    /**
     * Temporary directory which will contain the DLLs.
     */
    private static Path temporaryDir;

    private NativeUtil() {}

    /**
     * Loads library from current JAR archive
     * 

* The file from JAR is copied into system temporary directory and then loaded. The temporary file is deleted after * exiting. Method uses String as filename because the pathname is "abstract", not system-dependent. * * @param path The path of file inside JAR as absolute path (beginning with '/'), e.g. * /package/File.ext * @throws IOException If temporary file creation or read/write operation fails * @throws IllegalArgumentException If source file (param path) does not exist * @throws IllegalArgumentException If the path is not absolute or if the filename is shorter than three characters * (restriction of {@link File#createTempFile(java.lang.String, * java.lang.String)}). * @throws FileNotFoundException If the file could not be found inside the JAR. */ public static void loadLibraryFromJar(final String path) throws IOException { if (null == path || !path.startsWith("/")) { throw new IllegalArgumentException("The path has to be absolute (start with '/')."); } // Obtain filename from path String[] parts = path.split("/"); String filename = (parts.length > 1) ? parts[parts.length - 1] : null; // Check if the filename is okay if (filename == null || filename.length() < MIN_PREFIX_LENGTH) { throw new IllegalArgumentException("The filename has to be at least 3 characters long."); } // Prepare temporary file if (temporaryDir == null) { temporaryDir = createTempDirectory(NATIVE_FOLDER_PATH_PREFIX); temporaryDir.toFile().deleteOnExit(); } Path temp = temporaryDir.resolve(filename); try (InputStream is = NativeUtil.class.getResourceAsStream(path)) { if (!temporaryDir.toFile().canWrite()) throw new IOException("Can't write to temporary directory."); Files.copy(is, temp.toAbsolutePath(), StandardCopyOption.REPLACE_EXISTING); } catch (IOException e) { delete(temp); throw e; } catch (NullPointerException e) { delete(temp); throw new FileNotFoundException("File " + path + " was not found inside JAR."); } try { System.load(temp.toAbsolutePath().toString()); } finally { if (isPosixCompliant()) { // Assume POSIX compliant file system, can be deleted after loading delete(temp); } else { // Assume non-POSIX, and don't delete until last file descriptor closed temp.toFile().deleteOnExit(); } } } private static void delete(final Path path) { try { Files.deleteIfExists(path); } catch (IOException ignored) {} } private static Path createTempDirectory(final String prefix) throws IOException { return Files.createTempDirectory(prefix + System.nanoTime()); } private static boolean isPosixCompliant() { try { return FileSystems.getDefault() .supportedFileAttributeViews() .contains("posix"); } catch (FileSystemNotFoundException | ProviderNotFoundException | SecurityException e) { return false; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy