1 /*
2  * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
3  * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
4  *
5  *
6  *
7  *
8  *
9  *
10  *
11  *
12  *
13  *
14  *
15  *
16  *
17  *
18  *
19  *
20  *
21  *
22  *
23  *
24  */

25
26 package java.util.zip;
27
28 /**
29  * This class provides support for general purpose compression using the
30  * popular ZLIB compression library. The ZLIB compression library was
31  * initially developed as part of the PNG graphics standard and is not
32  * protected by patents. It is fully described in the specifications at
33  * the <a href="package-summary.html#package_description">java.util.zip
34  * package description</a>.
35  *
36  * <p>The following code fragment demonstrates a trivial compression
37  * and decompression of a string using <tt>Deflater</tt> and
38  * <tt>Inflater</tt>.
39  *
40  * <blockquote><pre>
41  * try {
42  *     // Encode a String into bytes
43  *     String inputString = "blahblahblah";
44  *     byte[] input = inputString.getBytes("UTF-8");
45  *
46  *     // Compress the bytes
47  *     byte[] output = new byte[100];
48  *     Deflater compresser = new Deflater();
49  *     compresser.setInput(input);
50  *     compresser.finish();
51  *     int compressedDataLength = compresser.deflate(output);
52  *     compresser.end();
53  *
54  *     // Decompress the bytes
55  *     Inflater decompresser = new Inflater();
56  *     decompresser.setInput(output, 0, compressedDataLength);
57  *     byte[] result = new byte[100];
58  *     int resultLength = decompresser.inflate(result);
59  *     decompresser.end();
60  *
61  *     // Decode the bytes into a String
62  *     String outputString = new String(result, 0, resultLength, "UTF-8");
63  * } catch(java.io.UnsupportedEncodingException ex) {
64  *     // handle
65  * } catch (java.util.zip.DataFormatException ex) {
66  *     // handle
67  * }
68  * </pre></blockquote>
69  *
70  * @see         Inflater
71  * @author      David Connelly
72  */

