< prev index next >

src/jdk.jartool/share/classes/sun/tools/jar/Main.java

Print this page
rev 50498 : 8199871: Deprecate pack200 and unpack200 tools
Reviewed-by:


  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 sun.tools.jar;
  27 
  28 import java.io.*;
  29 import java.lang.module.Configuration;
  30 import java.lang.module.FindException;
  31 import java.lang.module.InvalidModuleDescriptorException;
  32 import java.lang.module.ModuleDescriptor;
  33 import java.lang.module.ModuleDescriptor.Exports;
  34 import java.lang.module.ModuleDescriptor.Provides;
  35 import java.lang.module.ModuleDescriptor.Opens;
  36 import java.lang.module.ModuleDescriptor.Requires;
  37 import java.lang.module.ModuleDescriptor.Version;
  38 import java.lang.module.ModuleFinder;
  39 import java.lang.module.ModuleReader;
  40 import java.lang.module.ModuleReference;
  41 import java.lang.module.ResolutionException;
  42 import java.lang.module.ResolvedModule;
  43 import java.net.URI;
  44 import java.nio.ByteBuffer;
  45 import java.nio.file.Path;
  46 import java.nio.file.Files;

  47 import java.nio.file.Paths;
  48 import java.nio.file.StandardCopyOption;

  49 import java.util.*;
  50 import java.util.function.Consumer;
  51 import java.util.function.Supplier;



  52 import java.util.regex.Pattern;
  53 import java.util.stream.Collectors;
  54 import java.util.stream.Stream;
  55 import java.util.zip.*;
  56 import java.util.jar.*;
  57 import java.util.jar.Pack200.*;
  58 import java.util.jar.Manifest;
  59 import java.text.MessageFormat;
  60 
  61 import jdk.internal.module.Checks;
  62 import jdk.internal.module.ModuleHashes;
  63 import jdk.internal.module.ModuleHashesBuilder;
  64 import jdk.internal.module.ModuleInfo;
  65 import jdk.internal.module.ModuleInfoExtender;
  66 import jdk.internal.module.ModuleResolution;
  67 import jdk.internal.module.ModuleTarget;
  68 import jdk.internal.util.jar.JarIndex;
  69 
  70 import static jdk.internal.util.jar.JarIndex.INDEX_NAME;
  71 import static java.util.jar.JarFile.MANIFEST_NAME;
  72 import static java.util.stream.Collectors.joining;
  73 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
  74 
  75 /**
  76  * This class implements a simple utility for creating files in the JAR
  77  * (Java Archive) file format. The JAR format is based on the ZIP file
  78  * format, with optional meta-information stored in a MANIFEST entry.
  79  */
  80 public class Main {
  81     String program;
  82     PrintWriter out, err;
  83     String fname, mname, ename;
  84     String zname = "";
  85     String rootjar = null;
  86 
  87     private static final int BASE_VERSION = 0;
  88 
  89     private static class Entry {
  90         final String name;
  91         final File file;
  92         final boolean isDir;
  93 


 134 
 135     // The last parsed --release value, if any. Used in conjunction with
 136     // "-d,--describe-module" to select the operative module descriptor.
 137     int releaseValue = -1;
 138 
 139     /*
 140      * cflag: create
 141      * uflag: update
 142      * xflag: xtract
 143      * tflag: table
 144      * vflag: verbose
 145      * flag0: no zip compression (store only)
 146      * Mflag: DO NOT generate a manifest file (just ZIP)
 147      * iflag: generate jar index
 148      * nflag: Perform jar normalization at the end
 149      * pflag: preserve/don't strip leading slash and .. component from file name
 150      * dflag: print module descriptor
 151      */
 152     boolean cflag, uflag, xflag, tflag, vflag, flag0, Mflag, iflag, nflag, pflag, dflag;
 153 


 154     /* To support additional GNU Style informational options */
 155     Consumer<PrintWriter> info;
 156 
 157     /* Modular jar related options */
 158     Version moduleVersion;
 159     Pattern modulesToHash;
 160     ModuleResolution moduleResolution = ModuleResolution.empty();
 161     ModuleFinder moduleFinder = ModuleFinder.of();
 162 
 163     static final String MODULE_INFO = "module-info.class";
 164     static final String MANIFEST_DIR = "META-INF/";
 165     static final String VERSIONS_DIR = MANIFEST_DIR + "versions/";
 166     static final String VERSION = "1.0";
 167     static final int VERSIONS_DIR_LENGTH = VERSIONS_DIR.length();
 168     private static ResourceBundle rsrc;
 169 
 170     /**
 171      * If true, maintain compatibility with JDK releases prior to 6.0 by
 172      * timestamping extracted files with the time at which they are extracted.
 173      * Default is to use the time given in the archive.


 221         this.program = program;
 222     }
 223 
 224     /**
 225      * Creates a new empty temporary file in the same directory as the
 226      * specified file.  A variant of File.createTempFile.
 227      */
 228     private static File createTempFileInSameDirectoryAs(File file)
 229         throws IOException {
 230         File dir = file.getParentFile();
 231         if (dir == null)
 232             dir = new File(".");
 233         return File.createTempFile("jartmp", null, dir);
 234     }
 235 
 236     private boolean ok;
 237 
 238     /**
 239      * Starts main program with the specified arguments.
 240      */

 241     public synchronized boolean run(String args[]) {
 242         ok = true;
 243         if (!parseArgs(args)) {
 244             return false;
 245         }
 246         File tmpFile = null;
 247         try {
 248             if (cflag || uflag) {
 249                 if (fname != null) {
 250                     // The name of the zip file as it would appear as its own
 251                     // zip file entry. We use this to make sure that we don't
 252                     // add the zip file to itself.
 253                     zname = fname.replace(File.separatorChar, '/');
 254                     if (zname.startsWith("./")) {
 255                         zname = zname.substring(2);
 256                     }
 257                 }
 258             }
 259             if (cflag) {
 260                 Manifest manifest = null;


 298 
 299                 } else if (moduleVersion != null || modulesToHash != null) {
 300                     error(getMsg("error.module.options.without.info"));
 301                     return false;
 302                 }
 303                 if (vflag && fname == null) {
 304                     // Disable verbose output so that it does not appear
 305                     // on stdout along with file data
 306                     // error("Warning: -v option ignored");
 307                     vflag = false;
 308                 }
 309                 final String tmpbase = (fname == null)
 310                         ? "tmpjar"
 311                         : fname.substring(fname.indexOf(File.separatorChar) + 1);
 312 
 313                 tmpFile = createTemporaryFile(tmpbase, ".jar");
 314                 try (OutputStream out = new FileOutputStream(tmpFile)) {
 315                     create(new BufferedOutputStream(out, 4096), manifest);
 316                 }
 317                 if (nflag) {



 318                     File packFile = createTemporaryFile(tmpbase, ".pack");
 319                     try {
 320                         Packer packer = Pack200.newPacker();
 321                         Map<String, String> p = packer.properties();
 322                         p.put(Packer.EFFORT, "1"); // Minimal effort to conserve CPU
 323                         try (JarFile jarFile = new JarFile(tmpFile.getCanonicalPath());
 324                              OutputStream pack = new FileOutputStream(packFile))
 325                         {
 326                             packer.pack(jarFile, pack);
 327                         }
 328                         if (tmpFile.exists()) {
 329                             tmpFile.delete();
 330                         }
 331                         tmpFile = createTemporaryFile(tmpbase, ".jar");
 332                         try (OutputStream out = new FileOutputStream(tmpFile);
 333                              JarOutputStream jos = new JarOutputStream(out))
 334                         {
 335                             Unpacker unpacker = Pack200.newUnpacker();
 336                             unpacker.unpack(packFile, jos);
 337                         }
 338                     } finally {
 339                         Files.deleteIfExists(packFile.toPath());
 340                     }
 341                 }
 342                 validateAndClose(tmpFile);
 343             } else if (uflag) {
 344                 File inputFile = null;
 345                 if (fname != null) {
 346                     inputFile = new File(fname);
 347                     tmpFile = createTempFileInSameDirectoryAs(inputFile);
 348                 } else {
 349                     vflag = false;
 350                     tmpFile = createTemporaryFile("tmpjar", ".jar");
 351                 }
 352                 expand();
 353                 try (FileInputStream in = (fname != null) ? new FileInputStream(inputFile)
 354                         : new FileInputStream(FileDescriptor.in);
 355                      FileOutputStream out = new FileOutputStream(tmpFile);




  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 sun.tools.jar;
  27 
  28 import java.io.*;
  29 import java.lang.module.Configuration;
  30 import java.lang.module.FindException;
  31 import java.lang.module.InvalidModuleDescriptorException;
  32 import java.lang.module.ModuleDescriptor;
  33 import java.lang.module.ModuleDescriptor.Exports;

  34 import java.lang.module.ModuleDescriptor.Opens;
  35 import java.lang.module.ModuleDescriptor.Provides;
  36 import java.lang.module.ModuleDescriptor.Version;
  37 import java.lang.module.ModuleFinder;
  38 import java.lang.module.ModuleReader;
  39 import java.lang.module.ModuleReference;

  40 import java.lang.module.ResolvedModule;
  41 import java.net.URI;
  42 import java.nio.ByteBuffer;

  43 import java.nio.file.Files;
  44 import java.nio.file.Path;
  45 import java.nio.file.Paths;
  46 import java.nio.file.StandardCopyOption;
  47 import java.text.MessageFormat;
  48 import java.util.*;
  49 import java.util.function.Consumer;
  50 import java.util.jar.Attributes;
  51 import java.util.jar.JarFile;
  52 import java.util.jar.JarOutputStream;
  53 import java.util.jar.Manifest;
  54 import java.util.regex.Pattern;
  55 import java.util.stream.Collectors;
  56 import java.util.stream.Stream;
  57 import java.util.zip.CRC32;
  58 import java.util.zip.ZipEntry;
  59 import java.util.zip.ZipFile;
  60 import java.util.zip.ZipInputStream;
  61 import java.util.zip.ZipOutputStream;

  62 import jdk.internal.module.Checks;
  63 import jdk.internal.module.ModuleHashes;
  64 import jdk.internal.module.ModuleHashesBuilder;
  65 import jdk.internal.module.ModuleInfo;
  66 import jdk.internal.module.ModuleInfoExtender;
  67 import jdk.internal.module.ModuleResolution;
  68 import jdk.internal.module.ModuleTarget;
  69 import jdk.internal.util.jar.JarIndex;
  70 
  71 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
  72 import static java.util.jar.JarFile.MANIFEST_NAME;
  73 import static java.util.stream.Collectors.joining;
  74 import static jdk.internal.util.jar.JarIndex.INDEX_NAME;
  75 
  76 /**
  77  * This class implements a simple utility for creating files in the JAR
  78  * (Java Archive) file format. The JAR format is based on the ZIP file
  79  * format, with optional meta-information stored in a MANIFEST entry.
  80  */
  81 public class Main {
  82     String program;
  83     PrintWriter out, err;
  84     String fname, mname, ename;
  85     String zname = "";
  86     String rootjar = null;
  87 
  88     private static final int BASE_VERSION = 0;
  89 
  90     private static class Entry {
  91         final String name;
  92         final File file;
  93         final boolean isDir;
  94 


 135 
 136     // The last parsed --release value, if any. Used in conjunction with
 137     // "-d,--describe-module" to select the operative module descriptor.
 138     int releaseValue = -1;
 139 
 140     /*
 141      * cflag: create
 142      * uflag: update
 143      * xflag: xtract
 144      * tflag: table
 145      * vflag: verbose
 146      * flag0: no zip compression (store only)
 147      * Mflag: DO NOT generate a manifest file (just ZIP)
 148      * iflag: generate jar index
 149      * nflag: Perform jar normalization at the end
 150      * pflag: preserve/don't strip leading slash and .. component from file name
 151      * dflag: print module descriptor
 152      */
 153     boolean cflag, uflag, xflag, tflag, vflag, flag0, Mflag, iflag, nflag, pflag, dflag;
 154 
 155     boolean suppressDeprecateMsg = false;
 156 
 157     /* To support additional GNU Style informational options */
 158     Consumer<PrintWriter> info;
 159 
 160     /* Modular jar related options */
 161     Version moduleVersion;
 162     Pattern modulesToHash;
 163     ModuleResolution moduleResolution = ModuleResolution.empty();
 164     ModuleFinder moduleFinder = ModuleFinder.of();
 165 
 166     static final String MODULE_INFO = "module-info.class";
 167     static final String MANIFEST_DIR = "META-INF/";
 168     static final String VERSIONS_DIR = MANIFEST_DIR + "versions/";
 169     static final String VERSION = "1.0";
 170     static final int VERSIONS_DIR_LENGTH = VERSIONS_DIR.length();
 171     private static ResourceBundle rsrc;
 172 
 173     /**
 174      * If true, maintain compatibility with JDK releases prior to 6.0 by
 175      * timestamping extracted files with the time at which they are extracted.
 176      * Default is to use the time given in the archive.


 224         this.program = program;
 225     }
 226 
 227     /**
 228      * Creates a new empty temporary file in the same directory as the
 229      * specified file.  A variant of File.createTempFile.
 230      */
 231     private static File createTempFileInSameDirectoryAs(File file)
 232         throws IOException {
 233         File dir = file.getParentFile();
 234         if (dir == null)
 235             dir = new File(".");
 236         return File.createTempFile("jartmp", null, dir);
 237     }
 238 
 239     private boolean ok;
 240 
 241     /**
 242      * Starts main program with the specified arguments.
 243      */
 244     @SuppressWarnings({"removal"})
 245     public synchronized boolean run(String args[]) {
 246         ok = true;
 247         if (!parseArgs(args)) {
 248             return false;
 249         }
 250         File tmpFile = null;
 251         try {
 252             if (cflag || uflag) {
 253                 if (fname != null) {
 254                     // The name of the zip file as it would appear as its own
 255                     // zip file entry. We use this to make sure that we don't
 256                     // add the zip file to itself.
 257                     zname = fname.replace(File.separatorChar, '/');
 258                     if (zname.startsWith("./")) {
 259                         zname = zname.substring(2);
 260                     }
 261                 }
 262             }
 263             if (cflag) {
 264                 Manifest manifest = null;


 302 
 303                 } else if (moduleVersion != null || modulesToHash != null) {
 304                     error(getMsg("error.module.options.without.info"));
 305                     return false;
 306                 }
 307                 if (vflag && fname == null) {
 308                     // Disable verbose output so that it does not appear
 309                     // on stdout along with file data
 310                     // error("Warning: -v option ignored");
 311                     vflag = false;
 312                 }
 313                 final String tmpbase = (fname == null)
 314                         ? "tmpjar"
 315                         : fname.substring(fname.indexOf(File.separatorChar) + 1);
 316 
 317                 tmpFile = createTemporaryFile(tmpbase, ".jar");
 318                 try (OutputStream out = new FileOutputStream(tmpFile)) {
 319                     create(new BufferedOutputStream(out, 4096), manifest);
 320                 }
 321                 if (nflag) {
 322                     if (!suppressDeprecateMsg) {
 323                         warn(formatMsg("warn.flag.is.deprecated", "-n"));
 324                     }
 325                     File packFile = createTemporaryFile(tmpbase, ".pack");
 326                     try {
 327                         java.util.jar.Pack200.Packer packer = java.util.jar.Pack200.newPacker();
 328                         Map<String, String> p = packer.properties();
 329                         p.put(java.util.jar.Pack200.Packer.EFFORT, "1"); // Minimal effort to conserve CPU
 330                         try (JarFile jarFile = new JarFile(tmpFile.getCanonicalPath());
 331                              OutputStream pack = new FileOutputStream(packFile))
 332                         {
 333                             packer.pack(jarFile, pack);
 334                         }
 335                         if (tmpFile.exists()) {
 336                             tmpFile.delete();
 337                         }
 338                         tmpFile = createTemporaryFile(tmpbase, ".jar");
 339                         try (OutputStream out = new FileOutputStream(tmpFile);
 340                              JarOutputStream jos = new JarOutputStream(out))
 341                         {
 342                             java.util.jar.Pack200.Unpacker unpacker = java.util.jar.Pack200.newUnpacker();
 343                             unpacker.unpack(packFile, jos);
 344                         }
 345                     } finally {
 346                         Files.deleteIfExists(packFile.toPath());
 347                     }
 348                 }
 349                 validateAndClose(tmpFile);
 350             } else if (uflag) {
 351                 File inputFile = null;
 352                 if (fname != null) {
 353                     inputFile = new File(fname);
 354                     tmpFile = createTempFileInSameDirectoryAs(inputFile);
 355                 } else {
 356                     vflag = false;
 357                     tmpFile = createTemporaryFile("tmpjar", ".jar");
 358                 }
 359                 expand();
 360                 try (FileInputStream in = (fname != null) ? new FileInputStream(inputFile)
 361                         : new FileInputStream(FileDescriptor.in);
 362                      FileOutputStream out = new FileOutputStream(tmpFile);


< prev index next >