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