1 /* 2 * Copyright (c) 2003, 2017, 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 package java.util.jar; 26 27 import java.util.SortedMap; 28 import java.io.InputStream; 29 import java.io.OutputStream; 30 import java.io.File; 31 import java.io.IOException; 32 import sun.security.action.GetPropertyAction; 33 34 35 /** 36 * Transforms a JAR file to or from a packed stream in Pack200 format. 37 * Please refer to <a href="{@docRoot}/../specs/pack-spec.html">Network Transfer Format JSR 200 Specification</a> 38 * <p> 39 * Typically the packer engine is used by application developers 40 * to deploy or host JAR files on a website. 41 * The unpacker engine is used by deployment applications to 42 * transform the byte-stream back to JAR format. 43 * <p> 44 * Here is an example using packer and unpacker: 45 * <pre>{@code 46 * import java.util.jar.Pack200; 47 * import java.util.jar.Pack200.*; 48 * ... 49 * // Create the Packer object 50 * Packer packer = Pack200.newPacker(); 51 * 52 * // Initialize the state by setting the desired properties 53 * Map p = packer.properties(); 54 * // take more time choosing codings for better compression 55 * p.put(Packer.EFFORT, "7"); // default is "5" 56 * // use largest-possible archive segments (>10% better compression). 57 * p.put(Packer.SEGMENT_LIMIT, "-1"); 58 * // reorder files for better compression. 59 * p.put(Packer.KEEP_FILE_ORDER, Packer.FALSE); 60 * // smear modification times to a single value. 61 * p.put(Packer.MODIFICATION_TIME, Packer.LATEST); 62 * // ignore all JAR deflation requests, 63 * // transmitting a single request to use "store" mode. 64 * p.put(Packer.DEFLATE_HINT, Packer.FALSE); 65 * // discard debug attributes 66 * p.put(Packer.CODE_ATTRIBUTE_PFX+"LineNumberTable", Packer.STRIP); 67 * // throw an error if an attribute is unrecognized 68 * p.put(Packer.UNKNOWN_ATTRIBUTE, Packer.ERROR); 69 * // pass one class file uncompressed: 70 * p.put(Packer.PASS_FILE_PFX+0, "mutants/Rogue.class"); 71 * try { 72 * JarFile jarFile = new JarFile("/tmp/testref.jar"); 73 * FileOutputStream fos = new FileOutputStream("/tmp/test.pack"); 74 * // Call the packer 75 * packer.pack(jarFile, fos); 76 * jarFile.close(); 77 * fos.close(); 78 * 79 * File f = new File("/tmp/test.pack"); 80 * FileOutputStream fostream = new FileOutputStream("/tmp/test.jar"); 81 * JarOutputStream jostream = new JarOutputStream(fostream); 82 * Unpacker unpacker = Pack200.newUnpacker(); 83 * // Call the unpacker 84 * unpacker.unpack(f, jostream); 85 * // Must explicitly close the output. 86 * jostream.close(); 87 * } catch (IOException ioe) { 88 * ioe.printStackTrace(); 89 * } 90 * }</pre> 91 * <p> 92 * A Pack200 file compressed with gzip can be hosted on HTTP/1.1 web servers. 93 * The deployment applications can use "Accept-Encoding=pack200-gzip". This 94 * indicates to the server that the client application desires a version of 95 * the file encoded with Pack200 and further compressed with gzip. Please 96 * refer to the Java Deployment Guide for techniques and details. 97 * <p> 98 * Unless otherwise noted, passing a {@code null} argument to a constructor or 99 * method in this class will cause a {@link NullPointerException} to be thrown. 100 * 101 * @author John Rose 102 * @author Kumar Srinivasan 103 * @since 1.5 104 * @deprecated This class has been deprecated 105 */ 106 @Deprecated(since="11", forRemoval=true) 107 public abstract class Pack200 { 108 private Pack200() {} //prevent instantiation 109 110 // Static methods of the Pack200 class. 111 /** 112 * Obtain new instance of a class that implements Packer. 113 * <ul> 114 * <li><p>If the system property {@code java.util.jar.Pack200.Packer} 115 * is defined, then the value is taken to be the fully-qualified name 116 * of a concrete implementation class, which must implement Packer. 117 * This class is loaded and instantiated. If this process fails 118 * then an unspecified error is thrown.</p></li> 119 * 120 * <li><p>If an implementation has not been specified with the system 121 * property, then the system-default implementation class is instantiated, 122 * and the result is returned.</p></li> 123 * </ul> 124 * 125 * <p>Note: The returned object is not guaranteed to operate 126 * correctly if multiple threads use it at the same time. 127 * A multi-threaded application should either allocate multiple 128 * packer engines, or else serialize use of one engine with a lock. 129 * 130 * @return A newly allocated Packer engine. 131 */ 132 public static synchronized Packer newPacker() { 133 return (Packer) newInstance(PACK_PROVIDER); 134 } 135 136 137 /** 138 * Obtain new instance of a class that implements Unpacker. 139 * <ul> 140 * <li><p>If the system property {@code java.util.jar.Pack200.Unpacker} 141 * is defined, then the value is taken to be the fully-qualified 142 * name of a concrete implementation class, which must implement Unpacker. 143 * The class is loaded and instantiated. If this process fails 144 * then an unspecified error is thrown.</p></li> 145 * 146 * <li><p>If an implementation has not been specified with the 147 * system property, then the system-default implementation class 148 * is instantiated, and the result is returned.</p></li> 149 * </ul> 150 * 151 * <p>Note: The returned object is not guaranteed to operate 152 * correctly if multiple threads use it at the same time. 153 * A multi-threaded application should either allocate multiple 154 * unpacker engines, or else serialize use of one engine with a lock. 155 * 156 * @return A newly allocated Unpacker engine. 157 */ 158 159 public static Unpacker newUnpacker() { 160 return (Unpacker) newInstance(UNPACK_PROVIDER); 161 } 162 163 // Interfaces 164 /** 165 * The packer engine applies various transformations to the input JAR file, 166 * making the pack stream highly compressible by a compressor such as 167 * gzip or zip. An instance of the engine can be obtained 168 * using {@link #newPacker}. 169 170 * The high degree of compression is achieved 171 * by using a number of techniques described in the JSR 200 specification. 172 * Some of the techniques are sorting, re-ordering and co-location of the 173 * constant pool. 174 * <p> 175 * The pack engine is initialized to an initial state as described 176 * by their properties below. 177 * The initial state can be manipulated by getting the 178 * engine properties (using {@link #properties}) and storing 179 * the modified properties on the map. 180 * The resource files will be passed through with no changes at all. 181 * The class files will not contain identical bytes, since the unpacker 182 * is free to change minor class file features such as constant pool order. 183 * However, the class files will be semantically identical, 184 * as specified in 185 * <cite>The Java™ Virtual Machine Specification</cite>. 186 * <p> 187 * By default, the packer does not change the order of JAR elements. 188 * Also, the modification time and deflation hint of each 189 * JAR element is passed unchanged. 190 * (Any other ZIP-archive information, such as extra attributes 191 * giving Unix file permissions, are lost.) 192 * <p> 193 * Note that packing and unpacking a JAR will in general alter the 194 * bytewise contents of classfiles in the JAR. This means that packing 195 * and unpacking will in general invalidate any digital signatures 196 * which rely on bytewise images of JAR elements. In order both to sign 197 * and to pack a JAR, you must first pack and unpack the JAR to 198 * "normalize" it, then compute signatures on the unpacked JAR elements, 199 * and finally repack the signed JAR. 200 * Both packing steps should 201 * use precisely the same options, and the segment limit may also 202 * need to be set to "-1", to prevent accidental variation of segment 203 * boundaries as class file sizes change slightly. 204 * <p> 205 * (Here's why this works: Any reordering the packer does 206 * of any classfile structures is idempotent, so the second packing 207 * does not change the orderings produced by the first packing. 208 * Also, the unpacker is guaranteed by the JSR 200 specification 209 * to produce a specific bytewise image for any given transmission 210 * ordering of archive elements.) 211 * <p> 212 * In order to maintain backward compatibility, the pack file's version is 213 * set to accommodate the class files present in the input JAR file. In 214 * other words, the pack file version will be the latest, if the class files 215 * are the latest and conversely the pack file version will be the oldest 216 * if the class file versions are also the oldest. For intermediate class 217 * file versions the corresponding pack file version will be used. 218 * For example: 219 * If the input JAR-files are solely comprised of 1.5 (or lesser) 220 * class files, a 1.5 compatible pack file is produced. This will also be 221 * the case for archives that have no class files. 222 * If the input JAR-files contains a 1.6 class file, then the pack file 223 * version will be set to 1.6. 224 * <p> 225 * Note: Unless otherwise noted, passing a {@code null} argument to a 226 * constructor or method in this class will cause a {@link NullPointerException} 227 * to be thrown. 228 * 229 * @since 1.5 230 */ 231 @Deprecated(since="11", forRemoval=true) 232 public interface Packer { 233 /** 234 * This property is a numeral giving the estimated target size N 235 * (in bytes) of each archive segment. 236 * If a single input file requires more than N bytes, 237 * it will be given its own archive segment. 238 * <p> 239 * As a special case, a value of -1 will produce a single large 240 * segment with all input files, while a value of 0 will 241 * produce one segment for each class. 242 * Larger archive segments result in less fragmentation and 243 * better compression, but processing them requires more memory. 244 * <p> 245 * The size of each segment is estimated by counting the size of each 246 * input file to be transmitted in the segment, along with the size 247 * of its name and other transmitted properties. 248 * <p> 249 * The default is -1, which means the packer will always create a single 250 * segment output file. In cases where extremely large output files are 251 * generated, users are strongly encouraged to use segmenting or break 252 * up the input file into smaller JARs. 253 * <p> 254 * A 10Mb JAR packed without this limit will 255 * typically pack about 10% smaller, but the packer may require 256 * a larger Java heap (about ten times the segment limit). 257 */ 258 String SEGMENT_LIMIT = "pack.segment.limit"; 259 260 /** 261 * If this property is set to {@link #TRUE}, the packer will transmit 262 * all elements in their original order within the source archive. 263 * <p> 264 * If it is set to {@link #FALSE}, the packer may reorder elements, 265 * and also remove JAR directory entries, which carry no useful 266 * information for Java applications. 267 * (Typically this enables better compression.) 268 * <p> 269 * The default is {@link #TRUE}, which preserves the input information, 270 * but may cause the transmitted archive to be larger than necessary. 271 */ 272 String KEEP_FILE_ORDER = "pack.keep.file.order"; 273 274 275 /** 276 * If this property is set to a single decimal digit, the packer will 277 * use the indicated amount of effort in compressing the archive. 278 * Level 1 may produce somewhat larger size and faster compression speed, 279 * while level 9 will take much longer but may produce better compression. 280 * <p> 281 * The special value 0 instructs the packer to copy through the 282 * original JAR file directly, with no compression. The JSR 200 283 * standard requires any unpacker to understand this special case 284 * as a pass-through of the entire archive. 285 * <p> 286 * The default is 5, investing a modest amount of time to 287 * produce reasonable compression. 288 */ 289 String EFFORT = "pack.effort"; 290 291 /** 292 * If this property is set to {@link #TRUE} or {@link #FALSE}, the packer 293 * will set the deflation hint accordingly in the output archive, and 294 * will not transmit the individual deflation hints of archive elements. 295 * <p> 296 * If this property is set to the special string {@link #KEEP}, the packer 297 * will attempt to determine an independent deflation hint for each 298 * available element of the input archive, and transmit this hint separately. 299 * <p> 300 * The default is {@link #KEEP}, which preserves the input information, 301 * but may cause the transmitted archive to be larger than necessary. 302 * <p> 303 * It is up to the unpacker implementation 304 * to take action upon the hint to suitably compress the elements of 305 * the resulting unpacked jar. 306 * <p> 307 * The deflation hint of a ZIP or JAR element indicates 308 * whether the element was deflated or stored directly. 309 */ 310 String DEFLATE_HINT = "pack.deflate.hint"; 311 312 /** 313 * If this property is set to the special string {@link #LATEST}, 314 * the packer will attempt to determine the latest modification time, 315 * among all the available entries in the original archive or the latest 316 * modification time of all the available entries in each segment. 317 * This single value will be transmitted as part of the segment and applied 318 * to all the entries in each segment, {@link #SEGMENT_LIMIT}. 319 * <p> 320 * This can marginally decrease the transmitted size of the 321 * archive, at the expense of setting all installed files to a single 322 * date. 323 * <p> 324 * If this property is set to the special string {@link #KEEP}, 325 * the packer transmits a separate modification time for each input 326 * element. 327 * <p> 328 * The default is {@link #KEEP}, which preserves the input information, 329 * but may cause the transmitted archive to be larger than necessary. 330 * <p> 331 * It is up to the unpacker implementation to take action to suitably 332 * set the modification time of each element of its output file. 333 * @see #SEGMENT_LIMIT 334 */ 335 String MODIFICATION_TIME = "pack.modification.time"; 336 337 /** 338 * Indicates that a file should be passed through bytewise, with no 339 * compression. Multiple files may be specified by specifying 340 * additional properties with distinct strings appended, to 341 * make a family of properties with the common prefix. 342 * <p> 343 * There is no pathname transformation, except 344 * that the system file separator is replaced by the JAR file 345 * separator '/'. 346 * <p> 347 * The resulting file names must match exactly as strings with their 348 * occurrences in the JAR file. 349 * <p> 350 * If a property value is a directory name, all files under that 351 * directory will be passed also. 352 * <p> 353 * Examples: 354 * <pre>{@code 355 * Map p = packer.properties(); 356 * p.put(PASS_FILE_PFX+0, "mutants/Rogue.class"); 357 * p.put(PASS_FILE_PFX+1, "mutants/Wolverine.class"); 358 * p.put(PASS_FILE_PFX+2, "mutants/Storm.class"); 359 * # Pass all files in an entire directory hierarchy: 360 * p.put(PASS_FILE_PFX+3, "police/"); 361 * }</pre> 362 */ 363 String PASS_FILE_PFX = "pack.pass.file."; 364 365 /// Attribute control. 366 367 /** 368 * Indicates the action to take when a class-file containing an unknown 369 * attribute is encountered. Possible values are the strings {@link #ERROR}, 370 * {@link #STRIP}, and {@link #PASS}. 371 * <p> 372 * The string {@link #ERROR} means that the pack operation 373 * as a whole will fail, with an exception of type {@code IOException}. 374 * The string 375 * {@link #STRIP} means that the attribute will be dropped. 376 * The string 377 * {@link #PASS} means that the whole class-file will be passed through 378 * (as if it were a resource file) without compression, with a suitable warning. 379 * This is the default value for this property. 380 * <p> 381 * Examples: 382 * <pre>{@code 383 * Map p = pack200.getProperties(); 384 * p.put(UNKNOWN_ATTRIBUTE, ERROR); 385 * p.put(UNKNOWN_ATTRIBUTE, STRIP); 386 * p.put(UNKNOWN_ATTRIBUTE, PASS); 387 * }</pre> 388 */ 389 String UNKNOWN_ATTRIBUTE = "pack.unknown.attribute"; 390 391 /** 392 * When concatenated with a class attribute name, 393 * indicates the format of that attribute, 394 * using the layout language specified in the JSR 200 specification. 395 * <p> 396 * For example, the effect of this option is built in: 397 * {@code pack.class.attribute.SourceFile=RUH}. 398 * <p> 399 * The special strings {@link #ERROR}, {@link #STRIP}, and {@link #PASS} are 400 * also allowed, with the same meaning as {@link #UNKNOWN_ATTRIBUTE}. 401 * This provides a way for users to request that specific attributes be 402 * refused, stripped, or passed bitwise (with no class compression). 403 * <p> 404 * Code like this might be used to support attributes for JCOV: 405 * <pre>{@code 406 * Map p = packer.properties(); 407 * p.put(CODE_ATTRIBUTE_PFX+"CoverageTable", "NH[PHHII]"); 408 * p.put(CODE_ATTRIBUTE_PFX+"CharacterRangeTable", "NH[PHPOHIIH]"); 409 * p.put(CLASS_ATTRIBUTE_PFX+"SourceID", "RUH"); 410 * p.put(CLASS_ATTRIBUTE_PFX+"CompilationID", "RUH"); 411 * }</pre> 412 * <p> 413 * Code like this might be used to strip debugging attributes: 414 * <pre>{@code 415 * Map p = packer.properties(); 416 * p.put(CODE_ATTRIBUTE_PFX+"LineNumberTable", STRIP); 417 * p.put(CODE_ATTRIBUTE_PFX+"LocalVariableTable", STRIP); 418 * p.put(CLASS_ATTRIBUTE_PFX+"SourceFile", STRIP); 419 * }</pre> 420 */ 421 String CLASS_ATTRIBUTE_PFX = "pack.class.attribute."; 422 423 /** 424 * When concatenated with a field attribute name, 425 * indicates the format of that attribute. 426 * For example, the effect of this option is built in: 427 * {@code pack.field.attribute.Deprecated=}. 428 * The special strings {@link #ERROR}, {@link #STRIP}, and 429 * {@link #PASS} are also allowed. 430 * @see #CLASS_ATTRIBUTE_PFX 431 */ 432 String FIELD_ATTRIBUTE_PFX = "pack.field.attribute."; 433 434 /** 435 * When concatenated with a method attribute name, 436 * indicates the format of that attribute. 437 * For example, the effect of this option is built in: 438 * {@code pack.method.attribute.Exceptions=NH[RCH]}. 439 * The special strings {@link #ERROR}, {@link #STRIP}, and {@link #PASS} 440 * are also allowed. 441 * @see #CLASS_ATTRIBUTE_PFX 442 */ 443 String METHOD_ATTRIBUTE_PFX = "pack.method.attribute."; 444 445 /** 446 * When concatenated with a code attribute name, 447 * indicates the format of that attribute. 448 * For example, the effect of this option is built in: 449 * {@code pack.code.attribute.LocalVariableTable=NH[PHOHRUHRSHH]}. 450 * The special strings {@link #ERROR}, {@link #STRIP}, and {@link #PASS} 451 * are also allowed. 452 * @see #CLASS_ATTRIBUTE_PFX 453 */ 454 String CODE_ATTRIBUTE_PFX = "pack.code.attribute."; 455 456 /** 457 * The packer's progress as a percentage, as periodically 458 * updated by the packer. 459 * Values of 0 - 100 are normal, and -1 indicates a stall. 460 * Progress can be monitored by polling the value of this 461 * property. 462 * <p> 463 * At a minimum, the packer must set progress to 0 464 * at the beginning of a packing operation, and to 100 465 * at the end. 466 */ 467 String PROGRESS = "pack.progress"; 468 469 /** The string "keep", a possible value for certain properties. 470 * @see #DEFLATE_HINT 471 * @see #MODIFICATION_TIME 472 */ 473 String KEEP = "keep"; 474 475 /** The string "pass", a possible value for certain properties. 476 * @see #UNKNOWN_ATTRIBUTE 477 * @see #CLASS_ATTRIBUTE_PFX 478 * @see #FIELD_ATTRIBUTE_PFX 479 * @see #METHOD_ATTRIBUTE_PFX 480 * @see #CODE_ATTRIBUTE_PFX 481 */ 482 String PASS = "pass"; 483 484 /** The string "strip", a possible value for certain properties. 485 * @see #UNKNOWN_ATTRIBUTE 486 * @see #CLASS_ATTRIBUTE_PFX 487 * @see #FIELD_ATTRIBUTE_PFX 488 * @see #METHOD_ATTRIBUTE_PFX 489 * @see #CODE_ATTRIBUTE_PFX 490 */ 491 String STRIP = "strip"; 492 493 /** The string "error", a possible value for certain properties. 494 * @see #UNKNOWN_ATTRIBUTE 495 * @see #CLASS_ATTRIBUTE_PFX 496 * @see #FIELD_ATTRIBUTE_PFX 497 * @see #METHOD_ATTRIBUTE_PFX 498 * @see #CODE_ATTRIBUTE_PFX 499 */ 500 String ERROR = "error"; 501 502 /** The string "true", a possible value for certain properties. 503 * @see #KEEP_FILE_ORDER 504 * @see #DEFLATE_HINT 505 */ 506 String TRUE = "true"; 507 508 /** The string "false", a possible value for certain properties. 509 * @see #KEEP_FILE_ORDER 510 * @see #DEFLATE_HINT 511 */ 512 String FALSE = "false"; 513 514 /** The string "latest", a possible value for certain properties. 515 * @see #MODIFICATION_TIME 516 */ 517 String LATEST = "latest"; 518 519 /** 520 * Get the set of this engine's properties. 521 * This set is a "live view", so that changing its 522 * contents immediately affects the Packer engine, and 523 * changes from the engine (such as progress indications) 524 * are immediately visible in the map. 525 * 526 * <p>The property map may contain pre-defined implementation 527 * specific and default properties. Users are encouraged to 528 * read the information and fully understand the implications, 529 * before modifying pre-existing properties. 530 * <p> 531 * Implementation specific properties are prefixed with a 532 * package name associated with the implementor, beginning 533 * with {@code com.} or a similar prefix. 534 * All property names beginning with {@code pack.} and 535 * {@code unpack.} are reserved for use by this API. 536 * <p> 537 * Unknown properties may be ignored or rejected with an 538 * unspecified error, and invalid entries may cause an 539 * unspecified error to be thrown. 540 * 541 * <p> 542 * The returned map implements all optional {@link SortedMap} operations 543 * @return A sorted association of property key strings to property 544 * values. 545 */ 546 SortedMap<String,String> properties(); 547 548 /** 549 * Takes a JarFile and converts it into a Pack200 archive. 550 * <p> 551 * Closes its input but not its output. (Pack200 archives are appendable.) 552 * @param in a JarFile 553 * @param out an OutputStream 554 * @exception IOException if an error is encountered. 555 */ 556 void pack(JarFile in, OutputStream out) throws IOException ; 557 558 /** 559 * Takes a JarInputStream and converts it into a Pack200 archive. 560 * <p> 561 * Closes its input but not its output. (Pack200 archives are appendable.) 562 * <p> 563 * The modification time and deflation hint attributes are not available, 564 * for the JAR manifest file and its containing directory. 565 * 566 * @see #MODIFICATION_TIME 567 * @see #DEFLATE_HINT 568 * @param in a JarInputStream 569 * @param out an OutputStream 570 * @exception IOException if an error is encountered. 571 */ 572 void pack(JarInputStream in, OutputStream out) throws IOException ; 573 } 574 575 /** 576 * The unpacker engine converts the packed stream to a JAR file. 577 * An instance of the engine can be obtained 578 * using {@link #newUnpacker}. 579 * <p> 580 * Every JAR file produced by this engine will include the string 581 * "{@code PACK200}" as a zip file comment. 582 * This allows a deployer to detect if a JAR archive was packed and unpacked. 583 * <p> 584 * Note: Unless otherwise noted, passing a {@code null} argument to a 585 * constructor or method in this class will cause a {@link NullPointerException} 586 * to be thrown. 587 * <p> 588 * This version of the unpacker is compatible with all previous versions. 589 * @since 1.5 590 */ 591 @Deprecated(since="11", forRemoval=true) 592 public interface Unpacker { 593 594 /** The string "keep", a possible value for certain properties. 595 * @see #DEFLATE_HINT 596 */ 597 String KEEP = "keep"; 598 599 /** The string "true", a possible value for certain properties. 600 * @see #DEFLATE_HINT 601 */ 602 String TRUE = "true"; 603 604 /** The string "false", a possible value for certain properties. 605 * @see #DEFLATE_HINT 606 */ 607 String FALSE = "false"; 608 609 /** 610 * Property indicating that the unpacker should 611 * ignore all transmitted values for DEFLATE_HINT, 612 * replacing them by the given value, {@link #TRUE} or {@link #FALSE}. 613 * The default value is the special string {@link #KEEP}, 614 * which asks the unpacker to preserve all transmitted 615 * deflation hints. 616 */ 617 String DEFLATE_HINT = "unpack.deflate.hint"; 618 619 620 621 /** 622 * The unpacker's progress as a percentage, as periodically 623 * updated by the unpacker. 624 * Values of 0 - 100 are normal, and -1 indicates a stall. 625 * Progress can be monitored by polling the value of this 626 * property. 627 * <p> 628 * At a minimum, the unpacker must set progress to 0 629 * at the beginning of an unpacking operation, and to 100 630 * at the end. 631 */ 632 String PROGRESS = "unpack.progress"; 633 634 /** 635 * Get the set of this engine's properties. This set is 636 * a "live view", so that changing its 637 * contents immediately affects the Unpacker engine, and 638 * changes from the engine (such as progress indications) 639 * are immediately visible in the map. 640 * 641 * <p>The property map may contain pre-defined implementation 642 * specific and default properties. Users are encouraged to 643 * read the information and fully understand the implications, 644 * before modifying pre-existing properties. 645 * <p> 646 * Implementation specific properties are prefixed with a 647 * package name associated with the implementor, beginning 648 * with {@code com.} or a similar prefix. 649 * All property names beginning with {@code pack.} and 650 * {@code unpack.} are reserved for use by this API. 651 * <p> 652 * Unknown properties may be ignored or rejected with an 653 * unspecified error, and invalid entries may cause an 654 * unspecified error to be thrown. 655 * 656 * @return A sorted association of option key strings to option values. 657 */ 658 SortedMap<String,String> properties(); 659 660 /** 661 * Read a Pack200 archive, and write the encoded JAR to 662 * a JarOutputStream. 663 * The entire contents of the input stream will be read. 664 * It may be more efficient to read the Pack200 archive 665 * to a file and pass the File object, using the alternate 666 * method described below. 667 * <p> 668 * Closes its input but not its output. (The output can accumulate more elements.) 669 * @param in an InputStream. 670 * @param out a JarOutputStream. 671 * @exception IOException if an error is encountered. 672 */ 673 void unpack(InputStream in, JarOutputStream out) throws IOException; 674 675 /** 676 * Read a Pack200 archive, and write the encoded JAR to 677 * a JarOutputStream. 678 * <p> 679 * Does not close its output. (The output can accumulate more elements.) 680 * @param in a File. 681 * @param out a JarOutputStream. 682 * @exception IOException if an error is encountered. 683 */ 684 void unpack(File in, JarOutputStream out) throws IOException; 685 } 686 687 // Private stuff.... 688 689 private static final String PACK_PROVIDER = "java.util.jar.Pack200.Packer"; 690 private static final String UNPACK_PROVIDER = "java.util.jar.Pack200.Unpacker"; 691 692 private static Class<?> packerImpl; 693 private static Class<?> unpackerImpl; 694 695 private static synchronized Object newInstance(String prop) { 696 String implName = "(unknown)"; 697 try { 698 Class<?> impl = (PACK_PROVIDER.equals(prop))? packerImpl: unpackerImpl; 699 if (impl == null) { 700 // The first time, we must decide which class to use. 701 implName = GetPropertyAction.privilegedGetProperty(prop,""); 702 if (implName != null && !implName.equals("")) 703 impl = Class.forName(implName); 704 else if (PACK_PROVIDER.equals(prop)) 705 impl = com.sun.java.util.jar.pack.PackerImpl.class; 706 else 707 impl = com.sun.java.util.jar.pack.UnpackerImpl.class; 708 } 709 // We have a class. Now instantiate it. 710 @SuppressWarnings("deprecation") 711 Object result = impl.newInstance(); 712 return result; 713 } catch (ClassNotFoundException e) { 714 throw new Error("Class not found: " + implName + 715 ":\ncheck property " + prop + 716 " in your properties file.", e); 717 } catch (InstantiationException e) { 718 throw new Error("Could not instantiate: " + implName + 719 ":\ncheck property " + prop + 720 " in your properties file.", e); 721 } catch (IllegalAccessException e) { 722 throw new Error("Cannot access class: " + implName + 723 ":\ncheck property " + prop + 724 " in your properties file.", e); 725 } 726 } 727 728 }