src/java.base/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java

Print this page


   1 /*
   2  * Copyright (c) 2003, 2013, 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 com.sun.java.util.jar.pack;
  27 
  28 import java.io.BufferedInputStream;
  29 import java.io.ByteArrayOutputStream;
  30 import java.io.File;
  31 import java.io.FileInputStream;
  32 import java.io.IOException;
  33 import java.io.InputStream;
  34 import java.io.OutputStream;


  35 import java.util.HashSet;
  36 import java.util.Set;
  37 import java.util.SortedMap;
  38 import java.util.TimeZone;
  39 import java.util.jar.JarEntry;
  40 import java.util.jar.JarInputStream;
  41 import java.util.jar.JarOutputStream;
  42 import java.util.jar.Pack200;
  43 import java.util.zip.CRC32;
  44 import java.util.zip.CheckedOutputStream;
  45 import java.util.zip.ZipEntry;
  46 
  47 /*
  48  * Implementation of the Pack provider.
  49  * </pre></blockquote>
  50  * @author John Rose
  51  * @author Kumar Srinivasan
  52  */
  53 
  54 
  55 public class UnpackerImpl extends TLGlobals implements Pack200.Unpacker {
  56 
  57     public UnpackerImpl() {}
  58 


  78 
  79     // The unpack worker...
  80     /**
  81      * Takes a packed-stream InputStream, and writes to a JarOutputStream. Internally
  82      * the entire buffer must be read, it may be more efficient to read the packed-stream
  83      * to a file and pass the File object, in the alternate method described below.
  84      * <p>
  85      * Closes its input but not its output.  (The output can accumulate more elements.)
  86      * @param in an InputStream.
  87      * @param out a JarOutputStream.
  88      * @exception IOException if an error is encountered.
  89      */
  90     public synchronized void unpack(InputStream in, JarOutputStream out) throws IOException {
  91         if (in == null) {
  92             throw new NullPointerException("null input");
  93         }
  94         if (out == null) {
  95             throw new NullPointerException("null output");
  96         }
  97         assert(Utils.currentInstance.get() == null);
  98         TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE))
  99                       ? null
 100                       : TimeZone.getDefault();
 101 
 102         try {
 103             Utils.currentInstance.set(this);
 104             if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
 105             final int verbose = props.getInteger(Utils.DEBUG_VERBOSE);
 106             BufferedInputStream in0 = new BufferedInputStream(in);
 107             if (Utils.isJarMagic(Utils.readMagic(in0))) {
 108                 if (verbose > 0)
 109                     Utils.log.info("Copying unpacked JAR file...");
 110                 Utils.copyJarFile(new JarInputStream(in0), out);
 111             } else if (props.getBoolean(Utils.DEBUG_DISABLE_NATIVE)) {
 112                 (new DoUnpack()).run(in0, out);
 113                 in0.close();
 114                 Utils.markJarFile(out);
 115             } else {
 116                 try {
 117                     (new NativeUnpack(this)).run(in0, out);
 118                 } catch (UnsatisfiedLinkError | NoClassDefFoundError ex) {
 119                     // failover to java implementation
 120                     (new DoUnpack()).run(in0, out);
 121                 }
 122                 in0.close();
 123                 Utils.markJarFile(out);
 124             }
 125         } finally {
 126             _nunp = null;
 127             Utils.currentInstance.set(null);
 128             if (tz != null) TimeZone.setDefault(tz);
 129         }
 130     }
 131 
 132     /**
 133      * Takes an input File containing the pack file, and generates a JarOutputStream.
 134      * <p>
 135      * Does not close its output.  (The output can accumulate more elements.)
 136      * @param in a File.
 137      * @param out a JarOutputStream.
 138      * @exception IOException if an error is encountered.
 139      */
 140     public synchronized void unpack(File in, JarOutputStream out) throws IOException {
 141         if (in == null) {
 142             throw new NullPointerException("null input");
 143         }
 144         if (out == null) {
 145             throw new NullPointerException("null output");
 146         }
 147         // Use the stream-based implementation.
 148         // %%% Reconsider if native unpacker learns to memory-map the file.


 229                 bufOut.reset();
 230                 if (file.isClassStub()) {
 231                     Package.Class cls = file.getStubClass();
 232                     assert(cls != null);
 233                     new ClassWriter(cls, needCRC ? crcOut : bufOut).write();
 234                     classesToWrite.remove(cls);  // for an error check
 235                 } else {
 236                     // collect data & maybe CRC
 237                     file.writeTo(needCRC ? crcOut : bufOut);
 238                 }
 239                 je.setMethod(deflate ? JarEntry.DEFLATED : JarEntry.STORED);
 240                 if (needCRC) {
 241                     if (verbose > 0)
 242                         Utils.log.info("stored size="+bufOut.size()+" and crc="+crc.getValue());
 243 
 244                     je.setMethod(JarEntry.STORED);
 245                     je.setSize(bufOut.size());
 246                     je.setCrc(crc.getValue());
 247                 }
 248                 if (keepModtime) {
 249                     je.setTime(file.modtime);
 250                     // Convert back to milliseconds
 251                     je.setTime((long)file.modtime * 1000);
 252                 } else {
 253                     je.setTime((long)modtime * 1000);
 254                 }
 255                 out.putNextEntry(je);
 256                 bufOut.writeTo(out);
 257                 out.closeEntry();
 258                 if (verbose > 0)
 259                     Utils.log.info("Writing "+Utils.zeString((ZipEntry)je));
 260             }
 261             assert(classesToWrite.isEmpty());
 262             props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"100");
 263             pkg.reset();  // reset for the next segment, if any
 264         }
 265     }
 266 }
   1 /*
   2  * Copyright (c) 2003, 2015, 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 com.sun.java.util.jar.pack;
  27 
  28 import java.io.BufferedInputStream;
  29 import java.io.ByteArrayOutputStream;
  30 import java.io.File;
  31 import java.io.FileInputStream;
  32 import java.io.IOException;
  33 import java.io.InputStream;
  34 import java.io.OutputStream;
  35 import java.time.LocalDateTime;
  36 import java.time.ZoneOffset;
  37 import java.util.HashSet;
  38 import java.util.Set;
  39 import java.util.SortedMap;

  40 import java.util.jar.JarEntry;
  41 import java.util.jar.JarInputStream;
  42 import java.util.jar.JarOutputStream;
  43 import java.util.jar.Pack200;
  44 import java.util.zip.CRC32;
  45 import java.util.zip.CheckedOutputStream;
  46 import java.util.zip.ZipEntry;
  47 
  48 /*
  49  * Implementation of the Pack provider.
  50  * </pre></blockquote>
  51  * @author John Rose
  52  * @author Kumar Srinivasan
  53  */
  54 
  55 
  56 public class UnpackerImpl extends TLGlobals implements Pack200.Unpacker {
  57 
  58     public UnpackerImpl() {}
  59 


  79 
  80     // The unpack worker...
  81     /**
  82      * Takes a packed-stream InputStream, and writes to a JarOutputStream. Internally
  83      * the entire buffer must be read, it may be more efficient to read the packed-stream
  84      * to a file and pass the File object, in the alternate method described below.
  85      * <p>
  86      * Closes its input but not its output.  (The output can accumulate more elements.)
  87      * @param in an InputStream.
  88      * @param out a JarOutputStream.
  89      * @exception IOException if an error is encountered.
  90      */
  91     public synchronized void unpack(InputStream in, JarOutputStream out) throws IOException {
  92         if (in == null) {
  93             throw new NullPointerException("null input");
  94         }
  95         if (out == null) {
  96             throw new NullPointerException("null output");
  97         }
  98         assert(Utils.currentInstance.get() == null);



  99 
 100         try {
 101             Utils.currentInstance.set(this);

 102             final int verbose = props.getInteger(Utils.DEBUG_VERBOSE);
 103             BufferedInputStream in0 = new BufferedInputStream(in);
 104             if (Utils.isJarMagic(Utils.readMagic(in0))) {
 105                 if (verbose > 0)
 106                     Utils.log.info("Copying unpacked JAR file...");
 107                 Utils.copyJarFile(new JarInputStream(in0), out);
 108             } else if (props.getBoolean(Utils.DEBUG_DISABLE_NATIVE)) {
 109                 (new DoUnpack()).run(in0, out);
 110                 in0.close();
 111                 Utils.markJarFile(out);
 112             } else {
 113                 try {
 114                     (new NativeUnpack(this)).run(in0, out);
 115                 } catch (UnsatisfiedLinkError | NoClassDefFoundError ex) {
 116                     // failover to java implementation
 117                     (new DoUnpack()).run(in0, out);
 118                 }
 119                 in0.close();
 120                 Utils.markJarFile(out);
 121             }
 122         } finally {
 123             _nunp = null;
 124             Utils.currentInstance.set(null);

 125         }
 126     }
 127 
 128     /**
 129      * Takes an input File containing the pack file, and generates a JarOutputStream.
 130      * <p>
 131      * Does not close its output.  (The output can accumulate more elements.)
 132      * @param in a File.
 133      * @param out a JarOutputStream.
 134      * @exception IOException if an error is encountered.
 135      */
 136     public synchronized void unpack(File in, JarOutputStream out) throws IOException {
 137         if (in == null) {
 138             throw new NullPointerException("null input");
 139         }
 140         if (out == null) {
 141             throw new NullPointerException("null output");
 142         }
 143         // Use the stream-based implementation.
 144         // %%% Reconsider if native unpacker learns to memory-map the file.


 225                 bufOut.reset();
 226                 if (file.isClassStub()) {
 227                     Package.Class cls = file.getStubClass();
 228                     assert(cls != null);
 229                     new ClassWriter(cls, needCRC ? crcOut : bufOut).write();
 230                     classesToWrite.remove(cls);  // for an error check
 231                 } else {
 232                     // collect data & maybe CRC
 233                     file.writeTo(needCRC ? crcOut : bufOut);
 234                 }
 235                 je.setMethod(deflate ? JarEntry.DEFLATED : JarEntry.STORED);
 236                 if (needCRC) {
 237                     if (verbose > 0)
 238                         Utils.log.info("stored size="+bufOut.size()+" and crc="+crc.getValue());
 239 
 240                     je.setMethod(JarEntry.STORED);
 241                     je.setSize(bufOut.size());
 242                     je.setCrc(crc.getValue());
 243                 }
 244                 if (keepModtime) {
 245                     LocalDateTime ldt = LocalDateTime
 246                             .ofEpochSecond(file.modtime, 0, ZoneOffset.UTC);
 247                     je.setTimeLocal(ldt);
 248                 } else {
 249                     je.setTime((long)modtime * 1000);
 250                 }
 251                 out.putNextEntry(je);
 252                 bufOut.writeTo(out);
 253                 out.closeEntry();
 254                 if (verbose > 0)
 255                     Utils.log.info("Writing "+Utils.zeString((ZipEntry)je));
 256             }
 257             assert(classesToWrite.isEmpty());
 258             props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"100");
 259             pkg.reset();  // reset for the next segment, if any
 260         }
 261     }
 262 }