class for exploding jar/zip files onto the file system
/*******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation.
* 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
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;
/**
* class for exploding jar/zip files onto the file system
*
* @author Barry Feigenbaum
*/
public class ZipExploder {
/**
* create a zip exploder for unpacking .jar/.zip files
*/
public ZipExploder() {
this(false);
}
/**
* create a zip exploder for unpacking .jar/.zip files onto the file system
*
* @param verbose -
* set to <code>true</code> for verbose mode
*/
public ZipExploder(boolean verbose) {
setVerbose(verbose);
}
/**
* create a zip exploder for unpacking .jar/.zip files onto the file system
*
* @param verbose -
* set to <code>true</code> for verbose mode
* @param sorted -
* set to <code>true</code> for sorted file mode
*/
public ZipExploder(boolean verbose, boolean sorted) {
this(verbose);
setSortNames(sorted);
}
protected boolean verbose;
/**
* Get the verbose mode state.
*
* @return verbosity
*/
public boolean getVerbose() {
return verbose;
}
/**
* set the verbose mode state
*
* @param f -
* verbosity
*/
public void setVerbose(boolean f) {
verbose = f;
}
protected boolean sortNames;
/**
* @return Returns the sortNames.
*/
public boolean getSortNames() {
return sortNames;
}
/**
* @param sortNames
* The sortNames to set.
*/
public void setSortNames(boolean sortNames) {
this.sortNames = sortNames;
}
/**
* Explode source JAR and/or ZIP files into a target directory
*
* @param zipNames
* names of source files
* @param jarNames
* names of source files
* @param destDir
* target directory name (should already exist)
* @exception IOException
* error creating a target file
*/
public void process(String[] zipNames, String[] jarNames, String destDir) throws IOException {
processZips(zipNames, destDir);
processJars(jarNames, destDir);
}
/**
* Explode source JAR files into a target directory
*
* @param jarNames
* names of source files
* @param destDir
* target directory name (should already exist)
* @exception IOException
* error creating a target file
*/
public void processJars(String[] jarNames, String destDir) throws IOException {
for (int i = 0; i < jarNames.length; i++) {
processFile(jarNames[i], destDir);
}
}
/**
* Explode source ZIP files into a target directory
*
* @param zipNames
* names of source files
* @param destDir
* target directory name (should already exist)
* @exception IOException
* error creating a target file
*/
public void processZips(String[] zipNames, String destDir) throws IOException {
for (int i = 0; i < zipNames.length; i++) {
processFile(zipNames[i], destDir);
}
}
/**
* Explode source ZIP or JAR file into a target directory
*
* @param zipName
* names of source file
* @param destDir
* target directory name (should already exist)
* @exception IOException
* error creating a target file
*/
public void processFile(String zipName, String destDir) throws IOException {
String source = new File(zipName).getCanonicalPath();
String dest = new File(destDir).getCanonicalPath();
ZipFile f = null;
try {
f = new ZipFile(source);
Map fEntries = getEntries(f);
String[] names = (String[]) fEntries.keySet().toArray(new String[] {});
if (sortNames) {
Arrays.sort(names);
}
// copy all files
for (int i = 0; i < names.length; i++) {
String name = names[i];
ZipEntry e = (ZipEntry) fEntries.get(name);
copyFileEntry(dest, f, e);
}
} catch (IOException ioe) {
String msg = ioe.getMessage();
if (msg.indexOf(zipName) < 0) {
msg += " - " + zipName;
}
throw new IOException(msg);
} finally {
if (f != null) {
try {
f.close();
} catch (IOException ioe) {
}
}
}
}
/** Get all the entries in a ZIP file. */
protected Map getEntries(ZipFile zf) {
Enumeration e = zf.entries();
Map m = new HashMap();
while (e.hasMoreElements()) {
ZipEntry ze = (ZipEntry) e.nextElement();
m.put(ze.getName(), ze);
}
return m;
}
/**
* copy a single entry from the archive
*
* @param destDir
* @param zf
* @param ze
* @throws IOException
*/
public void copyFileEntry(String destDir, ZipFile zf, ZipEntry ze) throws IOException {
DataInputStream dis = new DataInputStream(new BufferedInputStream(zf.getInputStream(ze)));
try {
copyFileEntry(destDir, ze.isDirectory(), ze.getName(), dis);
} finally {
try {
dis.close();
} catch (IOException ioe) {
}
}
}
protected void copyFileEntry(String destDir, boolean destIsDir, String destFile,
DataInputStream dis) throws IOException {
byte[] bytes = readAllBytes(dis);
File file = new File(destFile);
String parent = file.getParent();
if (parent != null && parent.length() > 0) {
File dir = new File(destDir, parent);
if (dir != null) {
dir.mkdirs();
}
}
File outFile = new File(destDir, destFile);
if (destIsDir) {
outFile.mkdir();
} else {
FileOutputStream fos = new FileOutputStream(outFile);
try {
fos.write(bytes, 0, bytes.length);
} finally {
try {
fos.close();
} catch (IOException ioe) {
}
}
}
}
// *** below may be slow for large files ***
/** Read all the bytes in a ZIPed file */
protected byte[] readAllBytes(DataInputStream is) throws IOException {
byte[] bytes = new byte[0];
for (int len = is.available(); len > 0; len = is.available()) {
byte[] xbytes = new byte[len];
int count = is.read(xbytes);
if (count > 0) {
byte[] nbytes = new byte[bytes.length + count];
System.arraycopy(bytes, 0, nbytes, 0, bytes.length);
System.arraycopy(xbytes, 0, nbytes, bytes.length, count);
bytes = nbytes;
} else if (count < 0) {
// accommodate apparent bug in IBM JVM where
// available() always returns positive value on some files
break;
}
}
return bytes;
}
protected void print(String s) {
System.out.print(s);
}
/** Print command help text. */
protected static void printHelp() {
System.out.println();
System.out.println("Usage: java " + ZipExploder.class.getName()
+ " (-jar jarFilename... | -zip zipFilename...)... -dir destDir {-verbose}");
System.out.println("Where:");
System.out.println(" jarFilename path to source jar, may repeat");
System.out.println(" zipFilename path to source zip, may repeat");
System.out.println(" destDir path to target directory; should exist");
System.out.println("Note: one -jar or -zip is required; switch case or order is not important");
}
protected static void reportError(String msg) {
System.err.println(msg);
// printHelp();
System.exit(1);
}
/**
* Main command line entry point.
*
* @param args
*/
public static void main(final String[] args) {
if (args.length == 0) {
printHelp();
System.exit(0);
}
List zipNames = new ArrayList();
List jarNames = new ArrayList();
String destDir = null;
boolean jarActive = false, zipActive = false, destDirActive = false;
boolean verbose = false;
// process arguments
for (int i = 0; i < args.length; i++) {
String arg = args[i];
if (arg.charAt(0) == '-') { // switch
arg = arg.substring(1);
if (arg.equalsIgnoreCase("jar")) {
jarActive = true;
zipActive = false;
destDirActive = false;
} else if (arg.equalsIgnoreCase("zip")) {
zipActive = true;
jarActive = false;
destDirActive = false;
} else if (arg.equalsIgnoreCase("dir")) {
jarActive = false;
zipActive = false;
destDirActive = true;
} else if (arg.equalsIgnoreCase("verbose")) {
verbose = true;
} else {
reportError("Invalid switch - " + arg);
}
} else {
if (jarActive) {
jarNames.add(arg);
} else if (zipActive) {
zipNames.add(arg);
} else if (destDirActive) {
if (destDir != null) {
reportError("duplicate argument - " + "-destDir");
}
destDir = arg;
} else {
reportError("Too many parameters - " + arg);
}
}
}
if (destDir == null || (zipNames.size() + jarNames.size()) == 0) {
reportError("Missing parameters");
}
if (verbose) {
System.out.println("Effective command: " + ZipExploder.class.getName() + " "
+ (jarNames.size() > 0 ? "-jars " + jarNames + " " : "")
+ (zipNames.size() > 0 ? "-zips " + zipNames + " " : "") + "-dir " + destDir);
}
try {
ZipExploder ze = new ZipExploder(verbose);
ze.process((String[]) zipNames.toArray(new String[zipNames.size()]), (String[]) jarNames
.toArray(new String[jarNames.size()]), destDir);
} catch (IOException ioe) {
System.err.println("Exception - " + ioe.getMessage());
ioe.printStackTrace(); // *** debug ***
System.exit(2);
}
}
}
Related examples in the same category