package gov.nih.nci.cagrid.common;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
/**
* ZipUtilities
* Utilities to maniuplate zip files
*
* @author <A HREF="MAILTO:ervin@bmi.osu.edu">David W. Ervin</A> *
* @created Feb 21, 2007
* @version $Id: ZipUtilities.java,v 1.6 2008-01-11 15:49:48 dervin Exp $
*/
public class ZipUtilities {
/**
* Unzips a zip compressed file to a specific directory
*
* @param zip
* The zip compressed file
* @param location
* The location to unzip into
* @throws IOException
*/
public static void unzip(File zip, File location) throws IOException {
FileInputStream zipFileInput = new FileInputStream(zip.getAbsoluteFile());
ZipInputStream zipInput = new ZipInputStream(zipFileInput);
ZipEntry entry = null;
String baseDir = null;
if (location == null) {
baseDir = zip.getParentFile().getAbsolutePath();
} else {
baseDir = location.getAbsolutePath();
}
while ((entry = zipInput.getNextEntry()) != null) {
String name = entry.getName();
File outFile = new File(baseDir + File.separator + name);
if (entry.isDirectory()) {
outFile.mkdirs();
} else {
if (!outFile.getParentFile().exists()) {
outFile.getParentFile().mkdirs();
}
outFile.createNewFile();
BufferedOutputStream fileOut = new BufferedOutputStream(
new FileOutputStream(outFile));
copyStreams(zipInput, fileOut);
fileOut.flush();
fileOut.close();
}
}
zipInput.close();
}
/**
* Unzips a zip compressed file in the directory it resides in
*
* @param zip
* The zip compressed file
* @throws IOException
*/
public static void unzipInPlace(File zip) throws IOException {
unzip(zip, null);
}
/**
* Applies zip compression to a directory and all its contents
*
* @param dir
* The directory to compress
* @param zipFile
* The file to create the zip archive in
* @throws IOException
*/
public static void zipDirectory(File dir, File zipFile) throws IOException {
ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
List<File> files = Utils.recursiveListFiles(dir, new FileFilter() {
public boolean accept(File name) {
return true;
}
});
int baseDirNameLength = dir.getAbsolutePath().length();
Iterator<File> fileIter = files.iterator();
while (fileIter.hasNext()) {
File fileToAdd = fileIter.next();
String relativeFileName = fileToAdd.getAbsolutePath().substring(baseDirNameLength + 1);
ZipEntry entry = new ZipEntry(relativeFileName);
zipOut.putNextEntry(entry);
if (!fileToAdd.isDirectory()) {
BufferedInputStream fileInput = new BufferedInputStream(new FileInputStream(fileToAdd));
copyStreams(fileInput, zipOut);
fileInput.close();
}
}
zipOut.flush();
zipOut.close();
}
/**
* Extracts the contents of a zip file entry to a byte array
*
* @param zipFile
* The zip file
* @param entryName
* The name of the entry to extract
* @return
* A byte array containing the (uncompressed) contents of the entry
* @throws IOException
*/
public static byte[] extractEntryContents(File zipFile, String entryName) throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
ZipFile zip = new ZipFile(zipFile);
ZipEntry entry = zip.getEntry(entryName);
InputStream stream = zip.getInputStream(entry);
copyStreams(stream, output);
stream.close();
output.flush();
output.close();
return output.toByteArray();
}
/**
* Inserts an entry in a Zip file. If an entry with the given name is found,
* it will be replaced with the new one.
*
* @param zipFile
* The zip file to be appended
* @param entryName
* The name of the new entry
* @param data
* The data to add to the zip
* @throws IOException
*/
public static void insertEntry(File zipFile, String entryName, byte[] data) throws IOException {
// create a temp file
File tempZip = File.createTempFile(zipFile.getName(), "tmp");
tempZip.delete();
FileOutputStream tempOut = new FileOutputStream(tempZip);
ZipOutputStream zipOut = new ZipOutputStream(tempOut);
try {
// start streaming the input stream over to the temp
ZipFile zipIn = new ZipFile(zipFile);
Enumeration<? extends ZipEntry> entries = zipIn.entries();
while (entries.hasMoreElements()) {
ZipEntry inputEntry = entries.nextElement();
if (!inputEntry.getName().equals(entryName)) {
InputStream entryStream = zipIn.getInputStream(inputEntry);
zipOut.putNextEntry(inputEntry);
copyStreams(entryStream, zipOut);
zipOut.closeEntry();
}
}
// create new entry
ZipEntry insert = new ZipEntry(entryName);
zipOut.putNextEntry(insert);
copyStreams(new ByteArrayInputStream(data), zipOut);
zipOut.closeEntry();
zipOut.close();
zipIn.close();
zipFile.delete();
Utils.copyFile(tempZip, zipFile);
} finally {
// should delete the temp file regardless of what happens
// in the try block, and just let any exceptions percolate
// up the stack
tempZip.delete();
}
}
/**
* Copies the contents of an input stream into an output stream
*
* @param input
* @param output
* @throws IOException
*/
private static void copyStreams(InputStream input, OutputStream output) throws IOException {
byte[] temp = new byte[8192];
int read = -1;
while ((read = input.read(temp)) != -1) {
output.write(temp, 0, read);
}
}
}