JarFactory.java :  » Code-Analyzer » JBlanket » csdl » jblanket » util » Java Open Source

Java Open Source » Code Analyzer » JBlanket 
JBlanket » csdl » jblanket » util » JarFactory.java
package csdl.jblanket.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;

import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarException;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.zip.CRC32;

import org.apache.tools.ant.DirectoryScanner;

/**
 * Provides utilities to extract or package JAR files.
 * <p>
 * Methods are provided to either extract or package JAR files using the JDK1.2 java.util.jar
 * package. Noted that JAR files created with the <code>jar</code> method are smaller than their
 * counterpart created by using the <code>jar</code> command provided by Java.  This is probably
 * because the <code>jar</code> method here does not include any options.
 * <p>
 * Code snips from: Java Cookbook, pp 268-270 and The Java Class Libraries, pp 487-488
 *
 * @author Joy M. Agustin
 * @version $Id: JarFactory.java,v 1.1 2004/11/07 00:32:24 timshadel Exp $
 */
public class JarFactory {

  /** Buffer for reading/writing the JarFile data */
  private byte[] buffer;

  /** Directory to that does/will contain the class files */
  private String dir;

  /** Directory separator */
  private static final String SLASH = File.separator;
  /** Name of directory holding manifest file */
  private static final String MAN_DIR = "META-INF";
  /** Relative path to the manifest file starting at MAN_DIR */
  private static final String MAN_FILE_PATH = MAN_DIR + SLASH + "MANIFEST.MF";

  /**
   * Constructs an JarFactory object.
   *
   * @param dir the directory that contains/will contain the class files.
   */
  public JarFactory(String dir) {

    this.dir = dir;
    this.buffer = new byte[8092];
  }

  /**
   * Extracts all files in a JAR file.
   *
   * @param jarFile the JAR file to unjar.
   * @throws IOException if cannot unjar <code>fileName</code>.
   * @throws JarException if error extracting files from JAR file.
   */
  public void unJar(File jarFile) throws IOException, JarException {

    if (!jarFile.getName().endsWith(".jar")) {
      throw new JarException ("Not a zip file? " + jarFile.getName());
    }
    
    // process all entries in that JAR file
    JarFile jar = new JarFile(jarFile);
    Enumeration all = jar.entries();
    while (all.hasMoreElements()) {
      getEntry(jar, ((JarEntry) (all.nextElement())));
    }
    
    jar.close();
  }

  /**
   * Gets one file <code>entry</code> from <code>jarFile</code>.
   *
   * @param jarFile the JAR file reference to retrieve <code>entry</code> from.
   * @param entry the file from the JAR to extract.
   * @throws IOException if error trying to read entry.
   */
  private void getEntry(JarFile jarFile, JarEntry entry) throws IOException {

    String entryName = entry.getName();
    // if a directory, mkdir it (remember to create intervening subdirectories if needed!)
    if (entryName.endsWith("/")) {
      new File(dir, entryName).mkdirs();
      return;
    }
    
    File f = new File(dir, entryName);

    if (!f.getParentFile().exists()) {
      f.getParentFile().mkdirs();
    }

    // Must be a file; create output stream to the file
    FileOutputStream fostream = new FileOutputStream(f);
    InputStream istream = jarFile.getInputStream(entry);
    
    // extract files
    int n = 0;
    while ((n = istream.read(buffer)) > 0) {
      fostream.write(buffer, 0, n);
    }
    
    try {
      istream.close();
      fostream.close();
    }
    catch (IOException e) {
      // do nothing -- following "Java Examples in a Nutshell" from O'Reilly
    }
  }

