package org.jboss.windup.util; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.logging.Logger; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import org.jboss.forge.furnace.util.Streams; import org.jboss.windup.util.exception.WindupException; /** * @author <a href="mailto:jesse.sightler@gmail.com">Jesse Sightler</a> * @author <a href="http://ondra.zizka.cz/">Ondrej Zizka, zizka@seznam.cz</a> */ public class ZipUtil { private static final Logger log = Logger.getLogger(ZipUtil.class.getName()); private static Set<String> supportedExtensions; /** * Unzip a classpath resource using the given {@link Class} as the resource root path. */ public static void unzipFromClassResource(Class<?> clazz, String resourcePath, File extractToPath) throws IOException { File inputFile = File.createTempFile("windup-resource-to-unzip-", ".zip"); try { try (final InputStream stream = clazz.getResourceAsStream(resourcePath)) { FileUtils.copyInputStreamToFile(stream, inputFile); } extractToPath.mkdirs(); ZipUtil.unzipToFolder(inputFile, extractToPath); } finally { inputFile.delete(); } } /** * Unzip the given {@link File} to the specified directory. */ public static void unzipToFolder(File inputFile, File outputDir) throws IOException { if (inputFile == null) throw new IllegalArgumentException("Argument inputFile is null."); if (outputDir == null) throw new IllegalArgumentException("Argument outputDir is null."); try (ZipFile zipFile = new ZipFile(inputFile)) { Enumeration<? extends ZipEntry> entryEnum = zipFile.entries(); while (entryEnum.hasMoreElements()) { ZipEntry entry = entryEnum.nextElement(); String entryName = entry.getName(); File destFile = new File(outputDir, entryName); if (!entry.isDirectory()) { File parentDir = destFile.getParentFile(); if (!parentDir.isDirectory() && !parentDir.mkdirs()) { throw new WindupException("Unable to create directory: " + parentDir.getAbsolutePath()); } try (InputStream zipInputStream = zipFile.getInputStream(entry)) { try (FileOutputStream outputStream = new FileOutputStream(destFile)) { Streams.write(zipInputStream, outputStream); } } } } } } public static String getEndsWithZipRegularExpression() { Set<String> zipExtensions = getZipExtensions(); final String regex; if (zipExtensions.size() == 1) { regex = ".+\\." + zipExtensions.iterator().next() + "$"; } else { StringBuilder builder = new StringBuilder(); builder.append("\\b("); for (String value : zipExtensions) { builder.append("|"); builder.append(value); } builder.append(")\\b"); regex = ".+\\." + builder.toString() + "$"; } return regex; } public static boolean endsWithZipExtension(String path) { for (String extension : getZipExtensions()) { if (StringUtils.endsWith(path, "." + extension)) { return true; } } return false; } public static Set<String> getZipExtensions() { if (supportedExtensions == null) { Set<String> extensions = new HashSet<>(); extensions.add("war"); extensions.add("ear"); extensions.add("jar"); extensions.add("sar"); extensions.add("rar"); supportedExtensions = extensions; } return supportedExtensions; } public static List<String> scanZipFile(Path zipFilePath, boolean relativeOnly) { try { try (final InputStream is = new FileInputStream(zipFilePath.toFile())) { return scanZipFile(zipFilePath.normalize().toString(), is, relativeOnly); } } catch (IOException e) { System.err.println("Could not read file: " + zipFilePath + " due to: " + e.getMessage()); return Collections.emptyList(); } } public static List<String> scanZipFile(String parentPath, InputStream is, boolean relativeOnly) { try { ZipInputStream zis = new ZipInputStream(is); ZipEntry entry; List<String> results = new ArrayList<>(); while ((entry = zis.getNextEntry()) != null) { String fullPath = parentPath + "/" + entry.getName(); results.add(relativeOnly ? entry.getName() : fullPath); if (!entry.isDirectory() && ZipUtil.endsWithZipExtension(entry.getName())) { results.addAll(scanZipFile(fullPath, zis, relativeOnly)); } } return results; } catch (IOException e) { System.err.println("Could not read file: " + parentPath + " due to: " + e.getMessage()); return Collections.emptyList(); } } }