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

io.microsphere.util.jar.JarUtils Maven / Gradle / Ivy

The newest version!
/**
 *
 */
package io.microsphere.util.jar;

import io.microsphere.constants.ProtocolConstants;
import io.microsphere.filter.JarEntryFilter;

import javax.annotation.Nonnull;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import static io.microsphere.collection.ListUtils.ofList;
import static io.microsphere.constants.ProtocolConstants.FILE_PROTOCOL;
import static io.microsphere.constants.ProtocolConstants.JAR_PROTOCOL;
import static io.microsphere.constants.SeparatorConstants.ARCHIVE_ENTRY_SEPARATOR;
import static io.microsphere.io.IOUtils.close;
import static io.microsphere.io.IOUtils.copy;
import static io.microsphere.net.URLUtils.decode;
import static io.microsphere.net.URLUtils.normalizePath;
import static io.microsphere.net.URLUtils.resolveArchiveFile;
import static io.microsphere.text.FormatUtils.format;
import static io.microsphere.util.StringUtils.substringAfter;
import static java.util.Collections.emptyList;
import static java.util.Collections.unmodifiableList;

/**
 * Jar Utility class
 *
 * @author Mercy
 * @version 1.0.0
 * @see JarEntry
 * @see JarFile
 * @since 1.0.0
 */
public class JarUtils {

    /**
     * Create a {@link JarFile} from specified {@link URL} of {@link JarFile}
     *
     * @param jarURL {@link URL} of {@link JarFile} or {@link JarEntry}
     * @return JarFile
     * @throws IOException If {@link JarFile jar file} is invalid, see {@link JarFile#JarFile(String)}
     * @version 1.0.0
     * @since 1.0.0
     */
    public static JarFile toJarFile(URL jarURL) throws IOException {
        JarFile jarFile = null;
        final String jarAbsolutePath = resolveJarAbsolutePath(jarURL);
        if (jarAbsolutePath == null)
            return null;
        jarFile = new JarFile(jarAbsolutePath);
        return jarFile;
    }

    /**
     * Assert jarURL argument is valid , only supported protocols : {@link ProtocolConstants#JAR_PROTOCOL jar} and
     * {@link ProtocolConstants#FILE_PROTOCOL file}
     *
     * @param jarURL {@link URL} of {@link JarFile} or {@link JarEntry}
     * @throws NullPointerException     If jarURL is null
     * @throws IllegalArgumentException If {@link URL#getProtocol()} is not {@link ProtocolConstants#JAR_PROTOCOL jar} or {@link ProtocolConstants#FILE_PROTOCOL
     *                                  file}
     */
    protected static void assertJarURLProtocol(URL jarURL) throws NullPointerException, IllegalArgumentException {
        final String protocol = jarURL.getProtocol(); //NPE check
        if (!JAR_PROTOCOL.equals(protocol) && !FILE_PROTOCOL.equals(protocol)) {
            String message = format("jarURL Protocol['{}'] is unsupported ,except '{}' and '{}' ", protocol, JAR_PROTOCOL, FILE_PROTOCOL);
            throw new IllegalArgumentException(message);
        }
    }

    /**
     * Resolve Relative path from Jar URL
     *
     * @param jarURL {@link URL} of {@link JarFile} or {@link JarEntry}
     * @return Non-null
     * @throws NullPointerException     see {@link #assertJarURLProtocol(URL)}
     * @throws IllegalArgumentException see {@link #assertJarURLProtocol(URL)}
     */
    @Nonnull
    public static String resolveRelativePath(URL jarURL) throws NullPointerException, IllegalArgumentException {
        assertJarURLProtocol(jarURL);
        String form = jarURL.toExternalForm();
        String relativePath = substringAfter(form, ARCHIVE_ENTRY_SEPARATOR);
        relativePath = normalizePath(relativePath);
        return decode(relativePath);
    }

    /**
     * Resolve absolute path from the {@link URL} of {@link JarEntry}
     *
     * @param jarURL {@link URL} of {@link JarFile} or {@link JarEntry}
     * @return If {@link URL#getProtocol()} equals jar or file , resolves absolute path, or
     * return null
     * @throws NullPointerException     see {@link #assertJarURLProtocol(URL)}
     * @throws IllegalArgumentException see {@link #assertJarURLProtocol(URL)}
     * @version 1.0.0
     * @since 1.0.0
     */
    @Nonnull
    public static String resolveJarAbsolutePath(URL jarURL) throws NullPointerException, IllegalArgumentException {
        assertJarURLProtocol(jarURL);
        File archiveFile = resolveArchiveFile(jarURL);
        return archiveFile == null ? null : archiveFile.getAbsolutePath();
    }

