/*
* Copyright (C) 2006-2016 DLR, Germany
*
* All rights reserved
*
* http://www.rcenvironment.de/
*/
package de.rcenvironment.core.utils.common;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import org.apache.commons.compress.archivers.ArchiveException;
import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
/**
* Helper class for compressing / unfolding folders.
*
* @author Sascha Zur
*/
public final class CompressingHelper {
private CompressingHelper() {}
/**
* Create a zipped byte array from the given folder.
*
* @param folderToCompress folder to compress.
* @return byte array of zipped folder or null, if the given directory does not exist.
* @throws IOException if compressing did not work
* @throws FileNotFoundException if the temp dir could not be created
*/
public static byte[] createZippedByteArrayFromFolder(File folderToCompress) throws IOException, FileNotFoundException {
if (folderToCompress.exists()) {
File tempZipFile = TempFileServiceAccess.getInstance().createTempFileFromPattern("zippedFolder*.tar.gz");
ZipOutputStream zipFile = new ZipOutputStream(new FileOutputStream(tempZipFile));
compressDirectoryToZipfile(folderToCompress.getAbsolutePath(), folderToCompress.getAbsolutePath(), zipFile);
IOUtils.closeQuietly(zipFile);
tempZipFile.setLastModified(0);
byte[] zippedByteArray = FileUtils.readFileToByteArray(tempZipFile);
TempFileServiceAccess.getInstance().disposeManagedTempDirOrFile(tempZipFile);
return zippedByteArray;
}
return null;
}
private static void compressDirectoryToZipfile(String rootDir, String sourceDir, ZipOutputStream out)
throws IOException, FileNotFoundException {
File[] list = new File(sourceDir).listFiles();
Arrays.sort(list);
for (File file : list) {
if (file.isDirectory()) {
compressDirectoryToZipfile(rootDir, new File(sourceDir, file.getName()).getAbsolutePath(), out);
} else {
if (CrossPlatformFilenameUtils.isNFSFile(file.getName())) {
continue;
}
ZipEntry entry = new ZipEntry(sourceDir.replace(rootDir, "") + file.getName());
entry.setTime(0); // Set creation time to 0 to get the same hash value for same
// content.
out.putNextEntry(entry);
FileInputStream in = new FileInputStream(new File(sourceDir, file.getName()));
IOUtils.copy(in, out);
IOUtils.closeQuietly(in);
}
}
}
/**
* Decompresses a given byte array that is a compressed folder.
*
* @param folderAsCompressedArray to decompress
* @param unzippedLocation where the decompressed folder should be
* @throws IOException e
* @throws FileNotFoundException e
*/
public static void decompressFolderByteArray(byte[] folderAsCompressedArray, File unzippedLocation)
throws IOException, FileNotFoundException {
ZipInputStream zipFile = new ZipInputStream(new ByteArrayInputStream(folderAsCompressedArray));
ZipEntry ze = null;
final int minusOne = -1;
while ((ze = zipFile.getNextEntry()) != null) {
FileOutputStream fout = new FileOutputStream(new File(unzippedLocation, ze.getName()).getAbsolutePath());
for (int c = zipFile.read(); c != minusOne; c = zipFile.read()) {
fout.write(c);
}
zipFile.closeEntry();
fout.close();
}
zipFile.close();
}
/**
* Unzip a zip input stream to the destination folder.
*
* @param is {@link InputStream} from a zip file
* @param destination direcotry to unzip to
* @throws FileNotFoundException wrong is.
* @throws IOException unzipping failed
* @throws ArchiveException unzipping failed
*/
public static void unzip(InputStream is, File destination) throws FileNotFoundException, IOException, ArchiveException {
try (ArchiveInputStream ais = new ArchiveStreamFactory().createArchiveInputStream("zip", is)) {
ZipEntry entry = null;
while ((entry = (ZipArchiveEntry) ais.getNextEntry()) != null) {
if (entry.getName().endsWith("/")) {
File dir = new File(destination, entry.getName());
if (!dir.exists()) {
dir.mkdirs();
}
continue;
}
File outFile = new File(destination, entry.getName());
if (outFile.isDirectory()) {
continue;
}
if (outFile.exists()) {
continue;
}
FileOutputStream out = new FileOutputStream(outFile);
final int byteBuffer = 1024;
byte[] buffer = new byte[byteBuffer];
int length = 0;
while ((length = ais.read(buffer)) > 0) {
out.write(buffer, 0, length);
out.flush();
}
out.close();
}
}
}
}