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