  /**
   * Creates a JAR file.  If the JAR file already exists, it will be overwritten.
   *
   * @param jarFile the JAR file to create.
   * @throws IOException if cannot create JAR file.
   * @throws JarException if error putting files into JAR file.
   */
  public void jar(File jarFile) throws IOException, JarException {

    if (!jarFile.getName().endsWith(".jar")) {
      throw new JarException ("Not a zip file? " + jarFile.getName());
    }
    
    // get all files to include in JAR file, except for manifest
    DirectoryScanner scanner = new DirectoryScanner();
    scanner.setIncludes(new String[] {"**"});
    scanner.setExcludes(new String[] {"**" + SLASH + MAN_DIR + SLASH + "**"});
    scanner.setBasedir(new File(this.dir));
    scanner.setCaseSensitive(true);
    scanner.scan();
    String[] directories = scanner.getIncludedDirectories();
    String[] files = scanner.getIncludedFiles();
    
    // create JAR file
    FileOutputStream fostream = new FileOutputStream(jarFile);
    JarOutputStream jostream = new JarOutputStream(fostream);
    
    // create manifest directory and manifest
    if ((new File(dir, MAN_DIR)).exists()) {
      putManifest(jostream);
    }
    
    //create subdirectories
    String currentDirectory = "";
    for (int i = 0; i < directories.length; i++) {
      // do not need to put the current directory in JAR file
      if (directories[i].equals(currentDirectory)) {
        continue;
      }
      putEntry(directories[i] + SLASH, jostream);
    }
    
    // create files
    for (int i = 0; i < files.length; i++) {
      putEntry(files[i], jostream);
    }
    
    jostream.finish();
    
    try {
      jostream.close();
      fostream.close();
    }
    catch (IOException e) {
      // do nothing -- following "Java Examples in a Nutshell" from O'Reilly
    }
  }

  /**
   * Puts manifest file into a JAR file.
   *
   * @param jostream the JAR file to put manifest into.
   * @throws IOException if error trying to write entry.
   */
  private void putManifest(JarOutputStream jostream) throws IOException {

    // begin borrowed code from Ant Jar and Zip classes
    // put the META-INF directory into JAR file.
    String manDirPath = MAN_DIR + SLASH;
    JarEntry manifestDirEntry = new JarEntry(manDirPath.replace(File.separatorChar, '/'));
    manifestDirEntry.setTime(System.currentTimeMillis());
    manifestDirEntry.setSize(0);
    manifestDirEntry.setMethod(JarEntry.STORED);

    // This is faintly ridiculous - empty CRC value
    manifestDirEntry.setCrc((new CRC32()).getValue());
    jostream.putNextEntry(manifestDirEntry);

    // now put the manifest file into JAR file.
    JarEntry manifestFileEntry = new JarEntry(MAN_FILE_PATH.replace(File.separatorChar, '/'));
    manifestFileEntry.setTime(System.currentTimeMillis());
    FileInputStream fistream = new FileInputStream(new File(this.dir, MAN_FILE_PATH));
    jostream.putNextEntry(manifestFileEntry);

    int n = 0;
    while ((n = fistream.read(buffer)) >= 0) {
      jostream.write(buffer, 0, n);
    }
    jostream.closeEntry();

    // end borrowed code from Ant Jar and Zip classes
    try {
      fistream.close();
    }
    catch (IOException e) {
      // do nothing -- following "Java Examples in a Nutshell" from O'Reilly
    }
  }

  /**
   * Puts a file into a JAR file.
   *
   * @param fileName the file to put in the JAR.
   * @param jostream the JAR file to put <code>fileName</code> into.
   * @throws IOException if error trying to write entry.
   */
  private void putEntry(String fileName, JarOutputStream jostream) throws IOException {

    // prepare fileName for entry into JAR file
    String entryName = fileName.replace(File.separatorChar, '/');

    // put directory (remember to create intervening subdirectories if needed!)
    if (entryName.endsWith("/")) {
      jostream.putNextEntry(new JarEntry(entryName));
      jostream.closeEntry();
      return;
    }

    // put file
    FileInputStream fistream = new FileInputStream(new File(this.dir, fileName));
    jostream.putNextEntry(new JarEntry(entryName));
    int n;

    // now read and write the JAR entry data.
    while ((n = fistream.read(buffer)) >= 0) {
      jostream.write(buffer, 0, n);
    }

    jostream.closeEntry();

    try {
      fistream.close();
    }
    catch (IOException e) {
      // do nothing -- following "Java Examples in a Nutshell" from O'Reilly
    }
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.