73 public
74 class Deflater {
75
76     private final ZStreamRef zsRef;
77     private byte[] buf = new byte[0];
78     private int off, len;
79     private int level, strategy;
80     private boolean setParams;
81     private boolean finish, finished;
82     private long bytesRead;
83     private long bytesWritten;
84
85     /**
86      * Compression method for the deflate algorithm (the only one currently
87      * supported).
88      */

89     public static final int DEFLATED = 8;
90
91     /**
92      * Compression level for no compression.
93      */

94     public static final int NO_COMPRESSION = 0;
95
96     /**
97      * Compression level for fastest compression.
98      */

99     public static final int BEST_SPEED = 1;
100
101     /**
102      * Compression level for best compression.
103      */

104     public static final int BEST_COMPRESSION = 9;
105
106     /**
107      * Default compression level.
108      */

109     public static final int DEFAULT_COMPRESSION = -1;
110
111     /**
112      * Compression strategy best used for data consisting mostly of small
113      * values with a somewhat random distribution. Forces more Huffman coding
114      * and less string matching.
115      */

116     public static final int FILTERED = 1;
117
118     /**
119      * Compression strategy for Huffman coding only.
120      */

121     public static final int HUFFMAN_ONLY = 2;
122
123     /**
124      * Default compression strategy.
125      */

126     public static final int DEFAULT_STRATEGY = 0;
127
128     /**
129      * Compression flush mode used to achieve best compression result.
130      *
131      * @see Deflater#deflate(byte[], intintint)
132      * @since 1.7
133      */

134     public static final int NO_FLUSH = 0;
135
136     /**
137      * Compression flush mode used to flush out all pending output; may
138      * degrade compression for some compression algorithms.
139      *
140      * @see Deflater#deflate(byte[], intintint)
141      * @since 1.7
142      */

143     public static final int SYNC_FLUSH = 2;
144
145     /**
146      * Compression flush mode used to flush out all pending output and
147      * reset the deflater. Using this mode too often can seriously degrade
148      * compression.
149      *
150      * @see Deflater#deflate(byte[], intintint)
151      * @since 1.7
152      */

153     public static final int FULL_FLUSH = 3;
154
155     static {
156         /* Zip library is loaded from System.initializeSystemClass */
157         initIDs();
158     }
159
160     /**
161      * Creates a new compressor using the specified compression level.
162      * If 'nowrap' is true then the ZLIB header and checksum fields will
163      * not be used in order to support the compression format used in
164      * both GZIP and PKZIP.
165      * @param level the compression level (0-9)
166      * @param nowrap if true then use GZIP compatible compression
167      */

168     public Deflater(int level, boolean nowrap) {
169         this.level = level;
170         this.strategy = DEFAULT_STRATEGY;
171         this.zsRef = new ZStreamRef(init(level, DEFAULT_STRATEGY, nowrap));
172     }
173
174     /**
175      * Creates a new compressor using the specified compression level.
176      * Compressed data will be generated in ZLIB format.
177      * @param level the compression level (0-9)
178      */

179     public Deflater(int level) {
180         this(level, false);
181     }
182
183     /**
184      * Creates a new compressor with the default compression level.
185      * Compressed data will be generated in ZLIB format.
186      */

187     public Deflater() {
188         this(DEFAULT_COMPRESSION, false);
189     }
190
191     /**
192      * Sets input data for compression. This should be called whenever
193      * needsInput() returns true indicating that more input data is required.
194      * @param b the input data bytes
195      * @param off the start offset of the data
196      * @param len the length of the data
197      * @see Deflater#needsInput
198      */

199     public void setInput(byte[] b, int off, int len) {
200         if (b== null) {
201             throw new NullPointerException();
202         }
203         if (off < 0 || len < 0 || off > b.length - len) {
204             throw new ArrayIndexOutOfBoundsException();
205         }
206         synchronized (zsRef) {
207             this.buf = b;
208             this.off = off;
209             this.len = len;
210         }
211     }
212
213     /**
214      * Sets input data for compression. This should be called whenever
215      * needsInput() returns true indicating that more input data is required.
216      * @param b the input data bytes
217      * @see Deflater#needsInput
218      */

219     public void setInput(byte[] b) {
220         setInput(b, 0, b.length);
221     }
222
223     /**
224      * Sets preset dictionary for compression. A preset dictionary is used
225      * when the history buffer can be predetermined. When the data is later
226      * uncompressed with Inflater.inflate(), Inflater.getAdler() can be called
227      * in order to get the Adler-32 value of the dictionary required for
228      * decompression.
229      * @param b the dictionary data bytes
230      * @param off the start offset of the data
231      * @param len the length of the data
232      * @see Inflater#inflate
233      * @see Inflater#getAdler
234      */

235     public void setDictionary(byte[] b, int off, int len) {
236         if (b == null) {
237             throw new NullPointerException();
238         }
239         if (off < 0 || len < 0 || off > b.length - len) {
240             throw new ArrayIndexOutOfBoundsException();
241         }
242         synchronized (zsRef) {
243             ensureOpen();
244             setDictionary(zsRef.address(), b, off, len);
245         }
246     }
247
248     /**
249      * Sets preset dictionary for compression. A preset dictionary is used
250      * when the history buffer can be predetermined. When the data is later
251      * uncompressed with Inflater.inflate(), Inflater.getAdler() can be called
252      * in order to get the Adler-32 value of the dictionary required for
253      * decompression.
254      * @param b the dictionary data bytes
255      * @see Inflater#inflate
256      * @see Inflater#getAdler
257      */

258     public void setDictionary(byte[] b) {
259         setDictionary(b, 0, b.length);
260     }
261
262     /**
263      * Sets the compression strategy to the specified value.
264      *
265      * <p> If the compression strategy is changed, the next invocation
266      * of {@code deflate} will compress the input available so far with
267      * the old strategy (and may be flushed); the new strategy will take
268      * effect only after that invocation.
269      *
270      * @param strategy the new compression strategy
271      * @exception IllegalArgumentException if the compression strategy is
272      *                                     invalid
273      */

274     public void setStrategy(int strategy) {
275         switch (strategy) {
276           case DEFAULT_STRATEGY:
277           case FILTERED:
278           case HUFFMAN_ONLY:
279             break;
280           default:
281             throw new IllegalArgumentException();
282         }
283         synchronized (zsRef) {
284             if (this.strategy != strategy) {
285                 this.strategy = strategy;
286                 setParams = true;
287             }
288         }
289     }
290
291     /**
292      * Sets the compression level to the specified value.
293      *
294      * <p> If the compression level is changed, the next invocation
295      * of {@code deflate} will compress the input available so far
296      * with the old level (and may be flushed); the new level will
297      * take effect only after that invocation.
298      *
299      * @param level the new compression level (0-9)
300      * @exception IllegalArgumentException if the compression level is invalid
301      */

302     public void setLevel(int level) {
303         if ((level < 0 || level > 9) && level != DEFAULT_COMPRESSION) {
304             throw new IllegalArgumentException("invalid compression level");
305         }
306         synchronized (zsRef) {
307             if (this.level != level) {
308                 this.level = level;
309                 setParams = true;
310             }
311         }
312     }
313
314     /**
315      * Returns true if the input data buffer is empty and setInput()
316      * should be called in order to provide more input.
317      * @return true if the input data buffer is empty and setInput()
318      * should be called in order to provide more input
319      */

320     public boolean needsInput() {
321         synchronized (zsRef) {
322             return len <= 0;
323         }
324     }
325
326     /**
327      * When called, indicates that compression should end with the current
328      * contents of the input buffer.
329      */

330     public void finish() {
331         synchronized (zsRef) {
332             finish = true;
333         }
334     }
335
336     /**
337      * Returns true if the end of the compressed data output stream has
338      * been reached.
339      * @return true if the end of the compressed data output stream has
340      * been reached
341      */

342     public boolean finished() {
343         synchronized (zsRef) {
344             return finished;
345         }
346     }
347
348     /**
349      * Compresses the input data and fills specified buffer with compressed
350      * data. Returns actual number of bytes of compressed data. A return value
351      * of 0 indicates that {@link #needsInput() needsInput} should be called
352      * in order to determine if more input data is required.
353      *
354      * <p>This method uses {@link #NO_FLUSH} as its compression flush mode.
355      * An invocation of this method of the form {@code deflater.deflate(b, off, len)}
356      * yields the same result as the invocation of
357      * {@code deflater.deflate(b, off, len, Deflater.NO_FLUSH)}.
358      *
359      * @param b the buffer for the compressed data
360      * @param off the start offset of the data
361      * @param len the maximum number of bytes of compressed data
362      * @return the actual number of bytes of compressed data written to the
363      *         output buffer
364      */

365     public int deflate(byte[] b, int off, int len) {
366         return deflate(b, off, len, NO_FLUSH);
367     }
368
369     /**
370      * Compresses the input data and fills specified buffer with compressed
371      * data. Returns actual number of bytes of compressed data. A return value
372      * of 0 indicates that {@link #needsInput() needsInput} should be called
373      * in order to determine if more input data is required.
374      *
375      * <p>This method uses {@link #NO_FLUSH} as its compression flush mode.
376      * An invocation of this method of the form {@code deflater.deflate(b)}
377      * yields the same result as the invocation of
378      * {@code deflater.deflate(b, 0, b.length, Deflater.NO_FLUSH)}.
379      *
380      * @param b the buffer for the compressed data
381      * @return the actual number of bytes of compressed data written to the
382      *         output buffer
383      */

384     public int deflate(byte[] b) {
385         return deflate(b, 0, b.length, NO_FLUSH);
386     }
387
388     /**
389      * Compresses the input data and fills the specified buffer with compressed
390      * data. Returns actual number of bytes of data compressed.
391      *
392      * <p>Compression flush mode is one of the following three modes:
393      *
394      * <ul>
395      * <li>{@link #NO_FLUSH}: allows the deflater to decide how much data
396      * to accumulate, before producing output, in order to achieve the best
397      * compression (should be used in normal use scenario). A return value
398      * of 0 in this flush mode indicates that {@link #needsInput()} should
399      * be called in order to determine if more input data is required.
400      *
401      * <li>{@link #SYNC_FLUSH}: all pending output in the deflater is flushed,
402      * to the specified output buffer, so that an inflater that works on
403      * compressed data can get all input data available so far (In particular
404      * the {@link #needsInput()} returns {@code true} after this invocation
405      * if enough output space is provided). Flushing with {@link #SYNC_FLUSH}
406      * may degrade compression for some compression algorithms and so it
407      * should be used only when necessary.
408      *
409      * <li>{@link #FULL_FLUSH}: all pending output is flushed out as with
410      * {@link #SYNC_FLUSH}. The compression state is reset so that the inflater
411      * that works on the compressed output data can restart from this point
412      * if previous compressed data has been damaged or if random access is
413      * desired. Using {@link #FULL_FLUSH} too often can seriously degrade
414      * compression.
415      * </ul>
416      *
417      * <p>In the case of {@link #FULL_FLUSH} or {@link #SYNC_FLUSH}, if
418      * the return value is {@code len}, the space available in output
419      * buffer {@code b}, this method should be invoked again with the same
420      * {@code flush} parameter and more output space.
421      *
422      * @param b the buffer for the compressed data
423      * @param off the start offset of the data
424      * @param len the maximum number of bytes of compressed data
425      * @param flush the compression flush mode
426      * @return the actual number of bytes of compressed data written to
427      *         the output buffer
428      *
429      * @throws IllegalArgumentException if the flush mode is invalid
430      * @since 1.7
431      */

432     public int deflate(byte[] b, int off, int len, int flush) {
433         if (b == null) {
434             throw new NullPointerException();
435         }
436         if (off < 0 || len < 0 || off > b.length - len) {
437             throw new ArrayIndexOutOfBoundsException();
438         }
439         synchronized (zsRef) {
440             ensureOpen();
441             if (flush == NO_FLUSH || flush == SYNC_FLUSH ||
442                 flush == FULL_FLUSH) {
443                 int thisLen = this.len;
444                 int n = deflateBytes(zsRef.address(), b, off, len, flush);
445                 bytesWritten += n;
446                 bytesRead += (thisLen - this.len);
447                 return n;
448             }
449             throw new IllegalArgumentException();
450         }
451     }
452
453     /**
454      * Returns the ADLER-32 value of the uncompressed data.
455      * @return the ADLER-32 value of the uncompressed data
456      */

457     public int getAdler() {
458         synchronized (zsRef) {
459             ensureOpen();
460             return getAdler(zsRef.address());
461         }
462     }
463
464     /**
465      * Returns the total number of uncompressed bytes input so far.
466      *
467      * <p>Since the number of bytes may be greater than
468      * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now
469      * the preferred means of obtaining this information.</p>
470      *
471      * @return the total number of uncompressed bytes input so far
472      */

473     public int getTotalIn() {
474         return (int) getBytesRead();
475     }
476
477     /**
478      * Returns the total number of uncompressed bytes input so far.
479      *
480      * @return the total (non-negative) number of uncompressed bytes input so far
481      * @since 1.5
482      */

483     public long getBytesRead() {
484         synchronized (zsRef) {
485             ensureOpen();
486             return bytesRead;
487         }
488     }
489
490     /**
491      * Returns the total number of compressed bytes output so far.
492      *
493      * <p>Since the number of bytes may be greater than
494      * Integer.MAX_VALUE, the {@link #getBytesWritten()} method is now
495      * the preferred means of obtaining this information.</p>
496      *
497      * @return the total number of compressed bytes output so far
498      */

499     public int getTotalOut() {
500         return (int) getBytesWritten();
501     }
502
503     /**
504      * Returns the total number of compressed bytes output so far.
505      *
506      * @return the total (non-negative) number of compressed bytes output so far
507      * @since 1.5
508      */

509     public long getBytesWritten() {
510         synchronized (zsRef) {
511             ensureOpen();
512             return bytesWritten;
513         }
514     }
515
516     /**
517      * Resets deflater so that a new set of input data can be processed.
518      * Keeps current compression level and strategy settings.
519      */

520     public void reset() {
521         synchronized (zsRef) {
522             ensureOpen();
523             reset(zsRef.address());
524             finish = false;
525             finished = false;
526             off = len = 0;
527             bytesRead = bytesWritten = 0;
528         }
529     }
530
531     /**
532      * Closes the compressor and discards any unprocessed input.
533      * This method should be called when the compressor is no longer
534      * being used, but will also be called automatically by the
535      * finalize() method. Once this method is called, the behavior
536      * of the Deflater object is undefined.
537      */

538     public void end() {
539         synchronized (zsRef) {
540             long addr = zsRef.address();
541             zsRef.clear();
542             if (addr != 0) {
543                 end(addr);
544                 buf = null;
545             }
546         }
547     }
548
549     /**
550      * Closes the compressor when garbage is collected.
551      */

552     protected void finalize() {
553         end();
554     }
555
556     private void ensureOpen() {
557         assert Thread.holdsLock(zsRef);
558         if (zsRef.address() == 0)
559             throw new NullPointerException("Deflater has been closed");
560     }
561
562     private static native void initIDs();
563     private native static long init(int level, int strategy, boolean nowrap);
564     private native static void setDictionary(long addr, byte[] b, int off, int len);
565     private native int deflateBytes(long addr, byte[] b, int off, int len,
566                                     int flush);
567     private native static int getAdler(long addr);
568     private native static void reset(long addr);
569     private native static void end(long addr);
570 }
571
Powered by JavaMelody