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