package jeffaschenk.commons.util;
import org.apache.commons.compress.archivers.ArchiveException;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
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.ZipFile;
import org.apache.commons.compress.utils.IOUtils;
import java.io.*;
import java.util.Enumeration;
import java.util.zip.GZIPInputStream;
/**
* Zip File Utility Class
*
* @author jeffaschenk@gmail.com
*/
public class ArchiveUtility {
/**
* Ensure Class is not instantiated.
*/
private ArchiveUtility() {
}
/**
* Determine if the file is an Archive?
*
* @param file
* @return boolean
*/
public static boolean isArchive(File file) {
if ((file.getName().toLowerCase().endsWith(".zip")) ||
(file.getName().toLowerCase().endsWith(".tar")) ||
(file.getName().toLowerCase().endsWith("gz"))) {
return true;
}
return false;
}
/**
* Decompress Archive File
*
* @param file
* @param outputDirectory
* @return boolean
* @throws java.io.IOException
*/
public static boolean decompressArchiveFile(File file, File outputDirectory) throws IOException {
if ((!file.exists()) || (!file.canRead())) {
throw new IllegalAccessError("Compressed File:[" + file.getName() +
"] is not Accessible!");
}
if ((!outputDirectory.exists()) || (!outputDirectory.canWrite()) || (!outputDirectory.isDirectory())) {
throw new IllegalAccessError("Output Directory:[" + outputDirectory.getAbsolutePath() +
"] is not Accessible, or not a valid File System Directory!");
}
// Check for Zip Type
if (file.getName().toLowerCase().endsWith(".zip")) {
ZipFile zipFile = new ZipFile(file);
try {
// Obtain the Entries in the Zip.
Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
while (entries.hasMoreElements()) {
extractZipEntry(zipFile, entries.nextElement(), outputDirectory);
}
return true;
} finally {
zipFile.close();
}
// Check for a Tar Type
} else if (file.getName().toLowerCase().endsWith(".tar")) {
TarArchiveInputStream tarBallInputStream = null;
try {
tarBallInputStream =
(TarArchiveInputStream)
new ArchiveStreamFactory().createArchiveInputStream("tar", new FileInputStream(file));
TarArchiveEntry entry = null;
// Loop Through Entries in TarBall
while ((entry = (TarArchiveEntry) tarBallInputStream.getNextEntry()) != null) {
extractTarBallEntry(tarBallInputStream, entry, outputDirectory);
}
return true;
} catch (ArchiveException ae) {
throw new RuntimeException("Encountered an Archive Exception:[" + ae.getMessage() + "]", ae);
} finally {
tarBallInputStream.close();
}
// Check for a GZip Type
} else if (file.getName().toLowerCase().endsWith("gz")) {
File uncompressedFile = unGzip(file, outputDirectory);
decompressArchiveFile(uncompressedFile, outputDirectory);
return true;
} else {
throw new IllegalArgumentException("Compressed File:[" + file.getName() +
"] Archive Type in unknown to this Utility Function!");
}
}
/**
* Private Helper Method to Perform Extract of Compressed File with the Zip.
*
* @param zipFile
* @param entry
* @param outputDirectory
* @throws java.io.IOException
*/
private static void extractZipEntry(ZipFile zipFile, ZipArchiveEntry entry, File outputDirectory)
throws IOException {
BufferedInputStream content = new BufferedInputStream(zipFile.getInputStream(entry), 16384);
FileOutputStream fileOutputStream = new FileOutputStream(new File(outputDirectory + File.separator + entry.getName()));
try {
final byte[] buffer = new byte[16384];
int n = 0;
while (-1 != (n = content.read(buffer))) {
fileOutputStream.write(buffer, 0, n);
}
} finally {
content.close();
fileOutputStream.flush();
fileOutputStream.close();
}
}
/**
* Private Helper Method to Perform Extract for a Tarball Entry.
*
* @param tarArchiveInputStream
* @param entry
* @param outputDirectory
* @throws java.io.IOException
*/
private static void extractTarBallEntry(TarArchiveInputStream tarArchiveInputStream, TarArchiveEntry entry, File outputDirectory)
throws IOException {
final File outputFile = new File(outputDirectory, entry.getName());
if (entry.isDirectory()) {
if (!outputFile.exists()) {
if (!outputFile.mkdirs()) {
throw new IllegalStateException(String.format("Couldn't create directory %s.", outputFile.getAbsolutePath()));
}
}
} else {
final OutputStream outputFileStream = new FileOutputStream(outputFile);
IOUtils.copy(tarArchiveInputStream, outputFileStream);
outputFileStream.close();
}
}
/**
* Ungzip an input file into an output file.
* <p>
* The output file is created in the output folder, having the same name
* as the input file, minus the '.gz' extension.
*
* @param compressedInputFile the input .gz file
* @param outputDir the output directory file.
* @throws java.io.IOException
* @throws java.io.FileNotFoundException
*
* @return File with the ungzipped content.
*/
private static File unGzip(final File compressedInputFile, final File outputDir) throws IOException {
String uncompressedOutputFileName = null;
if (compressedInputFile.getName().endsWith(".gz"))
{
uncompressedOutputFileName =
compressedInputFile.getName().substring(0, compressedInputFile.getName().length() - 3);
} else if (compressedInputFile.getName().endsWith(".tgz"))
{
uncompressedOutputFileName =
compressedInputFile.getName().substring(0, compressedInputFile.getName().length() - 3) +
"tar";
} else {
throw new IllegalArgumentException("Compressed File:[" + compressedInputFile.getName() +
"] Archive Type in unknown to this Utility Function!");
}
// Un-Compress.
final File outputFile = new File(outputDir, uncompressedOutputFileName);
final GZIPInputStream in = new GZIPInputStream(new FileInputStream(compressedInputFile));
final FileOutputStream out = new FileOutputStream(outputFile);
for (int c = in.read(); c != -1; c = in.read()) {
out.write(c);
}
in.close();
out.close();
return outputFile;
}
}