File Input Output Java

/*******************************************************************************
 * 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 true 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 true for verbose mode
   * @param sorted -
   *          set to true 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);
    }
  }
}