• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 1996, 2010, 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 
26 package java.util.zip;
27 
28 import dalvik.system.CloseGuard;
29 
30 /**
31  * This class provides support for general purpose compression using the
32  * popular ZLIB compression library. The ZLIB compression library was
33  * initially developed as part of the PNG graphics standard and is not
34  * protected by patents. It is fully described in the specifications at
35  * the <a href="package-summary.html#package_description">java.util.zip
36  * package description</a>.
37  *
38  * <p>The following code fragment demonstrates a trivial compression
39  * and decompression of a string using <tt>Deflater</tt> and
40  * <tt>Inflater</tt>.
41  *
42  * <blockquote><pre>
43  * try {
44  *     // Encode a String into bytes
45  *     String inputString = "blahblahblah";
46  *     byte[] input = inputString.getBytes("UTF-8");
47  *
48  *     // Compress the bytes
49  *     byte[] output = new byte[100];
50  *     Deflater compresser = new Deflater();
51  *     compresser.setInput(input);
52  *     compresser.finish();
53  *     int compressedDataLength = compresser.deflate(output);
54  *     compresser.end();
55  *
56  *     // Decompress the bytes
57  *     Inflater decompresser = new Inflater();
58  *     decompresser.setInput(output, 0, compressedDataLength);
59  *     byte[] result = new byte[100];
60  *     int resultLength = decompresser.inflate(result);
61  *     decompresser.end();
62  *
63  *     // Decode the bytes into a String
64  *     String outputString = new String(result, 0, resultLength, "UTF-8");
65  * } catch(java.io.UnsupportedEncodingException ex) {
66  *     // handle
67  * } catch (java.util.zip.DataFormatException ex) {
68  *     // handle
69  * }
70  * </pre></blockquote>
71  *
72  * @see         Inflater
73  * @author      David Connelly
74  */
75 public
76 class Deflater {
77 
78     private final ZStreamRef zsRef;
79     private byte[] buf = new byte[0];
80     private int off, len;
81     private int level, strategy;
82     private boolean setParams;
83     private boolean finish, finished;
84     private long bytesRead;
85     private long bytesWritten;
86 
87     private final CloseGuard guard = CloseGuard.get();
88 
89     /**
90      * Compression method for the deflate algorithm (the only one currently
91      * supported).
92      */
93     public static final int DEFLATED = 8;
94 
95     /**
96      * Compression level for no compression.
97      */
98     public static final int NO_COMPRESSION = 0;
99 
100     /**
101      * Compression level for fastest compression.
102      */
103     public static final int BEST_SPEED = 1;
104 
105     /**
106      * Compression level for best compression.
107      */
108     public static final int BEST_COMPRESSION = 9;
109 
110     /**
111      * Default compression level.
112      */
113     public static final int DEFAULT_COMPRESSION = -1;
114 
115     /**
116      * Compression strategy best used for data consisting mostly of small
117      * values with a somewhat random distribution. Forces more Huffman coding
118      * and less string matching.
119      */
120     public static final int FILTERED = 1;
121 
122     /**
123      * Compression strategy for Huffman coding only.
124      */
125     public static final int HUFFMAN_ONLY = 2;
126 
127     /**
128      * Default compression strategy.
129      */
130     public static final int DEFAULT_STRATEGY = 0;
131 
132     /**
133      * Compression flush mode used to achieve best compression result.
134      *
135      * @see Deflater#deflate(byte[], int, int, int)
136      * @since 1.7
137      */
138     public static final int NO_FLUSH = 0;
139 
140     /**
141      * Compression flush mode used to flush out all pending output; may
142      * degrade compression for some compression algorithms.
143      *
144      * @see Deflater#deflate(byte[], int, int, int)
145      * @since 1.7
146      */
147     public static final int SYNC_FLUSH = 2;
148 
149     /**
150      * Compression flush mode used to flush out all pending output and
151      * reset the deflater. Using this mode too often can seriously degrade
152      * compression.
153      *
154      * @see Deflater#deflate(byte[], int, int, int)
155      * @since 1.7
156      */
157     public static final int FULL_FLUSH = 3;
158 
159     /**
160      * Creates a new compressor using the specified compression level.
161      * If 'nowrap' is true then the ZLIB header and checksum fields will
162      * not be used in order to support the compression format used in
163      * both GZIP and PKZIP.
164      * @param level the compression level (0-9)
165      * @param nowrap if true then use GZIP compatible compression
166      */
Deflater(int level, boolean nowrap)167     public Deflater(int level, boolean nowrap) {
168         this.level = level;
169         this.strategy = DEFAULT_STRATEGY;
170         this.zsRef = new ZStreamRef(init(level, DEFAULT_STRATEGY, nowrap));
171         guard.open("end");
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      */
Deflater(int level)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      */
Deflater()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      */
setInput(byte[] b, int off, int len)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      */
setInput(byte[] b)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      */
setDictionary(byte[] b, int off, int len)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      */
setDictionary(byte[] b)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      * @param strategy the new compression strategy
265      * @exception IllegalArgumentException if the compression strategy is
266      *                                     invalid
267      */
setStrategy(int strategy)268     public void setStrategy(int strategy) {
269         switch (strategy) {
270           case DEFAULT_STRATEGY:
271           case FILTERED:
272           case HUFFMAN_ONLY:
273             break;
274           default:
275             throw new IllegalArgumentException();
276         }
277         synchronized (zsRef) {
278             if (this.strategy != strategy) {
279                 this.strategy = strategy;
280                 setParams = true;
281             }
282         }
283     }
284 
285     /**
286      * Sets the current compression level to the specified value.
287      * @param level the new compression level (0-9)
288      * @exception IllegalArgumentException if the compression level is invalid
289      */
setLevel(int level)290     public void setLevel(int level) {
291         if ((level < 0 || level > 9) && level != DEFAULT_COMPRESSION) {
292             throw new IllegalArgumentException("invalid compression level");
293         }
294         synchronized (zsRef) {
295             if (this.level != level) {
296                 this.level = level;
297                 setParams = true;
298             }
299         }
300     }
301 
302     /**
303      * Returns true if the input data buffer is empty and setInput()
304      * should be called in order to provide more input.
305      * @return true if the input data buffer is empty and setInput()
306      * should be called in order to provide more input
307      */
needsInput()308     public boolean needsInput() {
309         return len <= 0;
310     }
311 
312     /**
313      * When called, indicates that compression should end with the current
314      * contents of the input buffer.
315      */
finish()316     public void finish() {
317         synchronized (zsRef) {
318             finish = true;
319         }
320     }
321 
322     /**
323      * Returns true if the end of the compressed data output stream has
324      * been reached.
325      * @return true if the end of the compressed data output stream has
326      * been reached
327      */
finished()328     public boolean finished() {
329         synchronized (zsRef) {
330             return finished;
331         }
332     }
333 
334     /**
335      * Compresses the input data and fills specified buffer with compressed
336      * data. Returns actual number of bytes of compressed data. A return value
337      * of 0 indicates that {@link #needsInput() needsInput} should be called
338      * in order to determine if more input data is required.
339      *
340      * <p>This method uses {@link #NO_FLUSH} as its compression flush mode.
341      * An invocation of this method of the form {@code deflater.deflate(b, off, len)}
342      * yields the same result as the invocation of
343      * {@code deflater.deflate(b, off, len, Deflater.NO_FLUSH)}.
344      *
345      * @param b the buffer for the compressed data
346      * @param off the start offset of the data
347      * @param len the maximum number of bytes of compressed data
348      * @return the actual number of bytes of compressed data written to the
349      *         output buffer
350      */
deflate(byte[] b, int off, int len)351     public int deflate(byte[] b, int off, int len) {
352         return deflate(b, off, len, NO_FLUSH);
353     }
354 
355     /**
356      * Compresses the input data and fills specified buffer with compressed
357      * data. Returns actual number of bytes of compressed data. A return value
358      * of 0 indicates that {@link #needsInput() needsInput} should be called
359      * in order to determine if more input data is required.
360      *
361      * <p>This method uses {@link #NO_FLUSH} as its compression flush mode.
362      * An invocation of this method of the form {@code deflater.deflate(b)}
363      * yields the same result as the invocation of
364      * {@code deflater.deflate(b, 0, b.length, Deflater.NO_FLUSH)}.
365      *
366      * @param b the buffer for the compressed data
367      * @return the actual number of bytes of compressed data written to the
368      *         output buffer
369      */
deflate(byte[] b)370     public int deflate(byte[] b) {
371         return deflate(b, 0, b.length, NO_FLUSH);
372     }
373 
374     /**
375      * Compresses the input data and fills the specified buffer with compressed
376      * data. Returns actual number of bytes of data compressed.
377      *
378      * <p>Compression flush mode is one of the following three modes:
379      *
380      * <ul>
381      * <li>{@link #NO_FLUSH}: allows the deflater to decide how much data
382      * to accumulate, before producing output, in order to achieve the best
383      * compression (should be used in normal use scenario). A return value
384      * of 0 in this flush mode indicates that {@link #needsInput()} should
385      * be called in order to determine if more input data is required.
386      *
387      * <li>{@link #SYNC_FLUSH}: all pending output in the deflater is flushed,
388      * to the specified output buffer, so that an inflater that works on
389      * compressed data can get all input data available so far (In particular
390      * the {@link #needsInput()} returns {@code true} after this invocation
391      * if enough output space is provided). Flushing with {@link #SYNC_FLUSH}
392      * may degrade compression for some compression algorithms and so it
393      * should be used only when necessary.
394      *
395      * <li>{@link #FULL_FLUSH}: all pending output is flushed out as with
396      * {@link #SYNC_FLUSH}. The compression state is reset so that the inflater
397      * that works on the compressed output data can restart from this point
398      * if previous compressed data has been damaged or if random access is
399      * desired. Using {@link #FULL_FLUSH} too often can seriously degrade
400      * compression.
401      * </ul>
402      *
403      * <p>In the case of {@link #FULL_FLUSH} or {@link #SYNC_FLUSH}, if
404      * the return value is {@code len}, the space available in output
405      * buffer {@code b}, this method should be invoked again with the same
406      * {@code flush} parameter and more output space.
407      *
408      * @param b the buffer for the compressed data
409      * @param off the start offset of the data
410      * @param len the maximum number of bytes of compressed data
411      * @param flush the compression flush mode
412      * @return the actual number of bytes of compressed data written to
413      *         the output buffer
414      *
415      * @throws IllegalArgumentException if the flush mode is invalid
416      * @since 1.7
417      */
deflate(byte[] b, int off, int len, int flush)418     public int deflate(byte[] b, int off, int len, int flush) {
419         if (b == null) {
420             throw new NullPointerException();
421         }
422         if (off < 0 || len < 0 || off > b.length - len) {
423             throw new ArrayIndexOutOfBoundsException();
424         }
425         synchronized (zsRef) {
426             ensureOpen();
427             if (flush == NO_FLUSH || flush == SYNC_FLUSH ||
428                 flush == FULL_FLUSH) {
429                 int thisLen = this.len;
430                 int n = deflateBytes(zsRef.address(), b, off, len, flush);
431                 bytesWritten += n;
432                 bytesRead += (thisLen - this.len);
433                 return n;
434             }
435             throw new IllegalArgumentException();
436         }
437     }
438 
439     /**
440      * Returns the ADLER-32 value of the uncompressed data.
441      * @return the ADLER-32 value of the uncompressed data
442      */
getAdler()443     public int getAdler() {
444         synchronized (zsRef) {
445             ensureOpen();
446             return getAdler(zsRef.address());
447         }
448     }
449 
450     /**
451      * Returns the total number of uncompressed bytes input so far.
452      *
453      * <p>Since the number of bytes may be greater than
454      * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now
455      * the preferred means of obtaining this information.</p>
456      *
457      * @return the total number of uncompressed bytes input so far
458      */
getTotalIn()459     public int getTotalIn() {
460         return (int) getBytesRead();
461     }
462 
463     /**
464      * Returns the total number of uncompressed bytes input so far.</p>
465      *
466      * @return the total (non-negative) number of uncompressed bytes input so far
467      * @since 1.5
468      */
getBytesRead()469     public long getBytesRead() {
470         synchronized (zsRef) {
471             ensureOpen();
472             return bytesRead;
473         }
474     }
475 
476     /**
477      * Returns the total number of compressed bytes output so far.
478      *
479      * <p>Since the number of bytes may be greater than
480      * Integer.MAX_VALUE, the {@link #getBytesWritten()} method is now
481      * the preferred means of obtaining this information.</p>
482      *
483      * @return the total number of compressed bytes output so far
484      */
getTotalOut()485     public int getTotalOut() {
486         return (int) getBytesWritten();
487     }
488 
489     /**
490      * Returns the total number of compressed bytes output so far.</p>
491      *
492      * @return the total (non-negative) number of compressed bytes output so far
493      * @since 1.5
494      */
getBytesWritten()495     public long getBytesWritten() {
496         synchronized (zsRef) {
497             ensureOpen();
498             return bytesWritten;
499         }
500     }
501 
502     /**
503      * Resets deflater so that a new set of input data can be processed.
504      * Keeps current compression level and strategy settings.
505      */
reset()506     public void reset() {
507         synchronized (zsRef) {
508             ensureOpen();
509             reset(zsRef.address());
510             finish = false;
511             finished = false;
512             off = len = 0;
513             bytesRead = bytesWritten = 0;
514         }
515     }
516 
517     /**
518      * Closes the compressor and discards any unprocessed input.
519      * This method should be called when the compressor is no longer
520      * being used, but will also be called automatically by the
521      * finalize() method. Once this method is called, the behavior
522      * of the Deflater object is undefined.
523      */
end()524     public void end() {
525         synchronized (zsRef) {
526             guard.close();
527 
528             long addr = zsRef.address();
529             zsRef.clear();
530             if (addr != 0) {
531                 end(addr);
532                 buf = null;
533             }
534         }
535     }
536 
537     /**
538      * Closes the compressor when garbage is collected.
539      */
finalize()540     protected void finalize() {
541         if (guard != null) {
542             guard.warnIfOpen();
543         }
544 
545         end();
546     }
547 
ensureOpen()548     private void ensureOpen() {
549         assert Thread.holdsLock(zsRef);
550         if (zsRef.address() == 0)
551             throw new NullPointerException("Deflater has been closed");
552     }
553 
init(int level, int strategy, boolean nowrap)554     private native static long init(int level, int strategy, boolean nowrap);
setDictionary(long addr, byte[] b, int off, int len)555     private native static void setDictionary(long addr, byte[] b, int off, int len);
deflateBytes(long addr, byte[] b, int off, int len, int flush)556     private native int deflateBytes(long addr, byte[] b, int off, int len,
557                                     int flush);
getAdler(long addr)558     private native static int getAdler(long addr);
reset(long addr)559     private native static void reset(long addr);
end(long addr)560     private native static void end(long addr);
561 }
562