Save This Page
Home » openjdk-7 » java » util » jar » [javadoc | source]
    1   /*
    2    * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package java.util.jar;
   27   
   28   import java.util.zip;
   29   import java.io;
   30   import sun.security.util.ManifestEntryVerifier;
   31   
   32   /**
   33    * The <code>JarInputStream</code> class is used to read the contents of
   34    * a JAR file from any input stream. It extends the class
   35    * <code>java.util.zip.ZipInputStream</code> with support for reading
   36    * an optional <code>Manifest</code> entry. The <code>Manifest</code>
   37    * can be used to store meta-information about the JAR file and its entries.
   38    *
   39    * @author  David Connelly
   40    * @see     Manifest
   41    * @see     java.util.zip.ZipInputStream
   42    * @since   1.2
   43    */
   44   public
   45   class JarInputStream extends ZipInputStream {
   46       private Manifest man;
   47       private JarEntry first;
   48       private JarVerifier jv;
   49       private ManifestEntryVerifier mev;
   50   
   51   
   52       /**
   53        * Creates a new <code>JarInputStream</code> and reads the optional
   54        * manifest. If a manifest is present, also attempts to verify
   55        * the signatures if the JarInputStream is signed.
   56        * @param in the actual input stream
   57        * @exception IOException if an I/O error has occurred
   58        */
   59       public JarInputStream(InputStream in) throws IOException {
   60           this(in, true);
   61       }
   62   
   63       /**
   64        * Creates a new <code>JarInputStream</code> and reads the optional
   65        * manifest. If a manifest is present and verify is true, also attempts
   66        * to verify the signatures if the JarInputStream is signed.
   67        *
   68        * @param in the actual input stream
   69        * @param verify whether or not to verify the JarInputStream if
   70        * it is signed.
   71        * @exception IOException if an I/O error has occurred
   72        */
   73       public JarInputStream(InputStream in, boolean verify) throws IOException {
   74           super(in);
   75           JarEntry e = (JarEntry)super.getNextEntry();
   76   
   77           if (e != null && e.getName().equalsIgnoreCase("META-INF/"))
   78               e = (JarEntry)super.getNextEntry();
   79   
   80           if (e != null && JarFile.MANIFEST_NAME.equalsIgnoreCase(e.getName())) {
   81               man = new Manifest();
   82               byte bytes[] = getBytes(new BufferedInputStream(this));
   83               man.read(new ByteArrayInputStream(bytes));
   84               //man.read(new BufferedInputStream(this));
   85               closeEntry();
   86               if (verify) {
   87                   jv = new JarVerifier(bytes);
   88                   mev = new ManifestEntryVerifier(man);
   89               }
   90               first = getNextJarEntry();
   91           } else {
   92               first = e;
   93           }
   94       }
   95   
   96       private byte[] getBytes(InputStream is)
   97           throws IOException
   98       {
   99           byte[] buffer = new byte[8192];
  100           ByteArrayOutputStream baos = new ByteArrayOutputStream(2048);
  101   
  102           int n;
  103   
  104           baos.reset();
  105           while ((n = is.read(buffer, 0, buffer.length)) != -1) {
  106               baos.write(buffer, 0, n);
  107           }
  108           return baos.toByteArray();
  109       }
  110   
  111       /**
  112        * Returns the <code>Manifest</code> for this JAR file, or
  113        * <code>null</code> if none.
  114        *
  115        * @return the <code>Manifest</code> for this JAR file, or
  116        *         <code>null</code> if none.
  117        */
  118       public Manifest getManifest() {
  119           return man;
  120       }
  121   
  122       /**
  123        * Reads the next ZIP file entry and positions the stream at the
  124        * beginning of the entry data. If verification has been enabled,
  125        * any invalid signature detected while positioning the stream for
  126        * the next entry will result in an exception.
  127        * @exception ZipException if a ZIP file error has occurred
  128        * @exception IOException if an I/O error has occurred
  129        * @exception SecurityException if any of the jar file entries
  130        *         are incorrectly signed.
  131        */
  132       public ZipEntry getNextEntry() throws IOException {
  133           JarEntry e;
  134           if (first == null) {
  135               e = (JarEntry)super.getNextEntry();
  136           } else {
  137               e = first;
  138               first = null;
  139           }
  140           if (jv != null && e != null) {
  141               // At this point, we might have parsed all the meta-inf
  142               // entries and have nothing to verify. If we have
  143               // nothing to verify, get rid of the JarVerifier object.
  144               if (jv.nothingToVerify() == true) {
  145                   jv = null;
  146                   mev = null;
  147               } else {
  148                   jv.beginEntry(e, mev);
  149               }
  150           }
  151           return e;
  152       }
  153   
  154       /**
  155        * Reads the next JAR file entry and positions the stream at the
  156        * beginning of the entry data. If verification has been enabled,
  157        * any invalid signature detected while positioning the stream for
  158        * the next entry will result in an exception.
  159        * @return the next JAR file entry, or null if there are no more entries
  160        * @exception ZipException if a ZIP file error has occurred
  161        * @exception IOException if an I/O error has occurred
  162        * @exception SecurityException if any of the jar file entries
  163        *         are incorrectly signed.
  164        */
  165       public JarEntry getNextJarEntry() throws IOException {
  166           return (JarEntry)getNextEntry();
  167       }
  168   
  169       /**
  170        * Reads from the current JAR file entry into an array of bytes.
  171        * If <code>len</code> is not zero, the method
  172        * blocks until some input is available; otherwise, no
  173        * bytes are read and <code>0</code> is returned.
  174        * If verification has been enabled, any invalid signature
  175        * on the current entry will be reported at some point before the
  176        * end of the entry is reached.
  177        * @param b the buffer into which the data is read
  178        * @param off the start offset in the destination array <code>b</code>
  179        * @param len the maximum number of bytes to read
  180        * @return the actual number of bytes read, or -1 if the end of the
  181        *         entry is reached
  182        * @exception  NullPointerException If <code>b</code> is <code>null</code>.
  183        * @exception  IndexOutOfBoundsException If <code>off</code> is negative,
  184        * <code>len</code> is negative, or <code>len</code> is greater than
  185        * <code>b.length - off</code>
  186        * @exception ZipException if a ZIP file error has occurred
  187        * @exception IOException if an I/O error has occurred
  188        * @exception SecurityException if any of the jar file entries
  189        *         are incorrectly signed.
  190        */
  191       public int read(byte[] b, int off, int len) throws IOException {
  192           int n;
  193           if (first == null) {
  194               n = super.read(b, off, len);
  195           } else {
  196               n = -1;
  197           }
  198           if (jv != null) {
  199               jv.update(n, b, off, len, mev);
  200           }
  201           return n;
  202       }
  203   
  204       /**
  205        * Creates a new <code>JarEntry</code> (<code>ZipEntry</code>) for the
  206        * specified JAR file entry name. The manifest attributes of
  207        * the specified JAR file entry name will be copied to the new
  208        * <CODE>JarEntry</CODE>.
  209        *
  210        * @param name the name of the JAR/ZIP file entry
  211        * @return the <code>JarEntry</code> object just created
  212        */
  213       protected ZipEntry createZipEntry(String name) {
  214           JarEntry e = new JarEntry(name);
  215           if (man != null) {
  216               e.attr = man.getAttributes(name);
  217           }
  218           return e;
  219       }
  220   }

Save This Page
Home » openjdk-7 » java » util » jar » [javadoc | source]