KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > util > jar > Pack200


1 /*
2  * @(#)Pack200.java 1.4 03/12/08
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 package java.util.jar;
8
9 import java.util.SortedMap JavaDoc;
10 import java.io.InputStream JavaDoc;
11 import java.io.OutputStream JavaDoc;
12 import java.io.File JavaDoc;
13 import java.io.IOException JavaDoc;
14 import java.beans.PropertyChangeListener JavaDoc;
15 import java.beans.PropertyChangeEvent JavaDoc;
16 import java.security.AccessController JavaDoc;
17 import java.security.PrivilegedAction JavaDoc;
18
19
20
21
22 /**
23  * Transforms a JAR file to or from a packed stream in Pack200 format.
24  * Please refer to Network Trasfer Format JSR 200 Specification at
25  * http://jcp.org/aboutJava/communityprocess/review/jsr200/index.html
26  * <p>
27  * Typically the packer engine is used by application developers
28  * to deploy or host JAR files on a website.
29  * The unpacker engine is used by deployment applications to
30  * transform the byte-stream back to JAR format.
31  * <p>
32  * Here is an example using packer and unpacker:<p>
33  * <blockquote><pre>
34  * import java.util.jar.Pack200;
35  * import java.util.jar.Pack200.*;
36  * ...
37  * // Create the Packer object
38  * Packer packer = Pack200.newPacker();
39  *
40  * // Initialize the state by setting the desired properties
41  * Map p = packer.properties();
42  * // take more time choosing codings for better compression
43  * p.put(Packer.EFFORT, "7"); // default is "5"
44  * // use largest-possible archive segments (>10% better compression).
45  * p.put(Packer.SEGMENT_LIMIT, "-1");
46  * // reorder files for better compression.
47  * p.put(Packer.KEEP_FILE_ORDER, Packer.FALSE);
48  * // smear modification times to a single value.
49  * p.put(Packer.MODIFICATION_TIME, Packer.LATEST);
50  * // ignore all JAR deflation requests,
51  * // transmitting a single request to use "store" mode.
52  * p.put(Packer.DEFLATE_HINT, Packer.FALSE);
53  * // discard debug attributes
54  * p.put(Packer.CODE_ATTRIBUTE_PFX+"LineNumberTable", Packer.STRIP);
55  * // throw an error if an attribute is unrecognized
56  * p.put(Packer.UNKNOWN_ATTRIBUTE, Packer.ERROR);
57  * // pass one class file uncompressed:
58  * p.put(Packer.PASS_FILE_PFX+0, "mutants/Rogue.class");
59  * try {
60  * JarFile jarFile = new JarFile("/tmp/testref.jar");
61  * FileOutputStream fos = new FileOutputStream("/tmp/test.pack");
62  * // Call the packer
63  * packer.pack(jarFile, fos);
64  * jarFile.close();
65  * fos.close();
66  *
67  * File f = new File("/tmp/test.pack");
68  * FileOutputStream fostream = new FileOutputStream("/tmp/test.jar");
69  * JarOutputStream jostream = new JarOutputStream(fostream);
70  * Unpacker unpacker = Pack200.newUnpacker();
71  * // Call the unpacker
72  * unpacker.unpack(f, jostream);
73  * // Must explicitly close the output.
74  * jostream.close();
75  * } catch (IOException ioe) {
76  * ioe.printStackTrace();
77  * }
78  * </pre></blockquote>
79  * <p>
80  * A Pack200 file compressed with gzip can be hosted on HTTP/1.1 web servers.
81  * The deployment applications can use "Accept-Encoding=pack200-gzip". This
82  * indicates to the server that the client application desires a version of
83  * the file encoded with Pack200 and further compressed with gzip. Please
84  * refer to Java Deployment Guide <TBD> for more details and techniques.
85  * <p>
86  * Unless otherwise noted, passing a <tt>null</tt> argument to a constructor or
87  * method in this class will cause a {@link NullPointerException} to be thrown.
88  *
89  * @author John Rose
90  * @author Kumar Srinivasan
91  * @version 1.4, 12/08/03
92  * @since 1.5
93  */

