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

automately.core.util.file.ZipUtil Maven / Gradle / Ivy

package automately.core.util.file;

import java.io.IOException;
import java.net.URI;
import java.nio.file.*;
import java.util.*;

/**
 * The ZipUtil is a simple zip utility that is used by Automately Core. It provides
 * basic zip and unzip functionality along with the ability to by default exclude files.
 */
public class ZipUtil {

    /**
     * Returns a zip file system
     * @param zipFilename to construct the file system from
     * @param create true if the zip file should be created
     * @return a zip file system
     * @throws IOException
     */
    private static FileSystem createZipFileSystem(String zipFilename,
                                                  boolean create)
            throws IOException {
        // convert the filename to a URI
        final Path path = Paths.get(zipFilename);
        final URI uri = URI.create("jar:file:" + path.toUri().getPath());

        final Map env = new HashMap<>();
        if (create) {
            env.put("create", "true");
        }
        return FileSystems.newFileSystem(uri, env);
    }

    public static void unzip(String zipFilename, String destDirname)
            throws IOException{

        final Path destDir = Paths.get(destDirname);
        //if the destination doesn't exist, create it
        if(Files.notExists(destDir)){
            Files.createDirectories(destDir);
        }

        try (FileSystem zipFileSystem = createZipFileSystem(zipFilename, false)){
            final Path root = zipFileSystem.getPath("/");

            Path[] files = Files.walk(root)
                    .filter(Files::isRegularFile).toArray(Path[]::new);

            for(Path file : files){
                Path dest = Paths.get(destDir.toString(), file.toString());
                if(Files.notExists(dest.getParent())){
                    Files.createDirectories(dest.getParent());
                }
                Files.copy(file, dest, StandardCopyOption.REPLACE_EXISTING);
            }
        }
    }

    public static void create(String zipFilename, String directory) throws IOException {
        create(zipFilename, directory, new Object[0]);
    }

    public static void create(String zipFilename, String directory , Object[] ignored)
            throws IOException {

        try (FileSystem zipFileSystem = createZipFileSystem(zipFilename, true)) {
            final Path root = zipFileSystem.getPath("/");

            final Path src = Paths.get(directory);
            //add a file to the zip file system
            if(!Files.isDirectory(src)){
                throw new RuntimeException(directory + " is not a valid directory");
            } else{
                Path[] files = Files.walk(src)
                        .filter(Files::isRegularFile).toArray(Path[]::new);

                for(Path file : files){

                    Set shouldIgnore = new HashSet<>();
                    Collections.addAll(shouldIgnore, ignored);
                    boolean ignore = IgnoredFiles.check(file.normalize().toAbsolutePath().toString(), shouldIgnore);
                    if(ignore){
                        continue;
                    }
                    Path relPath = src.relativize(file);
                    Path dest = zipFileSystem.getPath(root.toString(),
                            relPath.toString());
                    // This will force any directories that don't exist to be created.
                    if(Files.notExists(dest.getParent())){
                        Files.createDirectories(dest.getParent());
                    }
                    Files.copy(file, dest, StandardCopyOption.REPLACE_EXISTING);
                }
            }
        }
    }

    /**
     * IgnoredFiles is a static class used by the ZipUtil to provide a simple way to add default
     * rules for the ZipUtil to ignore.
     */
    public static class IgnoredFiles {

        private static Set DEFAULT_IGNORED_FILES;

        static {
            /*
            By default we ignore certain files such as git and IntelliJ projects
             */
            Set ignoredFiles = new HashSet<>();
            ignoredFiles.add(".*\\.git.*");
            ignoredFiles.add(".*\\.idea.*");
            ignoredFiles.add(".*\\.gitignore");
            ignoredFiles.add(".*\\.iml");
            DEFAULT_IGNORED_FILES = ignoredFiles;
        }

        public static Set getDefaultRules(){
            return DEFAULT_IGNORED_FILES;
        }

        /**
         * Checks a file location if it should be ignored or not.
         *
         * @param file the file location to check
         * @return returns true if the file should be ignored
         */
        public static boolean check(String file){
            return check(file, null);
        }

        /**
         * Checks a file location if it should be ignored or not.
         *
         * @param file the file location to check
         * @param ignoredFiles files to ignore;
         * @return returns true if the file should be ignored
         */
        public static boolean check(String file, Set ignoredFiles){
            Set rules = new HashSet<>();
            if(ignoredFiles != null){
                rules.addAll(ignoredFiles);
            }
            rules.addAll(DEFAULT_IGNORED_FILES);
            for(Object rule : rules){
                if(rule instanceof String){
                    try {
                        String pattern = (String) rule;
                        if(file.matches(pattern)){
                            return true;
                        }
                    } catch (Exception ignored){
                        ignored.printStackTrace();
                    }
                }
            }
            return false;
        }
    }
}