Java tutorial
/******************************************************************************* * 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); } } }