94 public abstract class Pack200 {
95     private Pack200() {} //prevent instantiation
96

97     // Static methods of the Pack200 class.
98
/**
99      * Obtain new instance of a class that implements Packer.
100      *
101      * <li><p>If the system property <tt>java.util.jar.Pack200.Packer</tt>
102      * is defined, then the value is taken to be the fully-qualified name
103      * of a concrete implementation class, which must implement Packer.
104      * This class is loaded and instantiated. If this process fails
105      * then an unspecified error is thrown.</p></li>
106      *
107      * <li><p>If an implementation has not been specified with the system
108      * property, then the system-default implementation class is instantiated,
109      * and the result is returned.</p></li>
110      *
111      * <p>Note: The returned object is not guaranteed to operate
112      * correctly if multiple threads use it at the same time.
113      * A multi-threaded application should either allocate multiple
114      * packer engines, or else serialize use of one engine with a lock.
115      *
116      * @return A newly allocated Packer engine.
117      */

118     public synchronized static Packer newPacker() {
119     return (Packer) newInstance(PACK_PROVIDER);
120     }
121
122
123     /**
124      * Obtain new instance of a class that implements Unpacker.
125      *
126      * <li><p>If the system property <tt>java.util.jar.Pack200.Unpacker</tt>
127      * is defined, then the value is taken to be the fully-qualified
128      * name of a concrete implementation class, which must implement Unpacker.
129      * The class is loaded and instantiated. If this process fails
130      * then an unspecified error is thrown.</p></li>
131      *
132      * <li><p>If an implementation has not been specified with the
133      * system property, then the system-default implementation class
134      * is instantiated, and the result is returned.</p></li>
135      *
136      * <p>Note: The returned object is not guaranteed to operate
137      * correctly if multiple threads use it at the same time.
138      * A multi-threaded application should either allocate multiple
139      * unpacker engines, or else serialize use of one engine with a lock.
140      *
141      * @return A newly allocated Unpacker engine.
142      */

143
144     public static Unpacker newUnpacker() {
145     return (Unpacker) newInstance(UNPACK_PROVIDER);
146     }
147
148     // Interfaces
149
/**
150      * The packer engine applies various transformations to the input JAR file,
151      * making the pack stream highly compressible by a compressor such as
152      * gzip or zip. An instance of the engine can be obtained
153      * using {@link #newPacker}.
154
155      * The high degree of compression is achieved
156      * by using a number of techniques described in the JSR 200 specification.
157      * Some of the techniques are sorting, re-ordering and co-location of the
158      * constant pool.
159      * <p>
160      * The pack engine is initialized to an initial state as described
161      * by their properties below.
162      * The initial state can be manipulated by getting the
163      * engine properties (using {@link #properties}) and storing
164      * the modified properties on the map.
165      * The resource files will be passed through with no changes at all.
166      * The class files will not contain identical bytes, since the unpacker
167      * is free to change minor class file features such as constant pool order.
168      * However, the class files will be semantically identical,
169      * as specified in the Java Virtual Machine Specification
170      * <a HREF="http://java.sun.com/docs/books/vmspec/html/ClassFile.doc.html">http://java.sun.com/docs/books/vmspec/html/ClassFile.doc.html</a>.
171      * <p>
172      * By default, the packer does not change the order of JAR elements.
173      * Also, the modification time and deflation hint of each
174      * JAR element is passed unchanged.
175      * (Any other ZIP-archive information, such as extra attributes
176      * giving Unix file permissions, are lost.)
177      * <p>
178      * Note that packing and unpacking a JAR will in general alter the
179      * bytewise contents of classfiles in the JAR. This means that packing
180      * and unpacking will in general invalidate any digital signatures
181      * which rely on bytewise images of JAR elements. In order both to sign
182      * and to pack a JAR, you must first pack and unpack the JAR to
183      * "normalize" it, then compute signatures on the unpacked JAR elements,
184      * and finally repack the signed JAR.
185      * Both packing steps should
186      * use precisely the same options, and the segment limit may also
187      * need to be set to "-1", to prevent accidental variation of segment
188      * boundaries as class file sizes change slightly.
189      * <p>
190      * (Here's why this works: Any reordering the packer does
191      * of any classfile structures is idempotent, so the second packing
192      * does not change the orderings produced by the first packing.
193      * Also, the unpacker is guaranteed by the JSR 200 specification
194      * to produce a specific bytewise image for any given transmission
195      * ordering of archive elements.)
196      */

197     public interface Packer {
198     /**
199      * This property is a numeral giving the estimated target size N
200      * (in bytes) of each archive segment.
201      * If a single input file requires more than N bytes,
202      * it will be given its own archive segment.
203      * <p>
204      * As a special case, a value of -1 will produce a single large
205      * segment with all input files, while a value of 0 will
206      * produce one segment for each class.
207      * Larger archive segments result in less fragmentation and
208      * better compression, but processing them requires more memory.
209      * <p>
210      * The size of each segment is estimated by counting the size of each
211      * input file to be transmitted in the segment, along with the size
212      * of its name and other transmitted properties.
213      * <p>
214      * The default is 1000000 (a million bytes). This allows input JAR files
215      * of moderate size to be transmitted in one segment. It also puts
216      * a limit on memory requirements for packers and unpackers.
217      * <p>
218      * A 10Mb JAR packed without this limit will
219      * typically pack about 10% smaller, but the packer may require
220      * a larger Java heap (about ten times the segment limit).
221      */

222     String JavaDoc SEGMENT_LIMIT = "pack.segment.limit";
223
224     /**
225      * If this property is set to {@link #TRUE}, the packer will transmit
226      * all elements in their original order within the source archive.
227      * <p>
228      * If it is set to {@link #FALSE}, the packer may reorder elements,
229      * and also remove JAR directory entries, which carry no useful
230      * information for Java applications.
231      * (Typically this enables better compression.)
232      * <p>
233      * The default is {@link #TRUE}, which preserves the input information,
234      * but may cause the transmitted archive to be larger than necessary.
235      */

236     String JavaDoc KEEP_FILE_ORDER = "pack.keep.file.order";
237
238
239     /**
240      * If this property is set to a single decimal digit, the packer will
241      * use the indicated amount of effort in compressing the archive.
242      * Level 1 may produce somewhat larger size and faster compression speed,
243      * while level 9 will take much longer but may produce better compression.
244      * <p>
245      * The special value 0 instructs the packer to copy through the
246      * original JAR file directly, with no compression. The JSR 200
247      * standard requires any unpacker to understand this special case
248      * as a pass-through of the entire archive.
249      * <p>
250      * The default is 5, investing a modest amount of time to
251      * produce reasonable compression.
252      */

253     String JavaDoc EFFORT = "pack.effort";
254
255     /**
256      * If this property is set to {@link #TRUE} or {@link #FALSE}, the packer
257      * will set the deflation hint accordingly in the output archive, and
258      * will not transmit the individual deflation hints of archive elements.
259      * <p>
260      * If this property is set to the special string {@link #KEEP}, the packer
261      * will attempt to determine an independent deflation hint for each
262      * available element of the input archive, and transmit this hint separately.
263      * <p>
264      * The default is {@link #KEEP}, which preserves the input information,
265      * but may cause the transmitted archive to be larger than necessary.
266      * <p>
267      * It is up to the unpacker implementation
268      * to take action upon the hint to suitably compress the elements of
269      * the resulting unpacked jar.
270      * <p>
271      * The deflation hint of a ZIP or JAR element indicates
272      * whether the element was deflated or stored directly.
273      */

274     String JavaDoc DEFLATE_HINT = "pack.deflate.hint";
275
276     /**
277      * If this property is set to the special string {@link #LATEST},
278      * the packer will attempt to determine the latest modification time,
279      * among all the available entries in the original archive or the latest
280      * modification time of all the available entries in each segment.
281      * This single value will be transmitted as part of the segment and applied
282      * to all the entries in each segment, {@link #SEGMENT_LIMIT}.
283      * <p>
284      * This can marginally decrease the transmitted size of the
285      * archive, at the expense of setting all installed files to a single
286      * date.
287      * <p>
288      * If this property is set to the special string {@link #KEEP},
289      * the packer transmits a separate modification time for each input
290      * element.
291      * <p>
292      * The default is {@link #KEEP}, which preserves the input information,
293      * but may cause the transmitted archive to be larger than necessary.
294      * <p>
295      * It is up to the unpacker implementation to take action to suitably
296      * set the modification time of each element of its output file.
297      * @see #SEGMENT_LIMIT
298      */

299     String JavaDoc MODIFICATION_TIME = "pack.modification.time";
300
301     /**
302      * Indicates that a file should be passed through bytewise, with no
303      * compression. Multiple files may be specified by specifying
304      * additional properties with distinct strings appended, to
305      * make a family of properties with the common prefix.
306      * <p>
307      * There is no pathname transformation, except
308      * that the system file separator is replaced by the JAR file
309      * separator '/'.
310      * <p>
311      * The resulting file names must match exactly as strings with their
312      * occurrences in the JAR file.
313      * <p>
314      * If a property value is a directory name, all files under that
315      * directory will be passed also.
316      * <p>
317      * Examples:
318      * <pre><code>
319      * Map p = packer.properties();
320      * p.put(PASS_FILE_PFX+0, "mutants/Rogue.class");
321      * p.put(PASS_FILE_PFX+1, "mutants/Wolverine.class");
322      * p.put(PASS_FILE_PFX+2, "mutants/Storm.class");
323      * # Pass all files in an entire directory hierarchy:
324      * p.put(PASS_FILE_PFX+3, "police/");
325      * </pre></code>.
326      */

327     String JavaDoc PASS_FILE_PFX = "pack.pass.file.";
328
329     /// Attribute control.
330

331     /**
332      * Indicates the action to take when a class-file containing an unknown
333      * attribute is encountered. Possible values are the strings {@link #ERROR},
334      * {@link #STRIP}, and {@link #PASS}.
335      * <p>
336      * The string {@link #ERROR} means that the pack operation
337      * as a whole will fail, with a suitable explanation.
338      * The string
339      * {@link #STRIP} means that the attribute will be dropped.
340      * The string
341      * {@link #PASS} means that the whole class-file will be passed through
342      * (as if it were a resource file) without compression, with a suitable warning.
343      * This is the default value for this property.
344      * <p>
345      * Examples:
346      * <pre><code>
347      * Map p = pack200.getProperties();
348      * p.put(UNKNOWN_ATTRIBUTE, ERROR);
349      * p.put(UNKNOWN_ATTRIBUTE, STRIP);
350      * p.put(UNKNOWN_ATTRIBUTE, PASS);
351      * </pre></code>
352      */

353     String JavaDoc UNKNOWN_ATTRIBUTE = "pack.unknown.attribute";
354
355     /**
356      * When concatenated with a class attribute name,
357      * indicates the format of that attribute,
358      * using the layout language specified in the JSR 200 specification.
359      * <p>
360      * For example, the effect of this option is built in:
361      * <code>pack.class.attribute.SourceFile=RUH</code>.
362      * <p>
363      * The special strings {@link #ERROR}, {@link #STRIP}, and {@link #PASS} are
364      * also allowed, with the same meaning as {@link #UNKNOWN_ATTRIBUTE}.
365      * This provides a way for users to request that specific attributes be
366      * refused, stripped, or passed bitwise (with no class compression).
367      * <p>
368      * Code like this might be used to support attributes for JCOV:
369      * <pre><code>
370      * Map p = packer.properties();
371      * p.put(CODE_ATTRIBUTE_PFX+"CoverageTable", "NH[PHHII]");
372      * p.put(CODE_ATTRIBUTE_PFX+"CharacterRangeTable", "NH[PHPOHIIH]");
373      * p.put(CLASS_ATTRIBUTE_PFX+"SourceID", "RUH");
374      * p.put(CLASS_ATTRIBUTE_PFX+"CompilationID", "RUH");
375      * </code></pre>
376      * <p>
377      * Code like this might be used to strip debugging attributes:
378      * <pre><code>
379      * Map p = packer.properties();
380      * p.put(CODE_ATTRIBUTE_PFX+"LineNumberTable", STRIP);
381      * p.put(CODE_ATTRIBUTE_PFX+"LocalVariableTable", STRIP);
382      * p.put(CLASS_ATTRIBUTE_PFX+"SourceFile", STRIP);
383      * </code></pre>
384      */

385     String JavaDoc CLASS_ATTRIBUTE_PFX = "pack.class.attribute.";
386
387     /**
388      * When concatenated with a field attribute name,
389      * indicates the format of that attribute.
390      * For example, the effect of this option is built in:
391      * <code>pack.field.attribute.Deprecated=</code>.
392      * The special strings {@link #ERROR}, {@link #STRIP}, and
393      * {@link #PASS} are also allowed.
394      * @see #CLASS_ATTRIBUTE_PFX
395      */

396     String JavaDoc FIELD_ATTRIBUTE_PFX = "pack.field.attribute.";
397
398     /**
399      * When concatenated with a method attribute name,
400      * indicates the format of that attribute.
401      * For example, the effect of this option is built in:
402      * <code>pack.method.attribute.Exceptions=NH[RCH]</code>.
403      * The special strings {@link #ERROR}, {@link #STRIP}, and {@link #PASS}
404      * are also allowed.
405      * @see #CLASS_ATTRIBUTE_PFX
406      */

407     String JavaDoc METHOD_ATTRIBUTE_PFX = "pack.method.attribute.";
408
409     /**
410      * When concatenated with a code attribute name,
411      * indicates the format of that attribute.
412      * For example, the effect of this option is built in:
413      * <code>pack.code.attribute.LocalVariableTable=NH[PHOHRUHRSHH]</code>.
414      * The special strings {@link #ERROR}, {@link #STRIP}, and {@link #PASS}
415      * are also allowed.
416      * @see #CLASS_ATTRIBUTE_PFX
417      */

418     String JavaDoc CODE_ATTRIBUTE_PFX = "pack.code.attribute.";
419
420     /**
421      * The unpacker's progress as a percentage, as periodically
422      * updated by the unpacker.
423      * Values of 0 - 100 are normal, and -1 indicates a stall.
424      * Observe this property with a {@link PropertyChangeListener}.
425      * <p>
426      * At a minimum, the unpacker must set progress to 0
427      * at the beginning of a packing operation, and to 100
428      * at the end.
429      * @see #addPropertyChangeListener
430      */

431     String JavaDoc PROGRESS = "pack.progress";
432
433     /** The string "keep", a possible value for certain properties.
434      * @see #DEFLATE_HINT
435      * @see #MODIFICATION_TIME
436      */

437     String JavaDoc KEEP = "keep";
438
439     /** The string "pass", a possible value for certain properties.
440      * @see #UNKNOWN_ATTRIBUTE
441      * @see #CLASS_ATTRIBUTE_PFX
442      * @see #FIELD_ATTRIBUTE_PFX
443      * @see #METHOD_ATTRIBUTE_PFX
444      * @see #CODE_ATTRIBUTE_PFX
445      */

446     String JavaDoc PASS = "pass";
447
448     /** The string "strip", a possible value for certain properties.
449      * @see #UNKNOWN_ATTRIBUTE
450      * @see #CLASS_ATTRIBUTE_PFX
451      * @see #FIELD_ATTRIBUTE_PFX
452      * @see #METHOD_ATTRIBUTE_PFX
453      * @see #CODE_ATTRIBUTE_PFX
454      */

455     String JavaDoc STRIP = "strip";
456
457     /** The string "error", a possible value for certain properties.
458      * @see #UNKNOWN_ATTRIBUTE
459      * @see #CLASS_ATTRIBUTE_PFX
460      * @see #FIELD_ATTRIBUTE_PFX
461      * @see #METHOD_ATTRIBUTE_PFX
462      * @see #CODE_ATTRIBUTE_PFX
463      */

464     String JavaDoc ERROR = "error";
465
466     /** The string "true", a possible value for certain properties.
467      * @see #KEEP_FILE_ORDER
468      * @see #DEFLATE_HINT
469      */

470     String JavaDoc TRUE = "true";
471
472     /** The string "false", a possible value for certain properties.
473      * @see #KEEP_FILE_ORDER
474      * @see #DEFLATE_HINT
475      */

476     String JavaDoc FALSE = "false";
477
478     /** The string "latest", a possible value for certain properties.
479      * @see #MODIFICATION_TIME
480      */

481     String JavaDoc LATEST = "latest";
482
483     /**
484      * Get the set of this engine's properties.
485      * This set is a "live view", so that changing its
486      * contents immediately affects the Packer engine, and
487      * changes from the engine (such as progress indications)
488      * are immediately visible in the map.
489      *
490      * <p>The property map may contain pre-defined implementation
491      * specific and default properties. Users are encouraged to
492      * read the information and fully understand the implications,
493      * before modifying pre-existing properties.
494      * <p>
495      * Implementation specific properties are prefixed with a
496      * package name associated with the implementor, beginning
497      * with <tt>com.</tt> or a similar prefix.
498      * All property names beginning with <tt>pack.</tt> and
499      * <tt>unpack.</tt> are reserved for use by this API.
500      * <p>
501      * Unknown properties may be ignored or rejected with an
502      * unspecified error, and invalid entries may cause an
503      * unspecified error to be thrown.
504          *
505      * <p>
506      * The returned map implements all optional {@link SortedMap} operations
507      * @return A sorted association of property key strings to property
508          * values.
509      */

510     SortedMap JavaDoc<String JavaDoc,String JavaDoc> properties();
511
512     /**
513      * Takes a JarFile and converts it into a Pack200 archive.
514      * <p>
515      * Closes its input but not its output. (Pack200 archives are appendable.)
516      * @param in a JarFile
517      * @param out an OutputStream
518      * @exception IOException if an error is encountered.
519      */

520     void pack(JarFile JavaDoc in, OutputStream JavaDoc out) throws IOException JavaDoc ;
521
522     /**
523      * Takes a JarInputStream and converts it into a Pack200 archive.
524      * <p>
525      * Closes its input but not its output. (Pack200 archives are appendable.)
526      * <p>
527      * The modification time and deflation hint attributes are not available,
528      * for the JAR manifest file and its containing directory.
529      *
530      * @see #MODIFICATION_TIME
531      * @see #DEFLATE_HINT
532      * @param in a JarInputStream
533      * @param out an OutputStream
534      * @exception IOException if an error is encountered.
535      */

536     void pack(JarInputStream JavaDoc in, OutputStream JavaDoc out) throws IOException JavaDoc ;
537
538     /**
539      * Registers a listener for PropertyChange events on the properties map.
540      * This is typically used by applications to update a progress bar.
541      *
542      * @see #properties
543      * @see #PROGRESS
544      * @param listener An object to be invoked when a property is changed.
545      */

546     void addPropertyChangeListener(PropertyChangeListener JavaDoc listener) ;
547
548     /**
549      * Remove a listener for PropertyChange events, added by
550      * the {@link #addPropertyChangeListener}.
551      *
552      * @see #addPropertyChangeListener
553      * @param listener The PropertyChange listener to be removed.
554      */

555     void removePropertyChangeListener(PropertyChangeListener JavaDoc listener);
556
557     }
558
559     /**
560      * The unpacker engine converts the packed stream to a JAR file.
561      * An instance of the engine can be obtained
562      * using {@link #newUnpacker}.
563      * <p>
564      * Every JAR file produced by this engine will include the string
565      * "<tt>PACK200</tt>" as a zip file comment.
566      * This allows a deployer to detect if a JAR archive was packed and unpacked.
567      * <p>
568      */

569     public interface Unpacker {
570
571     /** The string "keep", a possible value for certain properties.
572      * @see #DEFLATE_HINT
573      */

574     String JavaDoc KEEP = "keep";
575
576     /** The string "true", a possible value for certain properties.
577      * @see #DEFLATE_HINT
578      */

579     String JavaDoc TRUE = "true";
580
581     /** The string "false", a possible value for certain properties.
582      * @see #DEFLATE_HINT
583      */

584     String JavaDoc FALSE = "false";
585
586     /**
587      * Property indicating that the unpacker should
588      * ignore all transmitted values for DEFLATE_HINT,
589      * replacing them by the given value, {@link #TRUE} or {@link #FALSE}.
590      * The default value is the special string {@link #KEEP},
591      * which asks the unpacker to preserve all transmitted
592      * deflation hints.
593      */

594     String JavaDoc DEFLATE_HINT = "unpack.deflate.hint";
595
596
597
598     /**
599      * The unpacker's progress as a percentage, as periodically
600      * updated by the unpacker.
601      * Values of 0 - 100 are normal, and -1 indicates a stall.
602      * Observe this property with a {@link PropertyChangeListener}.
603      * <p>
604      * At a minimum, the unpacker must set progress to 0
605      * at the beginning of a packing operation, and to 100
606      * at the end.
607      * @see #addPropertyChangeListener
608      */

609     String JavaDoc PROGRESS = "unpack.progress";
610
611     /**
612      * Get the set of this engine's properties. This set is
613      * a "live view", so that changing its
614      * contents immediately affects the Packer engine, and
615      * changes from the engine (such as progress indications)
616      * are immediately visible in the map.
617      *
618      * <p>The property map may contain pre-defined implementation
619      * specific and default properties. Users are encouraged to
620      * read the information and fully understand the implications,
621      * before modifying pre-existing properties.
622      * <p>
623      * Implementation specific properties are prefixed with a
624      * package name associated with the implementor, beginning
625      * with <tt>com.</tt> or a similar prefix.
626      * All property names beginning with <tt>pack.</tt> and
627      * <tt>unpack.</tt> are reserved for use by this API.
628      * <p>
629      * Unknown properties may be ignored or rejected with an
630      * unspecified error, and invalid entries may cause an
631      * unspecified error to be thrown.
632      *
633      * @return A sorted association of option key strings to option values.
634      */

635     SortedMap JavaDoc<String JavaDoc,String JavaDoc> properties();
636
637     /**
638      * Read a Pack200 archive, and write the encoded JAR to
639      * a JarOutputStream.
640      * The entire contents of the input stream will be read.
641      * It may be more efficient to read the Pack200 archive
642      * to a file and pass the File object, using the alternate
643      * method described below.
644      * <p>
645      * Closes its input but not its output. (The output can accumulate more elements.)
646      * @param in an InputStream.
647      * @param out a JarOutputStream.
648      * @exception IOException if an error is encountered.
649      */

650     void unpack(InputStream JavaDoc in, JarOutputStream JavaDoc out) throws IOException JavaDoc;
651
652     /**
653      * Read a Pack200 archive, and write the encoded JAR to
654      * a JarOutputStream.
655      * <p>
656      * Does not close its output. (The output can accumulate more elements.)
657      * @param in a File.
658      * @param out a JarOutputStream.
659      * @exception IOException if an error is encountered.
660      */

661     void unpack(File JavaDoc in, JarOutputStream JavaDoc out) throws IOException JavaDoc;
662
663     /**
664      * Registers a listener for PropertyChange events on the properties map.
665      * This is typically used by applications to update a progress bar.
666      *
667      * @see #properties
668      * @see #PROGRESS
669      * @param listener An object to be invoked when a property is changed.
670      */

671     void addPropertyChangeListener(PropertyChangeListener JavaDoc listener) ;
672
673     /**
674      * Remove a listener for PropertyChange events, added by
675      * the {@link #addPropertyChangeListener}.
676      *
677      * @see #addPropertyChangeListener
678      * @param listener The PropertyChange listener to be removed.
679      */

680     void removePropertyChangeListener(PropertyChangeListener JavaDoc listener);
681     }
682
683     // Private stuff....
684

685     private static final String JavaDoc PACK_PROVIDER = "java.util.jar.Pack200.Packer";
686     private static final String JavaDoc UNPACK_PROVIDER = "java.util.jar.Pack200.Unpacker";
687
688     private static Class JavaDoc packerImpl;
689     private static Class JavaDoc unpackerImpl;
690
691     private synchronized static Object JavaDoc newInstance(String JavaDoc prop) {
692     String JavaDoc implName = "(unknown)";
693     try {
694         Class JavaDoc impl = (prop == PACK_PROVIDER)? packerImpl: unpackerImpl;
695         if (impl == null) {
696         // The first time, we must decide which class to use.
697
implName = (String JavaDoc)
698             java.security.AccessController.doPrivileged
699             (new sun.security.action.GetPropertyAction(prop,""));
700         if (implName != null && !implName.equals(""))
701             impl = Class.forName(implName);
702         else if (prop == PACK_PROVIDER)
703             impl = com.sun.java.util.jar.pack.PackerImpl.class;
704         else
705             impl = com.sun.java.util.jar.pack.UnpackerImpl.class;
706         }
707         // We have a class. Now instantiate it.
708
return impl.newInstance();
709     } catch (ClassNotFoundException JavaDoc e) {
710         throw new Error JavaDoc("Class not found: " + implName +
711                 ":\ncheck property " + prop +
712                 " in your properties file.", e);
713     } catch (InstantiationException JavaDoc e) {
714         throw new Error JavaDoc("Could not instantiate: " + implName +
715                 ":\ncheck property " + prop +
716                 " in your properties file.", e);
717     } catch (IllegalAccessException JavaDoc e) {
718         throw new Error JavaDoc("Cannot access class: " + implName +
719                 ":\ncheck property " + prop +
720                 " in your properties file.", e);
721     }
722     }
723
724 }
725
726
Popular Tags