/******************************************************************************* * Copyright (c) 2013 GigaSpaces Technologies Ltd. All rights reserved * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. ******************************************************************************/ package org.cloudifysource.esc.util; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; 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.compressors.gzip.GzipCompressorInputStream; import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; /** * Class utility to create TAR.GZ archives. * */ public final class TarGzUtils { private static final Logger LOGGER = Logger.getLogger(TarGzUtils.class.getName()); private static final String DEFAULT_PREFIX = "cloudFolder"; private static final int BUFFER = 2048; private TarGzUtils() { } /** * Create a temporary tar gz file. * * @return The temporary file * @throws IOException * If the file cannot be created. */ private static File createTempTarGzFile() throws IOException { final File archiveFile = File.createTempFile(DEFAULT_PREFIX, ".tar.gz"); archiveFile.deleteOnExit(); if (LOGGER.isLoggable(Level.FINE)) { System.out.println(archiveFile); LOGGER.finest("Created tar.gz file: " + archiveFile); } return archiveFile; } /** * Create a tar.gz file. * * @param sourcePaths * Folders or files to add in the archive. * @param addRoot * When <code>sourcePath</code> is a folder. if true, it will add the folder in the archive.<br/> * <i>i.e: if sourcepath=/tmp/folderToInclude, archive.tar.gz will include the folder * <b>folderToInclude</b> in the archive.</i> * @return The created archive. * @throws IOException * If the archive cannot be create. */ public static File createTarGz(final String sourcePaths, final boolean addRoot) throws IOException { return createTarGz(new String[] { sourcePaths }, "", addRoot); } /** * Create a tar.gz file. * * @param sourcePaths * Folders or files to add in the archive. * @param addRoot * When <code>sourcePath</code> is a folder. if true, it will add the folder in the archive.<br/> * <i>i.e: if sourcepath=/tmp/folderToInclude, archive.tar.gz will include the folder * <b>folderToInclude</b> in the archive.</i> * @return The created archive. * @throws IOException * If the archive cannot be create. */ public static File createTarGz(final String[] sourcePaths, final boolean addRoot) throws IOException { return createTarGz(sourcePaths, "", addRoot); } /** * Create a tar.gz file. * * @param sourcePaths * Folders or files to add in the archive. * @param base * The name to be use in the archive. * @param addRoot * When <code>sourcePath</code> is a folder. if true, it will add the folder in the archive.<br/> * <i>i.e: if sourcepath=/tmp/folderToInclude, archive.tar.gz will include the folder * <b>folderToInclude</b> in the archive.</i> * @return The created archive. * @throws IOException * If the archive cannot be create. */ public static File createTarGz(final String[] sourcePaths, final String base, final boolean addRoot) throws IOException { File tarGzFile = createTempTarGzFile(); if (!FilenameUtils.getExtension(tarGzFile.getName().toLowerCase()).equals("gz")) { throw new IllegalArgumentException("Expecting tar.gz file: " + tarGzFile.getAbsolutePath()); } FileOutputStream fOut = null; BufferedOutputStream bOut = null; GzipCompressorOutputStream gzOut = null; TarArchiveOutputStream tOut = null; try { fOut = new FileOutputStream(tarGzFile); bOut = new BufferedOutputStream(fOut); gzOut = new GzipCompressorOutputStream(bOut); tOut = new TarArchiveOutputStream(gzOut); for (String path : sourcePaths) { addFileToTarGz(tOut, path, base, addRoot); } } finally { if (tOut != null) { tOut.close(); } if (gzOut != null) { gzOut.close(); } if (bOut != null) { bOut.close(); } if (fOut != null) { fOut.close(); } } return tarGzFile; } private static void addFileToTarGz(final TarArchiveOutputStream tOut, final String path, final String base, final boolean addRoot) throws IOException { File f = new File(path); String entryName = base + f.getName(); if (f.isFile()) { TarArchiveEntry tarEntry = new TarArchiveEntry(f, entryName); tOut.putArchiveEntry(tarEntry); IOUtils.copy(new FileInputStream(f), tOut); tOut.closeArchiveEntry(); } else { if (addRoot) { TarArchiveEntry tarEntry = new TarArchiveEntry(f, entryName); tOut.putArchiveEntry(tarEntry); tOut.closeArchiveEntry(); } File[] children = f.listFiles(); if (children != null) { for (File child : children) { if (addRoot) { addFileToTarGz(tOut, child.getAbsolutePath(), entryName + "/", true); } else { addFileToTarGz(tOut, child.getAbsolutePath(), "", true); } } } } } /** * Extract a tar.gz file. * * @param source * The file to extract from. * @param destination * The destination folder. * @throws IOException * An error occured during the extraction. */ public static void extract(final File source, final String destination) throws IOException { LOGGER.fine(String.format("Extracting %s to %s", source.getName(), destination)); if (!FilenameUtils.getExtension(source.getName().toLowerCase()).equals("gz")) { throw new IllegalArgumentException("Expecting tar.gz file: " + source.getAbsolutePath()); } if (!new File(destination).isDirectory()) { throw new IllegalArgumentException("Destination should be a folder: " + destination); } /** create a TarArchiveInputStream object. **/ FileInputStream fin = new FileInputStream(source); BufferedInputStream in = new BufferedInputStream(fin); GzipCompressorInputStream gzIn = new GzipCompressorInputStream(in); TarArchiveInputStream tarIn = new TarArchiveInputStream(gzIn); TarArchiveEntry entry = null; /** Read the tar entries using the getNextEntry method **/ while ((entry = (TarArchiveEntry) tarIn.getNextEntry()) != null) { LOGGER.finer("Extracting: " + entry.getName()); /** If the entry is a directory, create the directory. **/ if (entry.isDirectory()) { File f = new File(destination, entry.getName()); f.mkdirs(); } else { int count; byte[] data = new byte[BUFFER]; FileOutputStream fos = new FileOutputStream(new File(destination, entry.getName())); BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER); while ((count = tarIn.read(data, 0, BUFFER)) != -1) { dest.write(data, 0, count); } dest.close(); } } /** Close the input stream **/ tarIn.close(); } }