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

    1   /*
    2    * Copyright (c) 1997, 2006, Oracle and/or its affiliates. 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.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package java.util.jar;
   27   
   28   import java.util.zip;
   29   import java.io;
   30   
   31   /**
   32    * The <code>JarOutputStream</code> class is used to write the contents
   33    * of a JAR file to any output stream. It extends the class
   34    * <code>java.util.zip.ZipOutputStream</code> with support
   35    * for writing an optional <code>Manifest</code> entry. The
   36    * <code>Manifest</code> can be used to specify meta-information about
   37    * the JAR file and its entries.
   38    *
   39    * @author  David Connelly
   40    * @see     Manifest
   41    * @see     java.util.zip.ZipOutputStream
   42    * @since   1.2
   43    */
   44   public
   45   class JarOutputStream extends ZipOutputStream {
   46       private static final int JAR_MAGIC = 0xCAFE;
   47   
   48       /**
   49        * Creates a new <code>JarOutputStream</code> with the specified
   50        * <code>Manifest</code>. The manifest is written as the first
   51        * entry to the output stream.
   52        *
   53        * @param out the actual output stream
   54        * @param man the optional <code>Manifest</code>
   55        * @exception IOException if an I/O error has occurred
   56        */
   57       public JarOutputStream(OutputStream out, Manifest man) throws IOException {
   58           super(out);
   59           if (man == null) {
   60               throw new NullPointerException("man");
   61           }
   62           ZipEntry e = new ZipEntry(JarFile.MANIFEST_NAME);
   63           putNextEntry(e);
   64           man.write(new BufferedOutputStream(this));
   65           closeEntry();
   66       }
   67   
   68       /**
   69        * Creates a new <code>JarOutputStream</code> with no manifest.
   70        * @param out the actual output stream
   71        * @exception IOException if an I/O error has occurred
   72        */
   73       public JarOutputStream(OutputStream out) throws IOException {
   74           super(out);
   75       }
   76   
   77       /**
   78        * Begins writing a new JAR file entry and positions the stream
   79        * to the start of the entry data. This method will also close
   80        * any previous entry. The default compression method will be
   81        * used if no compression method was specified for the entry.
   82        * The current time will be used if the entry has no set modification
   83        * time.
   84        *
   85        * @param ze the ZIP/JAR entry to be written
   86        * @exception ZipException if a ZIP error has occurred
   87        * @exception IOException if an I/O error has occurred
   88        */
   89       public void putNextEntry(ZipEntry ze) throws IOException {
   90           if (firstEntry) {
   91               // Make sure that extra field data for first JAR
   92               // entry includes JAR magic number id.
   93               byte[] edata = ze.getExtra();
   94               if (edata == null || !hasMagic(edata)) {
   95                   if (edata == null) {
   96                       edata = new byte[4];
   97                   } else {
   98                       // Prepend magic to existing extra data
   99                       byte[] tmp = new byte[edata.length + 4];
  100                       System.arraycopy(edata, 0, tmp, 4, edata.length);
  101                       edata = tmp;
  102                   }
  103                   set16(edata, 0, JAR_MAGIC); // extra field id
  104                   set16(edata, 2, 0);         // extra field size
  105                   ze.setExtra(edata);
  106               }
  107               firstEntry = false;
  108           }
  109           super.putNextEntry(ze);
  110       }
  111   
  112       private boolean firstEntry = true;
  113   
  114       /*
  115        * Returns true if specified byte array contains the
  116        * jar magic extra field id.
  117        */
  118       private static boolean hasMagic(byte[] edata) {
  119           try {
  120               int i = 0;
  121               while (i < edata.length) {
  122                   if (get16(edata, i) == JAR_MAGIC) {
  123                       return true;
  124                   }
  125                   i += get16(edata, i + 2) + 4;
  126               }
  127           } catch (ArrayIndexOutOfBoundsException e) {
  128               // Invalid extra field data
  129           }
  130           return false;
  131       }
  132   
  133       /*
  134        * Fetches unsigned 16-bit value from byte array at specified offset.
  135        * The bytes are assumed to be in Intel (little-endian) byte order.
  136        */
  137       private static int get16(byte[] b, int off) {
  138           return (b[off] & 0xff) | ((b[off+1] & 0xff) << 8);
  139       }
  140   
  141       /*
  142        * Sets 16-bit value at specified offset. The bytes are assumed to
  143        * be in Intel (little-endian) byte order.
  144        */
  145       private static void set16(byte[] b, int off, int value) {
  146           b[off+0] = (byte)value;
  147           b[off+1] = (byte)(value >> 8);
  148       }
  149   }

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