    /**
     * Filter {@link JarEntry} list from {@link JarFile}
     *
     * @param jarFile        {@link JarFile}
     * @param jarEntryFilter {@link JarEntryFilter}
     * @return Read-only List
     */
    @Nonnull
    public static List filter(JarFile jarFile, JarEntryFilter jarEntryFilter) {
        if (jarFile == null) {
            return emptyList();
        }
        Enumeration jarEntries = jarFile.entries();
        List jarEntriesList = ofList(jarEntries);
        return doFilter(jarEntriesList, jarEntryFilter);
    }

    protected static List doFilter(Iterable jarEntries, JarEntryFilter jarEntryFilter) {
        List jarEntriesList = new LinkedList<>();
        for (JarEntry jarEntry : jarEntries) {
            if (jarEntryFilter == null || jarEntryFilter.accept(jarEntry)) {
                jarEntriesList.add(jarEntry);
            }
        }
        return unmodifiableList(jarEntriesList);
    }

    /**
     * Find {@link JarEntry} from specified url
     *
     * @param jarURL jar resource url
     * @return If found , return {@link JarEntry}
     */
    public static JarEntry findJarEntry(URL jarURL) throws IOException {
        JarFile jarFile = toJarFile(jarURL);
        final String relativePath = resolveRelativePath(jarURL);
        JarEntry jarEntry = jarFile.getJarEntry(relativePath);
        return jarEntry;
    }


    /**
     * Extract the source {@link JarFile} to target directory
     *
     * @param jarSourceFile   the source {@link JarFile}
     * @param targetDirectory target directory
     * @throws IOException When the source jar file is an invalid {@link JarFile}
     */
    public static void extract(File jarSourceFile, File targetDirectory) throws IOException {
        extract(jarSourceFile, targetDirectory, null);
    }

    /**
     * Extract the source {@link JarFile} to target directory with specified {@link JarEntryFilter}
     *
     * @param jarSourceFile   the source {@link JarFile}
     * @param targetDirectory target directory
     * @param jarEntryFilter  {@link JarEntryFilter}
     * @throws IOException When the source jar file is an invalid {@link JarFile}
     */
    public static void extract(File jarSourceFile, File targetDirectory, JarEntryFilter jarEntryFilter) throws IOException {

        final JarFile jarFile = new JarFile(jarSourceFile);

        extract(jarFile, targetDirectory, jarEntryFilter);
    }

    /**
     * Extract the source {@link JarFile} to target directory with specified {@link JarEntryFilter}
     *
     * @param jarFile         the source {@link JarFile}
     * @param targetDirectory target directory
     * @param jarEntryFilter  {@link JarEntryFilter}
     * @throws IOException When the source jar file is an invalid {@link JarFile}
     */
    public static void extract(JarFile jarFile, File targetDirectory, JarEntryFilter jarEntryFilter) throws IOException {
        List jarEntriesList = filter(jarFile, jarEntryFilter);
        doExtract(jarFile, jarEntriesList, targetDirectory);
    }

    /**
     * Extract the source {@link JarFile} to target directory with specified {@link JarEntryFilter}
     *
     * @param jarResourceURL  The resource URL of {@link JarFile} or {@link JarEntry}
     * @param targetDirectory target directory
     * @param jarEntryFilter  {@link JarEntryFilter}
     * @throws IOException When the source jar file is an invalid {@link JarFile}
     */
    public static void extract(URL jarResourceURL, File targetDirectory, JarEntryFilter jarEntryFilter) throws IOException {
        final JarFile jarFile = toJarFile(jarResourceURL);
        final String relativePath = resolveRelativePath(jarResourceURL);
        final JarEntry jarEntry = jarFile.getJarEntry(relativePath);
        final boolean isDirectory = jarEntry.isDirectory();
        List jarEntriesList = filter(jarFile, new JarEntryFilter() {
            @Override
            public boolean accept(JarEntry filteredObject) {
                String name = filteredObject.getName();
                if (isDirectory && name.equals(relativePath)) {
                    return true;
                } else return name.startsWith(relativePath);
            }
        });

        jarEntriesList = doFilter(jarEntriesList, jarEntryFilter);

        doExtract(jarFile, jarEntriesList, targetDirectory);
    }

    protected static void doExtract(JarFile jarFile, Iterable jarEntries, File targetDirectory) throws IOException {
        if (jarEntries != null) {
            for (JarEntry jarEntry : jarEntries) {
                String jarEntryName = jarEntry.getName();
                File targetFile = new File(targetDirectory, jarEntryName);
                if (jarEntry.isDirectory()) {
                    targetFile.mkdirs();
                } else {
                    InputStream inputStream = null;
                    OutputStream outputStream = null;
                    try {
                        inputStream = jarFile.getInputStream(jarEntry);
                        if (inputStream != null) {
                            File parentFile = targetFile.getParentFile();
                            if (!parentFile.exists()) {
                                parentFile.mkdirs();
                            }
                            outputStream = new FileOutputStream(targetFile);
                            copy(inputStream, outputStream);
                        }
                    } finally {
                        close(outputStream);
                        close(inputStream);
                    }
                }
            }
        }
    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy