package com.elastic.support.util; import com.elastic.support.Constants; import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.ArchiveInputStream; import org.apache.commons.compress.archivers.ArchiveOutputStream; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; import org.apache.commons.compress.archivers.zip.ZipFile; import org.apache.commons.compress.compressors.CompressorOutputStream; import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream; import org.apache.commons.io.*; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.io.*; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.Enumeration; import java.util.List; import java.util.Vector; public class ArchiveUtils { private static final Logger logger = LogManager.getLogger(ArchiveUtils.class); public static void createArchive(String dir, String archiveFileName) { if(! createZipArchive(dir, archiveFileName)){ logger.error(Constants.CONSOLE, "Couldn't create zip archive. Trying tar.gz"); if(! createTarArchive(dir, archiveFileName)){ logger.info(Constants.CONSOLE, "Couldn't create tar.gz archive."); } } } public static boolean createZipArchive(String dir, String archiveFileName) { try { File srcDir = new File(dir); String filename = dir + "-" + archiveFileName + ".zip"; FileOutputStream fout = new FileOutputStream(filename); ZipArchiveOutputStream taos = new ZipArchiveOutputStream(fout); archiveResultsZip(archiveFileName, taos, srcDir, "", true); taos.close(); logger.info(Constants.CONSOLE, "Archive: " + filename + " was created"); } catch (Exception ioe) { logger.error( "Couldn't create archive.", ioe); return false; } return true; } public static boolean createTarArchive(String dir, String archiveFileName) { try { File srcDir = new File(dir); String filename = dir + "-" + archiveFileName + ".tar.gz"; FileOutputStream fout = new FileOutputStream(filename); CompressorOutputStream cout = new GzipCompressorOutputStream(fout); TarArchiveOutputStream taos = new TarArchiveOutputStream(cout); taos.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_STAR); taos.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU); archiveResultsTar(archiveFileName, taos, srcDir, "", true); taos.close(); logger.info(Constants.CONSOLE, "Archive: " + filename + " was created"); } catch (Exception ioe) { logger.error( "Couldn't create archive.", ioe); return false; } return true; } public static void archiveResultsZip(String archiveFilename, ZipArchiveOutputStream taos, File file, String path, boolean append) { String relPath = ""; try { if (append) { relPath = path + "/" + file.getName() + "-" + archiveFilename; } else { relPath = path + "/" + file.getName(); } ZipArchiveEntry tae = new ZipArchiveEntry(file, relPath); taos.putArchiveEntry(tae); if (file.isFile()) { BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); IOUtils.copy(bis, taos); taos.closeArchiveEntry(); bis.close(); } else if (file.isDirectory()) { taos.closeArchiveEntry(); for (File childFile : file.listFiles()) { archiveResultsZip(archiveFilename, taos, childFile, relPath, false); } } } catch (IOException e) { logger.error(Constants.CONSOLE,"Archive Error", e); } } public static void archiveResultsTar(String archiveFilename, TarArchiveOutputStream taos, File file, String path, boolean append) { String relPath = ""; try { if (append) { relPath = path + "/" + file.getName() + "-" + archiveFilename; } else { relPath = path + "/" + file.getName(); } TarArchiveEntry tae = new TarArchiveEntry(file, relPath); taos.putArchiveEntry(tae); if (file.isFile()) { BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); IOUtils.copy(bis, taos); taos.closeArchiveEntry(); bis.close(); } else if (file.isDirectory()) { taos.closeArchiveEntry(); for (File childFile : file.listFiles()) { archiveResultsTar(archiveFilename, taos, childFile, relPath, false); } } } catch (IOException e) { logger.error(Constants.CONSOLE,"Archive Error", e); } } public static void extractArchive(String filename, String targetDir) throws Exception{ final int bufferSize = 1024; ArchiveInputStream ais = null; try { InputStream inputStream = new FileInputStream(new File(filename)); if(filename.endsWith(".zip")){ ais = new ZipArchiveInputStream(inputStream); } else if (filename.endsWith(".tar")){ ais = new TarArchiveInputStream(inputStream); } else if (filename.endsWith(".tar.gz")){ ais = new TarArchiveInputStream(new GzipCompressorInputStream(inputStream)); } else{ logger.error(Constants.CONSOLE, "Unsupported archive type"); return; } ArchiveEntry entry = ais.getNextEntry(); String archiveDir = entry.getName(); while (( entry = ais.getNextEntry()) != null) { String newPath = entry.getName().replace(archiveDir, ""); if(newPath.endsWith(".zip") || newPath.endsWith(".tar") | newPath.endsWith("tar.gz")){ String nestedArch = entryToDisk(ais, targetDir, newPath); String nestedTargetDir = nestedArch.substring(nestedArch.lastIndexOf(SystemProperties.fileSeparator)); extractArchive(nestedArch, nestedTargetDir); new File(nestedArch).delete(); } else if (entry.isDirectory()) { File f = new File(targetDir + SystemProperties.fileSeparator + newPath); boolean created = f.mkdir(); if (!created) { System.out.printf("Unable to create directory '%s', during extraction of archive contents.\n", f.getAbsolutePath()); } } else { entryToDisk(ais, targetDir, newPath); /*int count; byte data[] = new byte[bufferSize]; FileOutputStream fos = new FileOutputStream(new File(targetDir + SystemProperties.fileSeparator + newPath), false); try (BufferedOutputStream dest = new BufferedOutputStream(fos, bufferSize)) { while ((count = ais.read(data, 0, bufferSize)) != -1) { dest.write(data, 0, count); } }*/ } } System.out.println("Extract completed successfully!"); } catch (IOException e) { logger.error(e); } finally { ais.close(); } } private static String entryToDisk(ArchiveInputStream ais, String targetDir, String newPath) throws IOException{ int bufferSize = 1024; int count; byte data[] = new byte[bufferSize]; String fileName = targetDir + SystemProperties.fileSeparator + newPath; FileOutputStream fos = new FileOutputStream(new File(fileName), false); try (BufferedOutputStream dest = new BufferedOutputStream(fos, bufferSize)) { while ((count = ais.read(data, 0, bufferSize)) != -1) { dest.write(data, 0, count); } } return fileName; } }