blob: ffce14a442534246304362f891c8dd889853dc0e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2010 BREDEX GmbH.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* BREDEX GmbH - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.jubula.tools.internal.utils;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import org.apache.commons.lang.StringUtils;
/**
* This Util class contains methods to ZIP and unzip directories
*
* @author BREDEX GmbH
* @created 13.08.2010
*/
public class ZipUtil {
/** file extension for JAR files, in lower case */
private static final String JAR_FILE_EXT = ".jar"; //$NON-NLS-1$
/** mapping from a ZIP file to its extracted temporary JAR files */
private static Map<File, File[]> zipToTempJars =
new HashMap<File, File[]>();
/**
*
* @author BREDEX GmbH
* @created 23.06.2011
*/
public static interface IZipEntryFilter {
/**
*
* @param entry The ZIP entry to filter.
* @return <code>true</code> if the ZIP entry should be accepted.
* Otherwise, <code>false</code>.
*/
public boolean accept(ZipEntry entry);
}
/** to prevent instantiation */
private ZipUtil() {
//do nothing
}
/**
* This method converts a directory into a zip file
* @param directory The directory to zip
* @param zip The destination zip file
* @throws IOException
*/
public static final void zipDirectory(File directory, File zip)
throws IOException {
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip));
zip(directory, directory, zos);
zos.close();
}
/**
* This method converts a directory into a zip file
* @param directory The directory to zip
* @param base The directory to zip
* @param zos A ZipOutputStream
* @throws IOException
*/
private static final void zip(File directory, File base,
ZipOutputStream zos)
throws IOException {
File[] files = directory.listFiles();
byte[] buffer = new byte[8192];
int read = 0;
for (int i = 0, n = files.length; i < n; i++) {
if (files[i].isDirectory()) {
zip(files[i], base, zos);
} else {
FileInputStream in = new FileInputStream(files[i]);
ZipEntry entry = new ZipEntry(files[i].getPath().substring(
base.getPath().length() + 1));
zos.putNextEntry(entry);
while (-1 != (read = in.read(buffer))) {
zos.write(buffer, 0, read);
}
in.close();
}
}
}
/**
* This method unzip's a zip file into a given folder
* @param zip The zip file
* @param extractTo The destination folder
* @throws IOException
*/
public static final void unzip(File zip, File extractTo)
throws IOException {
unzipFiles(zip, extractTo, new IZipEntryFilter() {
public boolean accept(ZipEntry entry) {
return true;
}
});
}
/**
* Extracts all JAR files from the given ZIP file into temporary JAR files.
* The directory structure of the extracted contents is not maintained.
* A mapping from ZIP file to extracted JARs is maintained by this class,
* so multiple calls to this method for a single ZIP file will extract JAR
* files once and return references to those files for each subsequent call.
* The extracted JAR files are deleted on VM exit.
* @param srcZip The ZIP file to extract.
* @return all extracted files.
* @throws IOException
*/
public static File[] unzipTempJars(File srcZip)
throws IOException {
if (zipToTempJars.containsKey(srcZip)) {
return zipToTempJars.get(srcZip);
}
IZipEntryFilter filter = new IZipEntryFilter() {
public boolean accept(ZipEntry entry) {
return entry.getName().toLowerCase().endsWith(JAR_FILE_EXT);
}
};
ZipFile archive = new ZipFile(srcZip);
Enumeration<? extends ZipEntry> e = archive.entries();
List<File> extractedFiles = new ArrayList<File>();
while (e.hasMoreElements()) {
ZipEntry entry = e.nextElement();
if (filter.accept(entry)) {
if (!entry.isDirectory()) {
String prefix = entry.getName().substring(
entry.getName().lastIndexOf("/") + 1, //$NON-NLS-1$
entry.getName().toLowerCase().lastIndexOf(
JAR_FILE_EXT));
File file = File.createTempFile(
StringUtils.rightPad(prefix, 3),
JAR_FILE_EXT);
extractedFiles.add(file);
file.deleteOnExit();
unzipFile(archive, file, entry);
}
}
}
File [] files = extractedFiles.toArray(
new File[extractedFiles.size()]);
zipToTempJars.put(srcZip, files);
return files;
}
/**
* Unzips the contents of the given zip file into the given directory.
*
* @param srcZip The zip file to extract.
* @param targetDir The base directory for extracted files.
* @param filter Only files accepted by this filter will be extracted.
* @return all extracted files.
* @throws IOException
*/
public static File[] unzipFiles(File srcZip, File targetDir,
IZipEntryFilter filter) throws IOException {
ZipFile archive = new ZipFile(srcZip);
Enumeration e = archive.entries();
List<File> extractedFiles = new ArrayList<File>();
while (e.hasMoreElements()) {
ZipEntry entry = (ZipEntry)e.nextElement();
if (filter.accept(entry)) {
File file = new File(targetDir, entry.getName());
if (entry.isDirectory() && !file.exists()) {
file.mkdirs();
} else {
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
extractedFiles.add(file);
unzipFile(archive, file, entry);
}
}
}
return extractedFiles.toArray(new File[extractedFiles.size()]);
}
/**
*
* @param archive The zip file from which to extract.
* @param targetFile The file to which the entry contents will be extracted.
* @param entry The entry to extract.
* @throws IOException
*/
private static void unzipFile(ZipFile archive, File targetFile,
ZipEntry entry) throws IOException {
InputStream in = null;
BufferedOutputStream out = null;
try {
in = archive.getInputStream(entry);
out = new BufferedOutputStream(
new FileOutputStream(targetFile));
byte[] buffer = new byte[8192];
int read;
while (-1 != (read = in.read(buffer))) {
out.write(buffer, 0, read);
}
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
}
}