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

com.github.jjYBdx4IL.utils.ResourceUtils Maven / Gradle / Ivy

The newest version!
/*
 * Copyright © 2014 jjYBdx4IL (https://github.com/jjYBdx4IL)
 *
 * 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.
 */
package com.github.jjYBdx4IL.utils;

//CHECKSTYLE:OFF
import com.sun.jna.Platform;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URISyntaxException;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author Github jjYBdx4IL Projects
 */
public class ResourceUtils {

    private static final Logger log = LoggerFactory.getLogger(ResourceUtils.class);

    protected static final Set libRegistry = new HashSet<>();

    /**
     * Loads native libraries from the classpath. Extracts from jar files if necessary. Follows the path
     * naming convention of JNA, {@link com.sun.jna.Platform#RESOURCE_PREFIX}. Strictly loads libraries from
     * the classpath. Ignores jni.library.path setting. This function will detect repeated loads of the same
     * library and silently skip any further loads using the same libName argument.
     *
     * @param libName the native library to load, ie. "fann" for "libfann.so" on Linux systems
     * @throws RuntimeException checked exception are wrapped in RuntimeException
     */
    public static synchronized void loadLibrary(String libName) {
        loadLibrary(libName, false);
    }

    /**
     * @see #loadLibrary(String)
     * @param libName the native library to load, ie. "fann" for "libfann.so" on Linux systems
     * @param deleteOnExit if true, delete unpacked library on VM exit, not before
     * @throws RuntimeException checked exception are wrapped in RuntimeException
     */
    public static synchronized void loadLibrary(String libName, boolean deleteOnExit) {
        if (libRegistry.contains(libName)) {
            log.debug("library " + libName + " already loaded, silently ignoring load request");
            return;
        }

        String mappedLibName = System.mapLibraryName(libName);
        String resourceId = "/" + Platform.RESOURCE_PREFIX + "/" + mappedLibName;
        log.debug("searching for " + resourceId);
        File extractedLib = null;
        try {
            extractedLib = extractResource(resourceId);
            log.debug("extracted resource to " + extractedLib.getPath());
            System.load(extractedLib.getPath());
            libRegistry.add(libName);
            log.debug(libName + " library loaded");
        } catch (IOException ex) {
            log.debug("failed to load library" + libName, ex);
            throw new RuntimeException(ex);
        } finally {
            if (extractedLib != null && extractedLib.exists()) {
                if (!extractedLib.delete()) {
                    log.debug("failed to delete " + extractedLib.getPath() + ", scheduling deletion for VM shutdown");
                    extractedLib.deleteOnExit();
                } else {
                    log.debug("deleted " + extractedLib.getPath());
                }
            }
        }
    }

    /**
     * Same as getClass().getResource(), but returns a {@link java.io.File} handle to an extracted file copy.
     * Beware: it's your duty to clean up this file, though it's created inside your system's temp folder.
     *
     * @param resourceId an absolute resourceId (ie. starts with "/")
     * @return the extracted file
     * @throws java.io.IOException if there was an I/O problem
     */
    public static File extractResource(String resourceId) throws IOException {
        if (resourceId == null || resourceId.isEmpty()) {
            throw new IllegalArgumentException("no resourceId given");
        }
        if (!resourceId.substring(0, 1).equals("/")) {
            throw new IllegalArgumentException("resourceId is not absolute");
        }
        try (InputStream is = ResourceUtils.class.getResourceAsStream(resourceId)) {
            if (is == null) {
                throw new IOException("resource not found: " + resourceId);
            }
            File tempFile = File.createTempFile("extractedResource", ".tmp");
            try (OutputStream os = new FileOutputStream(tempFile)) {
                IOUtils.copy(is, os);
            } catch (IOException ex) {
                if (!tempFile.delete()) {
                    tempFile.deleteOnExit();
                }
                throw ex;
            }
            return tempFile;
        }
    }

    /**
     * Get a {@link java.io.File} to a resource. Because you don't give this method a class, only
     * absolute resource IDs are usually sensible choices. This function only works for
     * extracted resources, not for resource packed inside jars. The function will throw only unchecked
     * exceptions and is mainly useful for static initializers and test units.
     * 
     * @param resourceId the resource path, preferably an absolute one
     * @return the resource
     */
    public static File getResFileUnchecked(String resourceId) {
        return getResFileUnchecked(ResourceUtils.class, resourceId);
    }

    /**
     * Get a {@link java.io.File} to a resource. The resourceId argument can be relative, it will be resolved
     * relative to the resourceClass argument. This function only works for
     * extracted resources, not for resource packed inside jars. The function will throw only unchecked
     * exceptions and is mainly useful for static initializers and test units.
     *
     * @param resourceClass the class
     * @param resourceId the resource path, sensibly a relative one
     * @return the resource
     */
    public static File getResFileUnchecked(Class resourceClass, String resourceId) {
        try {
            return new File(resourceClass.getResource(resourceId).toURI());
        } catch (URISyntaxException ex) {
            throw new RuntimeException(ex);
        }
    }

    private ResourceUtils() {
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy