Utils.java revision 12745:f068a4ffddd2
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 26package com.sun.java.util.jar.pack; 27 28import java.io.BufferedInputStream; 29import java.io.BufferedOutputStream; 30import java.io.File; 31import java.io.FilterOutputStream; 32import java.io.IOException; 33import java.io.InputStream; 34import java.io.OutputStream; 35import java.util.Collections; 36import java.util.Date; 37import java.util.jar.JarEntry; 38import java.util.jar.JarFile; 39import java.util.jar.JarInputStream; 40import java.util.jar.JarOutputStream; 41import java.util.zip.ZipEntry; 42import sun.util.logging.PlatformLogger; 43 44class Utils { 45 static final String COM_PREFIX = "com.sun.java.util.jar.pack."; 46 static final String METAINF = "META-INF"; 47 48 /* 49 * Outputs various diagnostic support information. 50 * If >0, print summary comments (e.g., constant pool info). 51 * If >1, print unit comments (e.g., processing of classes). 52 * If >2, print many comments (e.g., processing of members). 53 * If >3, print tons of comments (e.g., processing of references). 54 * (installer only) 55 */ 56 static final String DEBUG_VERBOSE = COM_PREFIX+"verbose"; 57 58 /* 59 * Disables use of native code, prefers the Java-coded implementation. 60 * (installer only) 61 */ 62 static final String DEBUG_DISABLE_NATIVE = COM_PREFIX+"disable.native"; 63 64 /* 65 * Use the default working TimeZone instead of UTC. 66 * Note: This has installer unpacker implications. 67 * see: zip.cpp which uses gmtime vs. localtime. 68 */ 69 static final String PACK_DEFAULT_TIMEZONE = COM_PREFIX+"default.timezone"; 70 71 /* 72 * Property indicating that the unpacker should 73 * ignore the transmitted PACK_MODIFICATION_TIME, 74 * replacing it by the given value. The value can 75 * be a numeric string, representing the number of 76 * mSecs since the epoch (UTC), or the special string 77 * {@link #NOW}, meaning the current time (UTC). 78 * The default value is the special string {@link #KEEP}, 79 * which asks the unpacker to preserve all transmitted 80 * modification time information. 81 * (installer only) 82 */ 83 static final String UNPACK_MODIFICATION_TIME = COM_PREFIX+"unpack.modification.time"; 84 85 /* 86 * Property indicating that the unpacker strip the 87 * Debug Attributes, if they are present, in the pack stream. 88 * The default value is false. 89 * (installer only) 90 */ 91 static final String UNPACK_STRIP_DEBUG = COM_PREFIX+"unpack.strip.debug"; 92 93 /* 94 * Remove the input file after unpacking. 95 * (installer only) 96 */ 97 static final String UNPACK_REMOVE_PACKFILE = COM_PREFIX+"unpack.remove.packfile"; 98 99 /* 100 * A possible value for MODIFICATION_TIME 101 */ 102 static final String NOW = "now"; 103 // Other debug options: 104 // com...debug.bands=false add band IDs to pack file, to verify sync 105 // com...dump.bands=false dump band contents to local disk 106 // com...no.vary.codings=false turn off coding variation heuristics 107 // com...no.big.strings=false turn off "big string" feature 108 109 /* 110 * If this property is set to {@link #TRUE}, the packer will preserve 111 * the ordering of class files of the original jar in the output archive. 112 * The ordering is preserved only for class-files; resource files 113 * may be reordered. 114 * <p> 115 * If the packer is allowed to reorder class files, it can marginally 116 * decrease the transmitted size of the archive. 117 */ 118 static final String PACK_KEEP_CLASS_ORDER = COM_PREFIX+"keep.class.order"; 119 /* 120 * This string PACK200 is given as a zip comment on all JAR files 121 * produced by this utility. 122 */ 123 static final String PACK_ZIP_ARCHIVE_MARKER_COMMENT = "PACK200"; 124 125 /* 126 * behaviour when we hit a class format error, but not necessarily 127 * an unknown attribute, by default it is allowed to PASS. 128 */ 129 static final String CLASS_FORMAT_ERROR = COM_PREFIX+"class.format.error"; 130 131 // Keep a TLS point to the global data and environment. 132 // This makes it simpler to supply environmental options 133 // to the engine code, especially the native code. 134 static final ThreadLocal<TLGlobals> currentInstance = new ThreadLocal<>(); 135 136 // convenience method to access the TL globals 137 static TLGlobals getTLGlobals() { 138 return currentInstance.get(); 139 } 140 141 static PropMap currentPropMap() { 142 Object obj = currentInstance.get(); 143 if (obj instanceof PackerImpl) 144 return ((PackerImpl)obj).props; 145 if (obj instanceof UnpackerImpl) 146 return ((UnpackerImpl)obj).props; 147 return null; 148 } 149 150 static final boolean nolog 151 = Boolean.getBoolean(COM_PREFIX+"nolog"); 152 153 static final boolean SORT_MEMBERS_DESCR_MAJOR 154 = Boolean.getBoolean(COM_PREFIX+"sort.members.descr.major"); 155 156 static final boolean SORT_HANDLES_KIND_MAJOR 157 = Boolean.getBoolean(COM_PREFIX+"sort.handles.kind.major"); 158 159 static final boolean SORT_INDY_BSS_MAJOR 160 = Boolean.getBoolean(COM_PREFIX+"sort.indy.bss.major"); 161 162 static final boolean SORT_BSS_BSM_MAJOR 163 = Boolean.getBoolean(COM_PREFIX+"sort.bss.bsm.major"); 164 165 static class Pack200Logger { 166 private final String name; 167 private PlatformLogger log; 168 Pack200Logger(String name) { 169 this.name = name; 170 } 171 172 private synchronized PlatformLogger getLogger() { 173 if (log == null) { 174 log = PlatformLogger.getLogger(name); 175 } 176 return log; 177 } 178 179 public void warning(String msg, Object param) { 180 getLogger().warning(msg, param); 181 } 182 183 public void warning(String msg) { 184 warning(msg, null); 185 } 186 187 public void info(String msg) { 188 int verbose = currentPropMap().getInteger(DEBUG_VERBOSE); 189 if (verbose > 0) { 190 if (nolog) { 191 System.out.println(msg); 192 } else { 193 getLogger().info(msg); 194 } 195 } 196 } 197 198 public void fine(String msg) { 199 int verbose = currentPropMap().getInteger(DEBUG_VERBOSE); 200 if (verbose > 0) { 201 System.out.println(msg); 202 } 203 } 204 } 205 206 static final Pack200Logger log 207 = new Pack200Logger("java.util.jar.Pack200"); 208 209 // Returns the Max Version String of this implementation 210 static String getVersionString() { 211 return "Pack200, Vendor: " + 212 System.getProperty("java.vendor") + 213 ", Version: " + Constants.MAX_PACKAGE_VERSION; 214 } 215 216 static void markJarFile(JarOutputStream out) throws IOException { 217 out.setComment(PACK_ZIP_ARCHIVE_MARKER_COMMENT); 218 } 219 220 // -0 mode helper 221 static void copyJarFile(JarInputStream in, JarOutputStream out) throws IOException { 222 if (in.getManifest() != null) { 223 ZipEntry me = new ZipEntry(JarFile.MANIFEST_NAME); 224 out.putNextEntry(me); 225 in.getManifest().write(out); 226 out.closeEntry(); 227 } 228 byte[] buffer = new byte[1 << 14]; 229 for (JarEntry je; (je = in.getNextJarEntry()) != null; ) { 230 out.putNextEntry(je); 231 for (int nr; 0 < (nr = in.read(buffer)); ) { 232 out.write(buffer, 0, nr); 233 } 234 } 235 in.close(); 236 markJarFile(out); // add PACK200 comment 237 } 238 static void copyJarFile(JarFile in, JarOutputStream out) throws IOException { 239 byte[] buffer = new byte[1 << 14]; 240 for (JarEntry je : Collections.list(in.entries())) { 241 out.putNextEntry(je); 242 InputStream ein = in.getInputStream(je); 243 for (int nr; 0 < (nr = ein.read(buffer)); ) { 244 out.write(buffer, 0, nr); 245 } 246 } 247 in.close(); 248 markJarFile(out); // add PACK200 comment 249 } 250 static void copyJarFile(JarInputStream in, OutputStream out) throws IOException { 251 // 4947205 : Peformance is slow when using pack-effort=0 252 out = new BufferedOutputStream(out); 253 out = new NonCloser(out); // protect from JarOutputStream.close() 254 try (JarOutputStream jout = new JarOutputStream(out)) { 255 copyJarFile(in, jout); 256 } 257 } 258 static void copyJarFile(JarFile in, OutputStream out) throws IOException { 259 260 // 4947205 : Peformance is slow when using pack-effort=0 261 out = new BufferedOutputStream(out); 262 out = new NonCloser(out); // protect from JarOutputStream.close() 263 try (JarOutputStream jout = new JarOutputStream(out)) { 264 copyJarFile(in, jout); 265 } 266 } 267 // Wrapper to prevent closing of client-supplied stream. 268 private static 269 class NonCloser extends FilterOutputStream { 270 NonCloser(OutputStream out) { super(out); } 271 public void close() throws IOException { flush(); } 272 } 273 static String getJarEntryName(String name) { 274 if (name == null) return null; 275 return name.replace(File.separatorChar, '/'); 276 } 277 278 static String zeString(ZipEntry ze) { 279 int store = (ze.getCompressedSize() > 0) ? 280 (int)( (1.0 - ((double)ze.getCompressedSize()/(double)ze.getSize()))*100 ) 281 : 0 ; 282 // Follow unzip -lv output 283 return ze.getSize() + "\t" + ze.getMethod() 284 + "\t" + ze.getCompressedSize() + "\t" 285 + store + "%\t" 286 + new Date(ze.getTime()) + "\t" 287 + Long.toHexString(ze.getCrc()) + "\t" 288 + ze.getName() ; 289 } 290 291 292 293 static byte[] readMagic(BufferedInputStream in) throws IOException { 294 in.mark(4); 295 byte[] magic = new byte[4]; 296 for (int i = 0; i < magic.length; i++) { 297 // read 1 byte at a time, so we always get 4 298 if (1 != in.read(magic, i, 1)) 299 break; 300 } 301 in.reset(); 302 return magic; 303 } 304 305 // magic number recognizers 306 static boolean isJarMagic(byte[] magic) { 307 return (magic[0] == (byte)'P' && 308 magic[1] == (byte)'K' && 309 magic[2] >= 1 && 310 magic[2] < 8 && 311 magic[3] == magic[2] + 1); 312 } 313 static boolean isPackMagic(byte[] magic) { 314 return (magic[0] == (byte)0xCA && 315 magic[1] == (byte)0xFE && 316 magic[2] == (byte)0xD0 && 317 magic[3] == (byte)0x0D); 318 } 319 static boolean isGZIPMagic(byte[] magic) { 320 return (magic[0] == (byte)0x1F && 321 magic[1] == (byte)0x8B && 322 magic[2] == (byte)0x08); 323 // fourth byte is variable "flg" field 324 } 325 326 private Utils() { } // do not instantiate 327} 328