001package jmri.util;
002
003import java.io.File;
004import java.io.FileInputStream;
005import java.io.InputStream;
006import java.io.FileOutputStream;
007import java.io.IOException;
008import java.util.zip.ZipEntry;
009import java.util.zip.ZipInputStream;
010
011/**
012 * Unzip a local file or URL to into a specified directory
013 * <p>
014 * Largely from
015 * https://examples.javacodegeeks.com/core-java/util/zip/zipinputstream/java-unzip-file-example/
016 */
017public class UnzipFileClass {
018
019    /**
020     * Unzip contents into a directory.
021     *
022     * @param destinationFolder Destination for contents, created if need be;
023     *                          relative or absolute, but must be pre-expanded.
024     * @param zipFile           .zip file name; relative or absolute, but must
025     *                          be pre-expanded.
026     * @throws                  java.io.FileNotFoundException if File Not Found.
027     */
028    public static void unzipFunction(String destinationFolder, String zipFile) throws java.io.FileNotFoundException {
029        File directory = new File(destinationFolder);
030        FileInputStream fInput = new FileInputStream(zipFile);
031
032        unzipFunction(directory, fInput);
033    }
034
035    /**
036     * Unzip contents into a directory.
037     *
038     * @param directory Destination for contents, created if need be
039     * @param input     in .zip format
040     */
041    public static void unzipFunction(File directory, InputStream input) {
042        // if the output directory doesn't exist, create it
043        if (!directory.exists()) {
044            if (!directory.mkdirs()) {
045                log.error("Unable to create output directory {}", directory);
046            }
047        }
048        String destinationFolder = directory.getPath();
049
050        // buffer for read and write data to file
051        byte[] buffer = new byte[2048];
052
053        try (ZipInputStream zipInput = new ZipInputStream(input)) {
054
055            ZipEntry entry = zipInput.getNextEntry();
056
057            while (entry != null) {
058                String entryName = entry.getName();
059                File file = new File(destinationFolder + File.separator + entryName);
060
061                log.info("Unzip file {} to {}", entryName, file.getAbsolutePath());
062
063                // create the directories of the zip directory
064                if (entry.isDirectory()) {
065                    File newDir = new File(file.getAbsolutePath());
066                    if (!newDir.exists()) {
067                        boolean success = newDir.mkdirs();
068                        if (success == false) {
069                            log.error("Problem creating Folder {}", newDir);
070                        }
071                    }
072                } else {
073                    try (FileOutputStream fOutput = new FileOutputStream(file)) {
074                        int count = 0;
075                        while ((count = zipInput.read(buffer)) > 0) {
076                            // write 'count' bytes to the file output stream
077                            fOutput.write(buffer, 0, count);
078                        }
079                    } catch (IOException e) {
080                        log.error("Error writing unpacked zip file contents", e);
081                        return;
082                    }
083                }
084                // close ZipEntry and take the next one
085                zipInput.closeEntry();
086                entry = zipInput.getNextEntry();
087            }
088
089            // close the last ZipEntry
090            zipInput.closeEntry();
091
092            zipInput.close();
093            input.close();
094        } catch (IOException e) {
095            log.error("Error unpacking zip file", e);
096        }
097    }
098
099    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(UnzipFileClass.class);
100}