package com.github.webdriverextensions.newversion; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream; import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; import org.apache.commons.io.FilenameUtils; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; import java.nio.file.*; import java.util.regex.Pattern; public class FileExtractorImpl implements FileExtractor { private final Pattern extractPattern; private final PathMatcher TAR_BZ2 = FileSystems.getDefault().getPathMatcher("glob:**.tar.bz2"); private final PathMatcher TAR_GZ = FileSystems.getDefault().getPathMatcher("glob:**.tar.gz"); private final PathMatcher BZ2 = FileSystems.getDefault().getPathMatcher("glob:**.bz2"); private final PathMatcher GZ = FileSystems.getDefault().getPathMatcher("glob:**.gz"); private final PathMatcher TAR = FileSystems.getDefault().getPathMatcher("glob:**.tar"); private final PathMatcher ZIP = FileSystems.getDefault().getPathMatcher("glob:**.zip"); public FileExtractorImpl(String extractPattern) { this.extractPattern = extractPattern == null ? null : Pattern.compile(extractPattern); } @Override public boolean isExtractable(Path file) { return TAR_BZ2.matches(file) || TAR_GZ.matches(file) || BZ2.matches(file) || GZ.matches(file) || TAR.matches(file) || ZIP.matches(file); } @Override public void extractFile(Path file, Path toDirectory) { try { if (TAR_BZ2.matches(file)) { extractTarBz2File(file, toDirectory); } else if (TAR_GZ.matches(file)) { extractTarGzFile(file, toDirectory); } else if (BZ2.matches(file)) { extractBz2File(file, toDirectory); } else if (GZ.matches(file)) { extractGzFile(file, toDirectory); } else if (TAR.matches(file)) { extractTarFile(file, toDirectory); } else if (ZIP.matches(file)) { extractZipFile(file, toDirectory); } } catch (IOException e) { throw new RuntimeException(e); } } private void extractBz2File(Path file, Path toDirectory) throws IOException { String extractedFilename = FilenameUtils.getBaseName(file.toString()); Path fileToExtract = toDirectory.resolve(extractedFilename); try (FileInputStream fin = new FileInputStream(file.toFile())) { try (BufferedInputStream bin = new BufferedInputStream(fin)) { try (BZip2CompressorInputStream bzip2Archive = new BZip2CompressorInputStream(bin)) { Files.copy(bzip2Archive, fileToExtract); } } } } private void extractGzFile(Path file, Path toDirectory) throws IOException { String extractedFilename = FilenameUtils.getBaseName(file.toString()); Path fileToExtract = toDirectory.resolve(extractedFilename); try (FileInputStream fin = new FileInputStream(file.toFile())) { try (BufferedInputStream bin = new BufferedInputStream(fin)) { try (GzipCompressorInputStream gzipArchive = new GzipCompressorInputStream(bin)) { Files.copy(gzipArchive, fileToExtract); } } } } private void extractTarFile(Path file, Path toDirectory) throws IOException { Files.createDirectories(toDirectory); try (FileInputStream fis = new FileInputStream(file.toFile())) { try (BufferedInputStream bis = new BufferedInputStream(fis)) { try (TarArchiveInputStream tarArchive = new TarArchiveInputStream(bis)) { extractTar(toDirectory, tarArchive); } } } } private void extractTarBz2File(Path file, Path toDirectory) throws IOException { Files.createDirectories(toDirectory); try (FileInputStream fin = new FileInputStream(file.toFile())) { try (BufferedInputStream bin = new BufferedInputStream(fin)) { try (BZip2CompressorInputStream bzip2Archive = new BZip2CompressorInputStream(bin)) { try (TarArchiveInputStream tarArchive = new TarArchiveInputStream(bzip2Archive)) { extractTar(toDirectory, tarArchive); } } } } } private void extractTar(Path toDirectory, TarArchiveInputStream tarArchive) throws IOException { for (TarArchiveEntry tarEntry = tarArchive.getNextTarEntry(); tarEntry != null; tarEntry = tarArchive.getNextTarEntry()) { if (tarEntry.isDirectory()) { if (extractPattern != null) { continue; } Files.createDirectories(toDirectory.resolve(tarEntry.getName())); } else { if (tarEntry.isSymbolicLink()) { continue; } extractPattern(toDirectory, tarArchive, tarEntry); } } } private void extractPattern(Path toDirectory, TarArchiveInputStream tarArchive, TarArchiveEntry tarEntry) throws IOException { if (extractPattern != null) { if (!extractPattern.matcher(tarEntry.getName()).matches()) { return; } Path filename = Paths.get(tarEntry.getName()).getFileName(); Path fileToExtract = toDirectory.resolve(filename); Files.copy(tarArchive, fileToExtract); } else { Path fileToExtract = toDirectory.resolve(tarEntry.getName()); Files.copy(tarArchive, fileToExtract); } } private void extractTarGzFile(Path file, Path toDirectory) throws IOException { Files.createDirectories(toDirectory); try (FileInputStream fin = new FileInputStream(file.toFile())) { try (BufferedInputStream bin = new BufferedInputStream(fin)) { try (GzipCompressorInputStream gzipArchive = new GzipCompressorInputStream(bin)) { try (TarArchiveInputStream tarArchive = new TarArchiveInputStream(gzipArchive)) { extractTar(toDirectory, tarArchive); } } } } } private void extractZipFile(Path file, Path toDirectory) throws IOException { Files.createDirectories(toDirectory); try (FileInputStream fis = new FileInputStream(file.toFile())) { try (BufferedInputStream bis = new BufferedInputStream(fis)) { try (ZipArchiveInputStream zipArchive = new ZipArchiveInputStream(bis)) { for (ZipArchiveEntry zipEntry = zipArchive.getNextZipEntry(); zipEntry != null; zipEntry = zipArchive.getNextZipEntry()) { if (zipEntry.isDirectory()) { if (extractPattern != null) { continue; } Files.createDirectories(toDirectory.resolve(zipEntry.getName())); } else { if (zipEntry.isUnixSymlink()) { continue; } if (extractPattern != null) { if (!extractPattern.matcher(zipEntry.getName()).matches()) { continue; } Path filename = Paths.get(zipEntry.getName()).getFileName(); Path fileToExtract = toDirectory.resolve(filename); Files.copy(zipArchive, fileToExtract); } else { Path fileToExtract = toDirectory.resolve(zipEntry.getName()); Files.copy(zipArchive, fileToExtract); } } } } } } } }