home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / jbuilder / unsupported / JDK1.2beta3 / SOURCE / SRC.ZIP / java / util / jar / JarFile.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  7.1 KB  |  260 lines

  1. /*
  2.  * @(#)JarFile.java    1.18 98/03/18
  3.  *
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.util.jar;
  16.  
  17. import java.io.*;
  18. import java.util.Hashtable;
  19. import java.util.Enumeration;
  20. import java.util.zip.*;
  21. import java.lang.reflect.*;
  22. import java.security.Identity;
  23.  
  24. /**
  25.  * The <code>JarFile</code> class is used to read the contents of a JAR file
  26.  * from any file that can be opened with <code>java.io.RandomAccessFile</code>.
  27.  * It extends the class <code>java.util.zip.ZipFile</code> with support
  28.  * for reading an optional <code>Manifest</code> entry. The
  29.  * <code>Manifest</code> can be used to specify meta-information about the
  30.  * JAR file and its entries.
  31.  *
  32.  * @author  David Connelly
  33.  * @version 1.18, 03/18/98
  34.  * @see        Manifest
  35.  * @see     java.util.zip.ZipFile
  36.  * @see     java.util.jar.JarEntry
  37.  * @since   JDK1.2
  38.  */
  39. public
  40. class JarFile extends ZipFile {
  41.     private Manifest man;
  42.     private JarEntry manEntry;
  43.     private boolean verifierInitialized = false;
  44.     private JarVerifier jv;
  45.     private byte[] buffer = new byte[8192];
  46.     private ByteArrayOutputStream baos = new ByteArrayOutputStream(2048);
  47.     private byte[] rawManifestBytes;
  48.  
  49.     public static final String MANIFEST_NAME = "META-INF/MANIFEST.MF";
  50.  
  51.     /**
  52.      * Creates a new, unnamed <code>JarFile</code>.
  53.      */
  54.     protected JarFile() {
  55.     super();
  56.     }
  57.  
  58.     /**
  59.      * Creates a new <code>JarFile</code> to read from the specified
  60.      * file <code>name</code>. The <code>JarFile</code> will be verified if
  61.      * it is signed.
  62.      * @param name the name of the JAR file to be opened for reading
  63.      * @exception FileNotFoundException if the file could not be found
  64.      * @exception IOException if an I/O error has occurred
  65.      */
  66.     public JarFile(String name) throws IOException {
  67.     this(name, true);
  68.     }
  69.  
  70.     /**
  71.      * Creates a new <code>JarFile</code> to read from the specified
  72.      * file <code>name</code>.
  73.      * @param name the name of the JAR file to be opened for reading
  74.      * @param verify whether or not to verify the JarFile if
  75.      * it is signed.
  76.      * @exception FileNotFoundException if the file could not be found
  77.      * @exception IOException if an I/O error has occurred
  78.      */
  79.     public JarFile(String name, boolean verify) throws IOException {
  80.     super(name);
  81.     JarEntry e = (JarEntry)getEntry(MANIFEST_NAME);
  82.     if (e == null) {
  83.         // Check all entries for matching name
  84.         Enumeration enum = entries();
  85.         while (enum.hasMoreElements() && e == null) {
  86.         e = (JarEntry)enum.nextElement();
  87.         if (!MANIFEST_NAME.equalsIgnoreCase(e.getName())) {
  88.             e = null;
  89.         }
  90.         }
  91.     }
  92.  
  93.     if (e != null) {
  94.         man = new Manifest();
  95.         rawManifestBytes = getBytes(e);
  96.         man.read(new ByteArrayInputStream(rawManifestBytes));
  97.         verifierInitialized = !verify;
  98.         manEntry = e;
  99.     }
  100.     }
  101.  
  102.     /**
  103.      * Creates a new <code>JarFile</code> to read from the specified
  104.      * <code>File</code> object. The <code>JarFile</code> will be verified if
  105.      * it is signed.
  106.      * @param file the JAR file to be opened for reading
  107.      * @exception FileNotFoundException if the file could not be found
  108.      * @exception IOException if an I/O error has occurred
  109.      */
  110.     public JarFile(File file) throws IOException {
  111.     this(file.getPath(), true);
  112.     }
  113.  
  114.  
  115.     /**
  116.      * Creates a new <code>JarFile</code> to read from the specified
  117.      * <code>File</code> object.
  118.      * @param file the JAR file to be opened for reading
  119.      * @param verify whether or not to verify the JarFile if
  120.      * it is signed.
  121.      * @exception FileNotFoundException if the file could not be found
  122.      * @exception IOException if an I/O error has occurred
  123.      */
  124.     public JarFile(File file, boolean verify) throws IOException {
  125.     this(file.getPath(), verify);
  126.     }
  127.  
  128.     /**
  129.      * Returns the JAR file manifest, or <code>null</code> if none.
  130.      */
  131.     public Manifest getManifest() {
  132.     return man;
  133.     }
  134.  
  135.     /**
  136.      * Returns the JarEntry for the manifest, or <code>null</code> if none.
  137.      */
  138.     public JarEntry getManifestEntry() {
  139.     return manEntry;
  140.     }
  141.  
  142.     /**
  143.      * Returns the <code>JarEntry</code> for the given entry name. Returns
  144.      * <code>null</code> if there is no entry corresponding to the given name.
  145.      *
  146.      * @param name the JAR file entry name
  147.      * @see java.util.jar.JarEntry
  148.      */
  149.     public JarEntry getJarEntry(String name) {
  150.     return (JarEntry)getEntry(name);
  151.     }
  152.  
  153.  
  154.     /*
  155.      * Initializes the verifier object by reading all the META-INF
  156.      * entries and passing them to the verifier.
  157.      */
  158.     private void initializeVerifier()
  159.     {
  160.     if (verifierInitialized) {
  161.         return;
  162.     }
  163.     verifierInitialized = true;
  164.     if (man == null) {
  165.         return;
  166.     }
  167.     Enumeration e = entries();
  168.     JarEntry je;
  169.     String name;
  170.     try {
  171.         while (e.hasMoreElements()) {
  172.         je = (JarEntry) e.nextElement();
  173.         name = je.getName().toUpperCase();
  174.         if (name.startsWith("META-INF/") && (!je.isDirectory())) {
  175.             byte[] data = getBytes(je);
  176.             if ((data != null) && (data.length > 0)) {
  177.             if (jv == null) {
  178.                 jv = new JarVerifier(man, rawManifestBytes);
  179.                 rawManifestBytes = null;
  180.             }
  181.             jv.beginEntry(je);
  182.             jv.update(data.length, data, 0, data.length);
  183.             jv.update(-1, null, 0, 0);
  184.             }
  185.         }
  186.         }
  187.     } catch (IOException ioe) {
  188.         // if we had an error parsing any blocks, just
  189.         // treat the jar file as being unsigned
  190.         jv = null;
  191.     }
  192.  
  193.     }
  194.  
  195.     /*
  196.      * Reads all the bytes for a given entry. This is needed
  197.      * so we can verify all the bytes before returning them.
  198.      */
  199.     private synchronized byte[] getBytes(ZipEntry ze) 
  200.     throws IOException
  201.     {
  202.     int n;
  203.     InputStream is = super.getInputStream(ze);
  204.  
  205.     baos.reset();
  206.     long left = ze.getSize();
  207.     while((left > 0) && (n = is.read(buffer, 0, buffer.length)) != -1) {
  208.         baos.write(buffer, 0, n);
  209.         left -= n;
  210.     }
  211.     is.close();
  212.  
  213.     return baos.toByteArray();
  214.     }
  215.  
  216.     /**
  217.      * Returns an input stream for reading the contents of the specified
  218.      * ZIP file entry.
  219.      * @param ze the zip file entry
  220.      * @exception ZipException if a ZIP format error has occurred
  221.      * @exception IOException if an I/O error has occurred
  222.      */
  223.     public synchronized InputStream getInputStream(ZipEntry ze) 
  224.     throws IOException 
  225.     {
  226.     if (!verifierInitialized) {
  227.         initializeVerifier();
  228.     }
  229.  
  230.     // if its still null, just return super...
  231.     if (jv == null) {
  232.         return super.getInputStream(ze);
  233.     }
  234.  
  235.     // get the bytes
  236.     byte[] data = getBytes(ze);
  237.  
  238.     // verify them
  239.     jv.beginEntry((JarEntry)ze);
  240.     jv.update(data.length, data, 0, data.length);
  241.     // signals end of entry
  242.     jv.update(-1, null, 0, 0);
  243.  
  244.     // return them
  245.     return new ByteArrayInputStream(data);
  246.     }
  247.  
  248.     /**
  249.      * Creates a new <code>JarEntry</code> for the specified JAR file
  250.      * entry name.
  251.      */
  252.     protected ZipEntry createZipEntry(String name) {
  253.     JarEntry e = new JarEntry(name);
  254.     if (man != null) {
  255.         e.attr = man.getAttributes(name);
  256.     }
  257.     return e;
  258.     }
  259. }
  260.