jdk/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java
changeset 6313 470912c9e214
parent 5506 202f599c92aa
child 7171 ee97f78e7482
equal deleted inserted replaced
6308:7d860a571385 6313:470912c9e214
     1 /*
     1 /*
     2  * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    28 import java.util.*;
    28 import java.util.*;
    29 import java.util.jar.*;
    29 import java.util.jar.*;
    30 import java.util.zip.*;
    30 import java.util.zip.*;
    31 import java.io.*;
    31 import java.io.*;
    32 import java.beans.PropertyChangeListener;
    32 import java.beans.PropertyChangeListener;
    33 import java.beans.PropertyChangeEvent;
       
    34 
    33 
    35 /*
    34 /*
    36  * Implementation of the Pack provider.
    35  * Implementation of the Pack provider.
    37  * </pre></blockquote>
    36  * </pre></blockquote>
    38  * @author John Rose
    37  * @author John Rose
    39  * @author Kumar Srinivasan
    38  * @author Kumar Srinivasan
    40  */
    39  */
    41 
    40 
    42 
    41 
    43 public class UnpackerImpl implements Pack200.Unpacker {
    42 public class UnpackerImpl extends TLGlobals implements Pack200.Unpacker {
    44 
    43 
    45 
    44 
    46     /**
    45     /**
    47      * Register a listener for changes to options.
    46      * Register a listener for changes to options.
    48      * @param listener  An object to be invoked when a property is changed.
    47      * @param listener  An object to be invoked when a property is changed.
    49      */
    48      */
    50     public void addPropertyChangeListener(PropertyChangeListener listener) {
    49     public void addPropertyChangeListener(PropertyChangeListener listener) {
    51         _props.addListener(listener);
    50         props.addListener(listener);
    52     }
    51     }
    53 
    52 
    54 
    53 
    55     /**
    54     /**
    56      * Remove a listener for the PropertyChange event.
    55      * Remove a listener for the PropertyChange event.
    57      * @param listener  The PropertyChange listener to be removed.
    56      * @param listener  The PropertyChange listener to be removed.
    58      */
    57      */
    59     public void removePropertyChangeListener(PropertyChangeListener listener) {
    58     public void removePropertyChangeListener(PropertyChangeListener listener) {
    60         _props.removeListener(listener);
    59         props.removeListener(listener);
    61     }
    60     }
    62 
    61 
    63     public UnpackerImpl() {
    62     public UnpackerImpl() {}
    64         _props = new PropMap();
    63 
    65         //_props.getProperty() consults defaultProps invisibly.
       
    66         //_props.putAll(defaultProps);
       
    67     }
       
    68 
       
    69     // Private stuff.
       
    70     final PropMap _props;
       
    71 
    64 
    72 
    65 
    73     /**
    66     /**
    74      * Get the set of options for the pack and unpack engines.
    67      * Get the set of options for the pack and unpack engines.
    75      * @return A sorted association of option key strings to option values.
    68      * @return A sorted association of option key strings to option values.
    76      */
    69      */
    77     public SortedMap properties() {
    70     public SortedMap<String, String> properties() {
    78         return _props;
    71         return props;
    79     }
    72     }
    80 
    73 
    81     // Back-pointer to NativeUnpacker, when active.
    74     // Back-pointer to NativeUnpacker, when active.
    82     Object _nunp;
    75     Object _nunp;
    83 
    76 
    99      * @param out a JarOutputStream.
    92      * @param out a JarOutputStream.
   100      * @exception IOException if an error is encountered.
    93      * @exception IOException if an error is encountered.
   101      */
    94      */
   102     public void unpack(InputStream in0, JarOutputStream out) throws IOException {
    95     public void unpack(InputStream in0, JarOutputStream out) throws IOException {
   103         assert(Utils.currentInstance.get() == null);
    96         assert(Utils.currentInstance.get() == null);
   104         TimeZone tz = (_props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null :
    97         TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE))
   105             TimeZone.getDefault();
    98                       ? null
       
    99                       : TimeZone.getDefault();
   106 
   100 
   107         try {
   101         try {
   108             Utils.currentInstance.set(this);
   102             Utils.currentInstance.set(this);
   109             if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
   103             if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
   110             final int verbose = _props.getInteger(Utils.DEBUG_VERBOSE);
   104             final int verbose = props.getInteger(Utils.DEBUG_VERBOSE);
   111             BufferedInputStream in = new BufferedInputStream(in0);
   105             BufferedInputStream in = new BufferedInputStream(in0);
   112             if (Utils.isJarMagic(Utils.readMagic(in))) {
   106             if (Utils.isJarMagic(Utils.readMagic(in))) {
   113                 if (verbose > 0)
   107                 if (verbose > 0)
   114                     Utils.log.info("Copying unpacked JAR file...");
   108                     Utils.log.info("Copying unpacked JAR file...");
   115                 Utils.copyJarFile(new JarInputStream(in), out);
   109                 Utils.copyJarFile(new JarInputStream(in), out);
   116             } else if (_props.getBoolean(Utils.DEBUG_DISABLE_NATIVE)) {
   110             } else if (props.getBoolean(Utils.DEBUG_DISABLE_NATIVE)) {
   117                 (new DoUnpack()).run(in, out);
   111                 (new DoUnpack()).run(in, out);
   118                 in.close();
   112                 in.close();
   119                 Utils.markJarFile(out);
   113                 Utils.markJarFile(out);
   120             } else {
   114             } else {
   121                 (new NativeUnpack(this)).run(in, out);
   115                 (new NativeUnpack(this)).run(in, out);
   140     public void unpack(File in, JarOutputStream out) throws IOException {
   134     public void unpack(File in, JarOutputStream out) throws IOException {
   141         // Use the stream-based implementation.
   135         // Use the stream-based implementation.
   142         // %%% Reconsider if native unpacker learns to memory-map the file.
   136         // %%% Reconsider if native unpacker learns to memory-map the file.
   143         FileInputStream instr = new FileInputStream(in);
   137         FileInputStream instr = new FileInputStream(in);
   144         unpack(instr, out);
   138         unpack(instr, out);
   145         if (_props.getBoolean(Utils.UNPACK_REMOVE_PACKFILE)) {
   139         if (props.getBoolean(Utils.UNPACK_REMOVE_PACKFILE)) {
   146             in.delete();
   140             in.delete();
   147         }
   141         }
   148     }
   142     }
   149 
   143 
   150     private class DoUnpack {
   144     private class DoUnpack {
   151         final int verbose = _props.getInteger(Utils.DEBUG_VERBOSE);
   145         final int verbose = props.getInteger(Utils.DEBUG_VERBOSE);
   152 
   146 
   153         {
   147         {
   154             _props.setInteger(Pack200.Unpacker.PROGRESS, 0);
   148             props.setInteger(Pack200.Unpacker.PROGRESS, 0);
   155         }
   149         }
   156 
   150 
   157         // Here's where the bits are read from disk:
   151         // Here's where the bits are read from disk:
   158         final Package pkg = new Package();
   152         final Package pkg = new Package();
   159 
   153 
   160         final boolean keepModtime
   154         final boolean keepModtime
   161             = Pack200.Packer.KEEP.equals(_props.getProperty(Utils.UNPACK_MODIFICATION_TIME, Pack200.Packer.KEEP));
   155             = Pack200.Packer.KEEP.equals(
       
   156               props.getProperty(Utils.UNPACK_MODIFICATION_TIME, Pack200.Packer.KEEP));
   162         final boolean keepDeflateHint
   157         final boolean keepDeflateHint
   163             = Pack200.Packer.KEEP.equals(_props.getProperty(Pack200.Unpacker.DEFLATE_HINT, Pack200.Packer.KEEP));
   158             = Pack200.Packer.KEEP.equals(
       
   159               props.getProperty(Pack200.Unpacker.DEFLATE_HINT, Pack200.Packer.KEEP));
   164         final int modtime;
   160         final int modtime;
   165         final boolean deflateHint;
   161         final boolean deflateHint;
   166         {
   162         {
   167             if (!keepModtime) {
   163             if (!keepModtime) {
   168                 modtime = _props.getTime(Utils.UNPACK_MODIFICATION_TIME);
   164                 modtime = props.getTime(Utils.UNPACK_MODIFICATION_TIME);
   169             } else {
   165             } else {
   170                 modtime = pkg.default_modtime;
   166                 modtime = pkg.default_modtime;
   171             }
   167             }
   172 
   168 
   173             deflateHint = (keepDeflateHint) ? false :
   169             deflateHint = (keepDeflateHint) ? false :
   174                 _props.getBoolean(java.util.jar.Pack200.Unpacker.DEFLATE_HINT);
   170                 props.getBoolean(java.util.jar.Pack200.Unpacker.DEFLATE_HINT);
   175         }
   171         }
   176 
   172 
   177         // Checksum apparatus.
   173         // Checksum apparatus.
   178         final CRC32 crc = new CRC32();
   174         final CRC32 crc = new CRC32();
   179         final ByteArrayOutputStream bufOut = new ByteArrayOutputStream();
   175         final ByteArrayOutputStream bufOut = new ByteArrayOutputStream();
   180         final OutputStream crcOut = new CheckedOutputStream(bufOut, crc);
   176         final OutputStream crcOut = new CheckedOutputStream(bufOut, crc);
   181 
   177 
   182         public void run(BufferedInputStream in, JarOutputStream out) throws IOException {
   178         public void run(BufferedInputStream in, JarOutputStream out) throws IOException {
   183             if (verbose > 0) {
   179             if (verbose > 0) {
   184                 _props.list(System.out);
   180                 props.list(System.out);
   185             }
   181             }
   186             for (int seg = 1; ; seg++) {
   182             for (int seg = 1; ; seg++) {
   187                 unpackSegment(in, out);
   183                 unpackSegment(in, out);
   188 
   184 
   189                 // Try to get another segment.
   185                 // Try to get another segment.
   192                     Utils.log.info("Finished segment #"+seg);
   188                     Utils.log.info("Finished segment #"+seg);
   193             }
   189             }
   194         }
   190         }
   195 
   191 
   196         private void unpackSegment(InputStream in, JarOutputStream out) throws IOException {
   192         private void unpackSegment(InputStream in, JarOutputStream out) throws IOException {
   197             _props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"0");
   193             props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"0");
   198             // Process the output directory or jar output.
   194             // Process the output directory or jar output.
   199             new PackageReader(pkg, in).read();
   195             new PackageReader(pkg, in).read();
   200 
   196 
   201             if (_props.getBoolean("unpack.strip.debug"))    pkg.stripAttributeKind("Debug");
   197             if (props.getBoolean("unpack.strip.debug"))    pkg.stripAttributeKind("Debug");
   202             if (_props.getBoolean("unpack.strip.compile"))  pkg.stripAttributeKind("Compile");
   198             if (props.getBoolean("unpack.strip.compile"))  pkg.stripAttributeKind("Compile");
   203             _props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"50");
   199             props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"50");
   204             pkg.ensureAllClassFiles();
   200             pkg.ensureAllClassFiles();
   205             // Now write out the files.
   201             // Now write out the files.
   206             HashSet classesToWrite = new HashSet(pkg.getClasses());
   202             HashSet<Package.Class> classesToWrite = new HashSet<>(pkg.getClasses());
   207             for (Iterator i = pkg.getFiles().iterator(); i.hasNext(); ) {
   203             for (Iterator i = pkg.getFiles().iterator(); i.hasNext(); ) {
   208                 Package.File file = (Package.File) i.next();
   204                 Package.File file = (Package.File) i.next();
   209                 String name = file.nameString;
   205                 String name = file.nameString;
   210                 JarEntry je = new JarEntry(Utils.getJarEntryName(name));
   206                 JarEntry je = new JarEntry(Utils.getJarEntryName(name));
   211                 boolean deflate;
   207                 boolean deflate;
   212 
   208 
   213                 deflate = (keepDeflateHint) ? (((file.options & Constants.FO_DEFLATE_HINT) != 0) ||
   209                 deflate = (keepDeflateHint)
   214                                                    ((pkg.default_options & Constants.AO_DEFLATE_HINT) != 0)) :
   210                           ? (((file.options & Constants.FO_DEFLATE_HINT) != 0) ||
   215                     deflateHint;
   211                             ((pkg.default_options & Constants.AO_DEFLATE_HINT) != 0))
       
   212                           : deflateHint;
   216 
   213 
   217                 boolean needCRC = !deflate;  // STORE mode requires CRC
   214                 boolean needCRC = !deflate;  // STORE mode requires CRC
   218 
   215 
   219                 if (needCRC)  crc.reset();
   216                 if (needCRC)  crc.reset();
   220                 bufOut.reset();
   217                 bufOut.reset();
   248                 out.closeEntry();
   245                 out.closeEntry();
   249                 if (verbose > 0)
   246                 if (verbose > 0)
   250                     Utils.log.info("Writing "+Utils.zeString((ZipEntry)je));
   247                     Utils.log.info("Writing "+Utils.zeString((ZipEntry)je));
   251             }
   248             }
   252             assert(classesToWrite.isEmpty());
   249             assert(classesToWrite.isEmpty());
   253             _props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"100");
   250             props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"100");
   254             pkg.reset();  // reset for the next segment, if any
   251             pkg.reset();  // reset for the next segment, if any
   255         }
   252         }
   256     }
   253     }
   257 }
   254 }