Mega Code Archive

 
Categories / Java / File Input Output
 

Zip jar Imploder

/*******************************************************************************  * 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.BufferedOutputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; /**  * @author Barry Feigenbaum  */ public class ZipImploder {   protected int dirCount, fileCount;   /**    * @return Returns the dirCount.    */   public int getDirCount() {     return dirCount;   }   /**    * @return Returns the fileCount.    */   public int getFileCount() {     return fileCount;   }   /**    * create a new imploder with no verbosity    *     */   public ZipImploder() {     this(false);   }   /**    * create a new imploder with the specified verbosity state    *     * @param verbose -    *          verbosity state    */   public ZipImploder(boolean verbose) {     setVerbose(verbose);   }   protected boolean verbose;   /**    * get the verbose mode    *     * @return verbosity mode    */   public boolean getVerbose() {     return verbose;   }   /**    * set the verbosity mode    *     * @param f    *          verbosity state    */   public void setVerbose(boolean f) {     verbose = f;   }   protected String baseDir;   /**    * @return Returns the baseDir.    */   public String getBaseDir() {     return baseDir;   }   /**    * @param baseDir    *          The baseDir to set.    * @throws IOException    */   public void setBaseDir(String baseDir) throws IOException {     if (baseDir != null) {       baseDir = new File(baseDir).getCanonicalPath();       baseDir = baseDir.replace('\\', '/');     }     this.baseDir = baseDir;   }   protected Manifest manifest;   /**    * @return Returns the manifest    */   public Manifest getManifest() {     return manifest;   }   /**    * @param manifest    *          The manifest to set.    */   public void setManifest(Manifest manifest) {     this.manifest = manifest;   }   protected boolean includeDirs;   /**    * returns whether or not path information is included in .zip    *     * @return <code>true</code> if path information is included,    *         <code>false</code> otherwise    */   public boolean getIncludeDirs() {     return includeDirs;   }   /**    * set whether or not path information is included in .zip files    *     * @param includeDirs    *          include path inforamtion in .zip file    */   public void setIncludeDirs(boolean includeDirs) {     this.includeDirs = includeDirs;   }   /**    * implode source directory into .jar/.zip file    *     * @param zipName    *          name of target file    * @param jarName    *          name of target file    * @param sourceDir    *          source directory name    * @exception IOException    *              error creating a target file    */   public void process(String zipName, String jarName, String sourceDir) throws IOException {     dirCount = 0;     fileCount = 0;     if (zipName != null) {       processZip(zipName, sourceDir);     }     if (jarName != null) {       processJar(jarName, sourceDir);     }   }   /**    * Implode target JAR file from a source directory    *     * @param jarName    *          name of target file    * @param sourceDir    *          source directory name    * @exception IOException    *              error creating a target file    */   public void processJar(String jarName, String sourceDir) throws IOException {     processJar(jarName, sourceDir, null);   }   /**    * Implode target JAR file from a source directory    *     * @param jarName    *          name of target file    * @param sourceDir    *          source directory name (    * @param comment    * @exception IOException    *              error creating a target file    */   public void processJar(String jarName, String sourceDir, String comment) throws IOException {     processJar(jarName, sourceDir, comment, -1, -1);   }   /**    * Implode target JAR file from a source directory    *     * @param jarName -    *          name of target .jar    * @param sourceDir -    *          source directory    * @param comment -    *          comment for .jar file    * @param method    * @param level    * @throws IOException    */   public void processJar(String jarName, String sourceDir, String comment, int method, int level)       throws IOException {     String dest = setup(jarName, sourceDir);     Manifest man = getManifest();     JarOutputStream jos = man != null ? new JarOutputStream(new BufferedOutputStream(         new FileOutputStream(dest)), man) : new JarOutputStream(new BufferedOutputStream(         new FileOutputStream(dest)));     configure(jos, comment, method, level);     process(jos, new File(sourceDir));   }   /**    * Implode target JAR file from a source directory    *     * @param zipName    *          name of target file    * @param sourceDir    *          source directory name (    * @exception IOException    *              error creating a target file    */   public void processZip(String zipName, String sourceDir) throws IOException {     processZip(zipName, sourceDir, null);   }   /**    * Implode target zip file from a source directory    *     * @param zipName    * @param sourceDir    * @param comment    * @throws IOException    */   public void processZip(String zipName, String sourceDir, String comment) throws IOException {     processZip(zipName, sourceDir, comment, -1, -1);   }   /**    * Implode target zip file from a source directory    *     * @param zipName    * @param sourceDir    * @param comment    * @param method    * @param level    * @throws IOException    */   public void processZip(String zipName, String sourceDir, String comment, int method, int level)       throws IOException {     String dest = setup(zipName, sourceDir);     ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(dest)));     configure(zos, comment, method, level);     process(zos, new File(sourceDir));   }   protected void configure(ZipOutputStream zos, String comment, int method, int level) {     if (comment != null) {       zos.setComment(comment);     }     if (method >= 0) {       zos.setMethod(method);     }     if (level >= 0) {       zos.setLevel(level);     }   }   protected String setup(String zipName, String sourceDir) throws IOException {     File dir = new File(sourceDir);     if (!dir.exists() && !dir.isDirectory()) {       throw new IOException("source must exist and be a directory: " + dir);     }     String source = dir.getCanonicalPath();     String dest = new File(zipName).getCanonicalPath();     return dest;   }   protected void process(ZipOutputStream zos, File dir) throws IOException {     try {       processDir(zos, dir);     } finally {       zos.close();     }   }   protected String removeDrive(String path) {     return path.length() >= 2 && path.charAt(1) == ':' ? path.substring(2) : path;   }   protected String removeLead(String path) {     if (baseDir != null && path.startsWith(baseDir)) {       path = path.substring(baseDir.length());       if (path.length() >= 1) {         if (path.charAt(0) == '/' || path.charAt(0) == '\\') {           path = path.substring(1); // drop leading /         }       }     }     return path;   }   public void processDir(ZipOutputStream zos, File dir) throws IOException {     String path = dir.getCanonicalPath();     path = path.replace('\\', '/');     if (includeDirs) {       if (baseDir == null || path.length() > baseDir.length()) {         String xpath = removeDrive(removeLead(path));         if (xpath.length() > 0) {           xpath += '/';           ZipEntry ze = new ZipEntry(xpath);           zos.putNextEntry(ze);         }       }     }     dirCount++;     String[] files = dir.list();     for (int i = 0; i < files.length; i++) {       String file = files[i];       File f = new File(dir, file);       if (f.isDirectory()) {         processDir(zos, f);       } else {         processFile(zos, f);       }     }   }   /**    * process a single file for a .zip file    *     * @param zos    * @param f    * @throws IOException    */   public void processFile(ZipOutputStream zos, File f) throws IOException {     String path = f.getCanonicalPath();     path = path.replace('\\', '/');     String xpath = removeDrive(removeLead(path));     ZipEntry ze = new ZipEntry(xpath);     ze.setTime(f.lastModified());     ze.setSize(f.length());     zos.putNextEntry(ze);     fileCount++;     try {       copyFileEntry(zos, f);     } finally {       zos.closeEntry();     }   }   protected void copyFileEntry(ZipOutputStream zos, File f) throws IOException {     DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(f)));     try {       copyFileEntry(zos, dis);     } finally {       try {         dis.close();       } catch (IOException ioe) {       }     }   }   protected void copyFileEntry(ZipOutputStream zos, DataInputStream dis) throws IOException {     byte[] bytes = readAllBytes(dis);     zos.write(bytes, 0, bytes.length);   }   // *** below may be slow for large files ***   /** Read all the bytes in a stream */   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;       }     }     return bytes;   }   protected void print(String s) {     System.out.print(s);   }   /** Print command help text. */   public static void printHelp() {     System.out.println();     System.out.println("Usage: java " + ZipImploder.class.getName());     System.out.println("       (-jar <jarName> {-manifest <manfile>} | -zip <zipName>)");     System.out.println("       -dir <sourceDir> {-lead <leadDir>} {-doDirs} {-verbose}");     System.out.println("Where:");     System.out.println("  <jarName>     path to target jar");     System.out.println("  <zipName>     path to target zip");     System.out.println("  <manfile>     path to manifest file");     System.out.println("  <sourceDir>   path to source directory; must exist");     System.out         .println("  <leadDir>     partial lead path to remove from stored entries; default: <sourceDir>");     System.out.println("  <noDirs>      skip output of directory entries");     System.out.println("  <verbose>     output progress information");     System.out.println("Note: 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);     }     String zipName = null;     String jarName = null;     String manName = null;     String sourceDir = null;     String leadDir = null;     boolean jarActive = false, manActive = false, zipActive = false, sourceDirActive = false, leadDirActive = false;     boolean verbose = false;     boolean noDirs = 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;           manActive = false;           zipActive = false;           sourceDirActive = false;           leadDirActive = false;         } else if (arg.equalsIgnoreCase("manifest")) {           jarActive = false;           manActive = true;           zipActive = false;           sourceDirActive = false;           leadDirActive = false;         } else if (arg.equalsIgnoreCase("zip")) {           zipActive = true;           manActive = false;           jarActive = false;           sourceDirActive = false;           leadDirActive = false;         } else if (arg.equalsIgnoreCase("dir")) {           jarActive = false;           manActive = false;           zipActive = false;           sourceDirActive = true;           leadDirActive = false;         } else if (arg.equalsIgnoreCase("lead")) {           jarActive = false;           manActive = false;           zipActive = false;           sourceDirActive = false;           leadDirActive = true;         } else if (arg.equalsIgnoreCase("noDirs")) {           noDirs = true;           jarActive = false;           manActive = false;           zipActive = false;           sourceDirActive = false;           leadDirActive = false;         } else if (arg.equalsIgnoreCase("verbose")) {           verbose = true;           jarActive = false;           manActive = false;           zipActive = false;           sourceDirActive = false;           leadDirActive = false;         } else {           reportError("Invalid switch - " + arg);         }       } else {         if (jarActive) {           if (jarName != null) {             reportError("Duplicate value - " + arg);           }           jarName = arg;         } else if (manActive) {           if (manName != null) {             reportError("Duplicate value - " + arg);           }           manName = arg;         } else if (zipActive) {           if (zipName != null) {             reportError("Duplicate value - " + arg);           }           zipName = arg;         } else if (sourceDirActive) {           if (sourceDir != null) {             reportError("Duplicate value - " + arg);           }           sourceDir = arg;         } else if (leadDirActive) {           if (leadDir != null) {             reportError("Duplicate value - " + arg);           }           leadDir = arg;         } else {           reportError("Too many parameters - " + arg);         }       }     }     if (sourceDir == null || (zipName == null && jarName == null)) {       reportError("Missing parameters");     }     if (manName != null && zipName != null) {       reportError("Manifests not supported on ZIP files");     }     if (leadDir == null) {       leadDir = new File(sourceDir).getAbsolutePath().replace('\\', '/') + '/';     }     if (verbose) {       System.out.println("Effective command: "           + ZipImploder.class.getName()           + (jarName != null ? " -jar " + jarName               + (manName != null ? " -manifest " + manName : "") : "")           + (zipName != null ? " -zip " + zipName : "") + " -dir " + sourceDir + " -lead "           + leadDir + (noDirs ? " -noDirs" : "") + (verbose ? " -verbose" : ""));     }     try {       ZipImploder zi = new ZipImploder(verbose);       if (leadDir != null) {         zi.setBaseDir(leadDir);       }       if (manName != null) {         BufferedInputStream bis = new BufferedInputStream(new FileInputStream(manName));         try {           zi.setManifest(new Manifest(bis));         } finally {           bis.close();         }       }       zi.setIncludeDirs(!noDirs);       zi.process(zipName, jarName, sourceDir);       if (verbose) {         System.out             .println("\nDone Directories=" + zi.getDirCount() + " Files=" + zi.getFileCount());       }     } catch (IOException ioe) {       System.err.println("Exception - " + ioe.getMessage());       // ioe.printStackTrace(); // *** debug ***       System.exit(2);     }   } }