1 /*
2  * Copyright (c) 1996, 2022, 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 import java.lang.ref.Cleaner.Cleanable;
31 import java.lang.ref.Reference;
32 import java.nio.ByteBuffer;
33 import java.nio.ReadOnlyBufferException;
34 import java.util.Objects;
35 
36 import jdk.internal.ref.CleanerFactory;
37 import sun.nio.ch.DirectBuffer;
38 
39 /**
40  * This class provides support for general purpose compression using the
41  * popular ZLIB compression library. The ZLIB compression library was
42  * initially developed as part of the PNG graphics standard and is not
43  * protected by patents. It is fully described in the specifications at
44  * the <a href="package-summary.html#package-description">java.util.zip
45  * package description</a>.
46  * <p>
47  * This class deflates sequences of bytes into ZLIB compressed data format.
48  * The input byte sequence is provided in either byte array or byte buffer,
49  * via one of the {@code setInput()} methods. The output byte sequence is
50  * written to the output byte array or byte buffer passed to the
51  * {@code deflate()} methods.
52  * <p>
53  * The following code fragment demonstrates a trivial compression
54  * and decompression of a string using {@code Deflater} and
55  * {@code Inflater}.
56  *
57  * <blockquote><pre>
58  * try {
59  *     // Encode a String into bytes
60  *     String inputString = "blahblahblah";
61  *     byte[] input = inputString.getBytes("UTF-8");
62  *
63  *     // Compress the bytes
64  *     byte[] output = new byte[100];
65  *     Deflater compresser = new Deflater();
66  *     compresser.setInput(input);
67  *     compresser.finish();
68  *     int compressedDataLength = compresser.deflate(output);
69  *     compresser.end();
70  *
71  *     // Decompress the bytes
72  *     Inflater decompresser = new Inflater();
73  *     decompresser.setInput(output, 0, compressedDataLength);
74  *     byte[] result = new byte[100];
75  *     int resultLength = decompresser.inflate(result);
76  *     decompresser.end();
77  *
78  *     // Decode the bytes into a String
79  *     String outputString = new String(result, 0, resultLength, "UTF-8");
80  * } catch (java.io.UnsupportedEncodingException ex) {
81  *     // handle
82  * } catch (java.util.zip.DataFormatException ex) {
83  *     // handle
84  * }
85  * </pre></blockquote>
86  *
87  * @apiNote
88  * To release resources used by this {@code Deflater}, the {@link #end()} method
89  * should be called explicitly. Subclasses are responsible for the cleanup of resources
90  * acquired by the subclass. Subclasses that override {@link #finalize()} in order
91  * to perform cleanup should be modified to use alternative cleanup mechanisms such
92  * as {@link java.lang.ref.Cleaner} and remove the overriding {@code finalize} method.
93  *
94  * @see         Inflater
95  * @author      David Connelly
96  * @since 1.1
97  */
98 
99 public class Deflater {
100 
101     private final DeflaterZStreamRef zsRef;
102     private ByteBuffer input = ZipUtils.defaultBuf;
103     private byte[] inputArray;
104     private int inputPos, inputLim;
105     private int level, strategy;
106     private boolean setParams;
107     private boolean finish, finished;
108     private long bytesRead;
109     private long bytesWritten;
110 
111     // Android-added: CloseGuard support.
112     @ReachabilitySensitive
113     private final CloseGuard guard = CloseGuard.get();
114 
115     /**
116      * Compression method for the deflate algorithm (the only one currently
117      * supported).
118      */
119     public static final int DEFLATED = 8;
120 
121     /**
122      * Compression level for no compression.
123      */
124     public static final int NO_COMPRESSION = 0;
125 
126     /**
127      * Compression level for fastest compression.
128      */
129     public static final int BEST_SPEED = 1;
130 
131     /**
132      * Compression level for best compression.
133      */
134     public static final int BEST_COMPRESSION = 9;
135 
136     /**
137      * Default compression level.
138      */
139     public static final int DEFAULT_COMPRESSION = -1;
140 
141     /**
142      * Compression strategy best used for data consisting mostly of small
143      * values with a somewhat random distribution. Forces more Huffman coding
144      * and less string matching.
145      */
146     public static final int FILTERED = 1;
147 
148     /**
149      * Compression strategy for Huffman coding only.
150      */
151     public static final int HUFFMAN_ONLY = 2;
152 
153     /**
154      * Default compression strategy.
155      */
156     public static final int DEFAULT_STRATEGY = 0;
157 
158     /**
159      * Compression flush mode used to achieve best compression result.
160      *
161      * @see Deflater#deflate(byte[], int, int, int)
162      * @since 1.7
163      */
164     public static final int NO_FLUSH = 0;
165 
166     /**
167      * Compression flush mode used to flush out all pending output; may
168      * degrade compression for some compression algorithms.
169      *
170      * @see Deflater#deflate(byte[], int, int, int)
171      * @since 1.7
172      */
173     public static final int SYNC_FLUSH = 2;
174 
175     /**
176      * Compression flush mode used to flush out all pending output and
177      * reset the deflater. Using this mode too often can seriously degrade
178      * compression.
179      *
180      * @see Deflater#deflate(byte[], int, int, int)
181      * @since 1.7
182      */
183     public static final int FULL_FLUSH = 3;
184 
185     /**
186      * Flush mode to use at the end of output.  Can only be provided by the
187      * user by way of {@link #finish()}.
188      */
189     private static final int FINISH = 4;
190 
191     // Android-removed: initIDs handled in register method.
192     /*
193     static {
194         ZipUtils.loadLibrary();
195     }
196     */
197 
198     /**
199      * Creates a new compressor using the specified compression level.
200      * If 'nowrap' is true then the ZLIB header and checksum fields will
201      * not be used in order to support the compression format used in
202      * both GZIP and PKZIP.
203      * @param level the compression level (0-9)
204      * @param nowrap if true then use GZIP compatible compression
205      */
Deflater(int level, boolean nowrap)206     public Deflater(int level, boolean nowrap) {
207         this.level = level;
208         this.strategy = DEFAULT_STRATEGY;
209         this.zsRef = new DeflaterZStreamRef(this,
210                 init(level, DEFAULT_STRATEGY, nowrap));
211         // Android-added: CloseGuard support.
212         guard.open("end");
213     }
214 
215     /**
216      * Creates a new compressor using the specified compression level.
217      * Compressed data will be generated in ZLIB format.
218      * @param level the compression level (0-9)
219      */
Deflater(int level)220     public Deflater(int level) {
221         this(level, false);
222     }
223 
224     /**
225      * Creates a new compressor with the default compression level.
226      * Compressed data will be generated in ZLIB format.
227      */
Deflater()228     public Deflater() {
229         this(DEFAULT_COMPRESSION, false);
230     }
231 
232     /**
233      * Sets input data for compression.
234      * <p>
235      * One of the {@code setInput()} methods should be called whenever
236      * {@code needsInput()} returns true indicating that more input data
237      * is required.
238      * @param input the input data bytes
239      * @param off the start offset of the data
240      * @param len the length of the data
241      * @see Deflater#needsInput
242      */
setInput(byte[] input, int off, int len)243     public void setInput(byte[] input, int off, int len) {
244         if (off < 0 || len < 0 || off > input.length - len) {
245             throw new ArrayIndexOutOfBoundsException();
246         }
247         synchronized (zsRef) {
248             this.input = null;
249             this.inputArray = input;
250             this.inputPos = off;
251             this.inputLim = off + len;
252         }
253     }
254 
255     /**
256      * Sets input data for compression.
257      * <p>
258      * One of the {@code setInput()} methods should be called whenever
259      * {@code needsInput()} returns true indicating that more input data
260      * is required.
261      * @param input the input data bytes
262      * @see Deflater#needsInput
263      */
setInput(byte[] input)264     public void setInput(byte[] input) {
265         setInput(input, 0, input.length);
266     }
267 
268     /**
269      * Sets input data for compression.
270      * <p>
271      * One of the {@code setInput()} methods should be called whenever
272      * {@code needsInput()} returns true indicating that more input data
273      * is required.
274      * <p>
275      * The given buffer's position will be advanced as deflate
276      * operations are performed, up to the buffer's limit.
277      * The input buffer may be modified (refilled) between deflate
278      * operations; doing so is equivalent to creating a new buffer
279      * and setting it with this method.
280      * <p>
281      * Modifying the input buffer's contents, position, or limit
282      * concurrently with an deflate operation will result in
283      * undefined behavior, which may include incorrect operation
284      * results or operation failure.
285      *
286      * @param input the input data bytes
287      * @see Deflater#needsInput
288      * @since 11
289      */
setInput(ByteBuffer input)290     public void setInput(ByteBuffer input) {
291         Objects.requireNonNull(input);
292         synchronized (zsRef) {
293             this.input = input;
294             this.inputArray = null;
295         }
296     }
297 
298     /**
299      * Sets preset dictionary for compression. A preset dictionary is used
300      * when the history buffer can be predetermined. When the data is later
301      * uncompressed with Inflater.inflate(), Inflater.getAdler() can be called
302      * in order to get the Adler-32 value of the dictionary required for
303      * decompression.
304      * @param dictionary the dictionary data bytes
305      * @param off the start offset of the data
306      * @param len the length of the data
307      * @see Inflater#inflate
308      * @see Inflater#getAdler
309      */
setDictionary(byte[] dictionary, int off, int len)310     public void setDictionary(byte[] dictionary, int off, int len) {
311         if (off < 0 || len < 0 || off > dictionary.length - len) {
312             throw new ArrayIndexOutOfBoundsException();
313         }
314         synchronized (zsRef) {
315             ensureOpen();
316             setDictionary(zsRef.address(), dictionary, off, len);
317         }
318     }
319 
320     /**
321      * Sets preset dictionary for compression. A preset dictionary is used
322      * when the history buffer can be predetermined. When the data is later
323      * uncompressed with Inflater.inflate(), Inflater.getAdler() can be called
324      * in order to get the Adler-32 value of the dictionary required for
325      * decompression.
326      * @param dictionary the dictionary data bytes
327      * @see Inflater#inflate
328      * @see Inflater#getAdler
329      */
setDictionary(byte[] dictionary)330     public void setDictionary(byte[] dictionary) {
331         setDictionary(dictionary, 0, dictionary.length);
332     }
333 
334     /**
335      * Sets preset dictionary for compression. A preset dictionary is used
336      * when the history buffer can be predetermined. When the data is later
337      * uncompressed with Inflater.inflate(), Inflater.getAdler() can be called
338      * in order to get the Adler-32 value of the dictionary required for
339      * decompression.
340      * <p>
341      * The bytes in given byte buffer will be fully consumed by this method.  On
342      * return, its position will equal its limit.
343      *
344      * @param dictionary the dictionary data bytes
345      * @see Inflater#inflate
346      * @see Inflater#getAdler
347      */
setDictionary(ByteBuffer dictionary)348     public void setDictionary(ByteBuffer dictionary) {
349         synchronized (zsRef) {
350             int position = dictionary.position();
351             int remaining = Math.max(dictionary.limit() - position, 0);
352             ensureOpen();
353             if (dictionary.isDirect()) {
354                 long address = ((DirectBuffer) dictionary).address();
355                 try {
356                     setDictionaryBuffer(zsRef.address(), address + position, remaining);
357                 } finally {
358                     Reference.reachabilityFence(dictionary);
359                 }
360             } else {
361                 byte[] array = ZipUtils.getBufferArray(dictionary);
362                 int offset = ZipUtils.getBufferOffset(dictionary);
363                 setDictionary(zsRef.address(), array, offset + position, remaining);
364             }
365             dictionary.position(position + remaining);
366         }
367     }
368 
369     /**
370      * Sets the compression strategy to the specified value.
371      *
372      * <p> If the compression strategy is changed, the next invocation
373      * of {@code deflate} will compress the input available so far with
374      * the old strategy (and may be flushed); the new strategy will take
375      * effect only after that invocation.
376      *
377      * @param strategy the new compression strategy
378      * @throws    IllegalArgumentException if the compression strategy is
379      *                                     invalid
380      */
setStrategy(int strategy)381     public void setStrategy(int strategy) {
382         switch (strategy) {
383           case DEFAULT_STRATEGY:
384           case FILTERED:
385           case HUFFMAN_ONLY:
386             break;
387           default:
388             throw new IllegalArgumentException();
389         }
390         synchronized (zsRef) {
391             if (this.strategy != strategy) {
392                 this.strategy = strategy;
393                 setParams = true;
394             }
395         }
396     }
397 
398     /**
399      * Sets the compression level to the specified value.
400      *
401      * <p> If the compression level is changed, the next invocation
402      * of {@code deflate} will compress the input available so far
403      * with the old level (and may be flushed); the new level will
404      * take effect only after that invocation.
405      *
406      * @param level the new compression level (0-9)
407      * @throws    IllegalArgumentException if the compression level is invalid
408      */
setLevel(int level)409     public void setLevel(int level) {
410         if ((level < 0 || level > 9) && level != DEFAULT_COMPRESSION) {
411             throw new IllegalArgumentException("invalid compression level");
412         }
413         synchronized (zsRef) {
414             if (this.level != level) {
415                 this.level = level;
416                 setParams = true;
417             }
418         }
419     }
420 
421     /**
422      * Returns true if no data remains in the input buffer. This can
423      * be used to determine if one of the {@code setInput()} methods should be
424      * called in order to provide more input.
425      *
426      * @return true if the input data buffer is empty and setInput()
427      * should be called in order to provide more input
428      */
needsInput()429     public boolean needsInput() {
430         synchronized (zsRef) {
431             ByteBuffer input = this.input;
432             return input == null ? inputLim == inputPos : ! input.hasRemaining();
433         }
434     }
435 
436     /**
437      * When called, indicates that compression should end with the current
438      * contents of the input buffer.
439      */
finish()440     public void finish() {
441         synchronized (zsRef) {
442             finish = true;
443         }
444     }
445 
446     /**
447      * Returns true if the end of the compressed data output stream has
448      * been reached.
449      * @return true if the end of the compressed data output stream has
450      * been reached
451      */
finished()452     public boolean finished() {
453         synchronized (zsRef) {
454             return finished;
455         }
456     }
457 
458     /**
459      * Compresses the input data and fills specified buffer with compressed
460      * data. Returns actual number of bytes of compressed data. A return value
461      * of 0 indicates that {@link #needsInput() needsInput} should be called
462      * in order to determine if more input data is required.
463      *
464      * <p>This method uses {@link #NO_FLUSH} as its compression flush mode.
465      * An invocation of this method of the form {@code deflater.deflate(b, off, len)}
466      * yields the same result as the invocation of
467      * {@code deflater.deflate(b, off, len, Deflater.NO_FLUSH)}.
468      *
469      * @param output the buffer for the compressed data
470      * @param off the start offset of the data
471      * @param len the maximum number of bytes of compressed data
472      * @return the actual number of bytes of compressed data written to the
473      *         output buffer
474      */
deflate(byte[] output, int off, int len)475     public int deflate(byte[] output, int off, int len) {
476         return deflate(output, off, len, NO_FLUSH);
477     }
478 
479     /**
480      * Compresses the input data and fills specified buffer with compressed
481      * data. Returns actual number of bytes of compressed data. A return value
482      * of 0 indicates that {@link #needsInput() needsInput} should be called
483      * in order to determine if more input data is required.
484      *
485      * <p>This method uses {@link #NO_FLUSH} as its compression flush mode.
486      * An invocation of this method of the form {@code deflater.deflate(b)}
487      * yields the same result as the invocation of
488      * {@code deflater.deflate(b, 0, b.length, Deflater.NO_FLUSH)}.
489      *
490      * @param output the buffer for the compressed data
491      * @return the actual number of bytes of compressed data written to the
492      *         output buffer
493      */
deflate(byte[] output)494     public int deflate(byte[] output) {
495         return deflate(output, 0, output.length, NO_FLUSH);
496     }
497 
498     /**
499      * Compresses the input data and fills specified buffer with compressed
500      * data. Returns actual number of bytes of compressed data. A return value
501      * of 0 indicates that {@link #needsInput() needsInput} should be called
502      * in order to determine if more input data is required.
503      *
504      * <p>This method uses {@link #NO_FLUSH} as its compression flush mode.
505      * An invocation of this method of the form {@code deflater.deflate(output)}
506      * yields the same result as the invocation of
507      * {@code deflater.deflate(output, Deflater.NO_FLUSH)}.
508      *
509      * @param output the buffer for the compressed data
510      * @return the actual number of bytes of compressed data written to the
511      *         output buffer
512      * @since 11
513      */
deflate(ByteBuffer output)514     public int deflate(ByteBuffer output) {
515         return deflate(output, NO_FLUSH);
516     }
517 
518     /**
519      * Compresses the input data and fills the specified buffer with compressed
520      * data. Returns actual number of bytes of data compressed.
521      *
522      * <p>Compression flush mode is one of the following three modes:
523      *
524      * <ul>
525      * <li>{@link #NO_FLUSH}: allows the deflater to decide how much data
526      * to accumulate, before producing output, in order to achieve the best
527      * compression (should be used in normal use scenario). A return value
528      * of 0 in this flush mode indicates that {@link #needsInput()} should
529      * be called in order to determine if more input data is required.
530      *
531      * <li>{@link #SYNC_FLUSH}: all pending output in the deflater is flushed,
532      * to the specified output buffer, so that an inflater that works on
533      * compressed data can get all input data available so far (In particular
534      * the {@link #needsInput()} returns {@code true} after this invocation
535      * if enough output space is provided). Flushing with {@link #SYNC_FLUSH}
536      * may degrade compression for some compression algorithms and so it
537      * should be used only when necessary.
538      *
539      * <li>{@link #FULL_FLUSH}: all pending output is flushed out as with
540      * {@link #SYNC_FLUSH}. The compression state is reset so that the inflater
541      * that works on the compressed output data can restart from this point
542      * if previous compressed data has been damaged or if random access is
543      * desired. Using {@link #FULL_FLUSH} too often can seriously degrade
544      * compression.
545      * </ul>
546      *
547      * <p>In the case of {@link #FULL_FLUSH} or {@link #SYNC_FLUSH}, if
548      * the return value is {@code len}, the space available in output
549      * buffer {@code b}, this method should be invoked again with the same
550      * {@code flush} parameter and more output space. Make sure that
551      * {@code len} is greater than 6 to avoid flush marker (5 bytes) being
552      * repeatedly output to the output buffer every time this method is
553      * invoked.
554      *
555      * <p>If the {@link #setInput(ByteBuffer)} method was called to provide a buffer
556      * for input, the input buffer's position will be advanced by the number of bytes
557      * consumed by this operation.
558      *
559      * @param output the buffer for the compressed data
560      * @param off the start offset of the data
561      * @param len the maximum number of bytes of compressed data
562      * @param flush the compression flush mode
563      * @return the actual number of bytes of compressed data written to
564      *         the output buffer
565      *
566      * @throws IllegalArgumentException if the flush mode is invalid
567      * @since 1.7
568      */
deflate(byte[] output, int off, int len, int flush)569     public int deflate(byte[] output, int off, int len, int flush) {
570         if (off < 0 || len < 0 || off > output.length - len) {
571             throw new ArrayIndexOutOfBoundsException();
572         }
573         if (flush != NO_FLUSH && flush != SYNC_FLUSH && flush != FULL_FLUSH) {
574             throw new IllegalArgumentException();
575         }
576         synchronized (zsRef) {
577             ensureOpen();
578 
579             ByteBuffer input = this.input;
580             if (finish) {
581                 // disregard given flush mode in this case
582                 flush = FINISH;
583             }
584             int params;
585             if (setParams) {
586                 // bit 0: true to set params
587                 // bit 1-2: strategy (0, 1, or 2)
588                 // bit 3-31: level (0..9 or -1)
589                 params = 1 | strategy << 1 | level << 3;
590             } else {
591                 params = 0;
592             }
593             int inputPos;
594             long result;
595             if (input == null) {
596                 inputPos = this.inputPos;
597                 result = deflateBytesBytes(zsRef.address(),
598                     inputArray, inputPos, inputLim - inputPos,
599                     output, off, len,
600                     flush, params);
601             } else {
602                 inputPos = input.position();
603                 int inputRem = Math.max(input.limit() - inputPos, 0);
604                 if (input.isDirect()) {
605                     try {
606                         long inputAddress = ((DirectBuffer) input).address();
607                         result = deflateBufferBytes(zsRef.address(),
608                             inputAddress + inputPos, inputRem,
609                             output, off, len,
610                             flush, params);
611                     } finally {
612                         Reference.reachabilityFence(input);
613                     }
614                 } else {
615                     byte[] inputArray = ZipUtils.getBufferArray(input);
616                     int inputOffset = ZipUtils.getBufferOffset(input);
617                     result = deflateBytesBytes(zsRef.address(),
618                         inputArray, inputOffset + inputPos, inputRem,
619                         output, off, len,
620                         flush, params);
621                 }
622             }
623             int read = (int) (result & 0x7fff_ffffL);
624             int written = (int) (result >>> 31 & 0x7fff_ffffL);
625             if ((result >>> 62 & 1) != 0) {
626                 finished = true;
627             }
628             if (params != 0 && (result >>> 63 & 1) == 0) {
629                 setParams = false;
630             }
631             if (input != null) {
632                 input.position(inputPos + read);
633             } else {
634                 this.inputPos = inputPos + read;
635             }
636             bytesWritten += written;
637             bytesRead += read;
638             return written;
639         }
640     }
641 
642     /**
643      * Compresses the input data and fills the specified buffer with compressed
644      * data. Returns actual number of bytes of data compressed.
645      *
646      * <p>Compression flush mode is one of the following three modes:
647      *
648      * <ul>
649      * <li>{@link #NO_FLUSH}: allows the deflater to decide how much data
650      * to accumulate, before producing output, in order to achieve the best
651      * compression (should be used in normal use scenario). A return value
652      * of 0 in this flush mode indicates that {@link #needsInput()} should
653      * be called in order to determine if more input data is required.
654      *
655      * <li>{@link #SYNC_FLUSH}: all pending output in the deflater is flushed,
656      * to the specified output buffer, so that an inflater that works on
657      * compressed data can get all input data available so far (In particular
658      * the {@link #needsInput()} returns {@code true} after this invocation
659      * if enough output space is provided). Flushing with {@link #SYNC_FLUSH}
660      * may degrade compression for some compression algorithms and so it
661      * should be used only when necessary.
662      *
663      * <li>{@link #FULL_FLUSH}: all pending output is flushed out as with
664      * {@link #SYNC_FLUSH}. The compression state is reset so that the inflater
665      * that works on the compressed output data can restart from this point
666      * if previous compressed data has been damaged or if random access is
667      * desired. Using {@link #FULL_FLUSH} too often can seriously degrade
668      * compression.
669      * </ul>
670      *
671      * <p>In the case of {@link #FULL_FLUSH} or {@link #SYNC_FLUSH}, if
672      * the return value is equal to the {@linkplain ByteBuffer#remaining() remaining space}
673      * of the buffer, this method should be invoked again with the same
674      * {@code flush} parameter and more output space. Make sure that
675      * the buffer has at least 6 bytes of remaining space to avoid the
676      * flush marker (5 bytes) being repeatedly output to the output buffer
677      * every time this method is invoked.
678      *
679      * <p>On success, the position of the given {@code output} byte buffer will be
680      * advanced by as many bytes as were produced by the operation, which is equal
681      * to the number returned by this method.
682      *
683      * <p>If the {@link #setInput(ByteBuffer)} method was called to provide a buffer
684      * for input, the input buffer's position will be advanced by the number of bytes
685      * consumed by this operation.
686      *
687      * @param output the buffer for the compressed data
688      * @param flush the compression flush mode
689      * @return the actual number of bytes of compressed data written to
690      *         the output buffer
691      *
692      * @throws IllegalArgumentException if the flush mode is invalid
693      * @since 11
694      */
deflate(ByteBuffer output, int flush)695     public int deflate(ByteBuffer output, int flush) {
696         if (output.isReadOnly()) {
697             throw new ReadOnlyBufferException();
698         }
699         if (flush != NO_FLUSH && flush != SYNC_FLUSH && flush != FULL_FLUSH) {
700             throw new IllegalArgumentException();
701         }
702         synchronized (zsRef) {
703             ensureOpen();
704 
705             ByteBuffer input = this.input;
706             if (finish) {
707                 // disregard given flush mode in this case
708                 flush = FINISH;
709             }
710             int params;
711             if (setParams) {
712                 // bit 0: true to set params
713                 // bit 1-2: strategy (0, 1, or 2)
714                 // bit 3-31: level (0..9 or -1)
715                 params = 1 | strategy << 1 | level << 3;
716             } else {
717                 params = 0;
718             }
719             int outputPos = output.position();
720             int outputRem = Math.max(output.limit() - outputPos, 0);
721             int inputPos;
722             long result;
723             if (input == null) {
724                 inputPos = this.inputPos;
725                 if (output.isDirect()) {
726                     long outputAddress = ((DirectBuffer) output).address();
727                     try {
728                         result = deflateBytesBuffer(zsRef.address(),
729                             inputArray, inputPos, inputLim - inputPos,
730                             outputAddress + outputPos, outputRem,
731                             flush, params);
732                     } finally {
733                         Reference.reachabilityFence(output);
734                     }
735                 } else {
736                     byte[] outputArray = ZipUtils.getBufferArray(output);
737                     int outputOffset = ZipUtils.getBufferOffset(output);
738                     result = deflateBytesBytes(zsRef.address(),
739                         inputArray, inputPos, inputLim - inputPos,
740                         outputArray, outputOffset + outputPos, outputRem,
741                         flush, params);
742                 }
743             } else {
744                 inputPos = input.position();
745                 int inputRem = Math.max(input.limit() - inputPos, 0);
746                 if (input.isDirect()) {
747                     long inputAddress = ((DirectBuffer) input).address();
748                     try {
749                         if (output.isDirect()) {
750                             long outputAddress = outputPos + ((DirectBuffer) output).address();
751                             try {
752                                 result = deflateBufferBuffer(zsRef.address(),
753                                     inputAddress + inputPos, inputRem,
754                                     outputAddress, outputRem,
755                                     flush, params);
756                             } finally {
757                                 Reference.reachabilityFence(output);
758                             }
759                         } else {
760                             byte[] outputArray = ZipUtils.getBufferArray(output);
761                             int outputOffset = ZipUtils.getBufferOffset(output);
762                             result = deflateBufferBytes(zsRef.address(),
763                                 inputAddress + inputPos, inputRem,
764                                 outputArray, outputOffset + outputPos, outputRem,
765                                 flush, params);
766                         }
767                     } finally {
768                         Reference.reachabilityFence(input);
769                     }
770                 } else {
771                     byte[] inputArray = ZipUtils.getBufferArray(input);
772                     int inputOffset = ZipUtils.getBufferOffset(input);
773                     if (output.isDirect()) {
774                         long outputAddress = ((DirectBuffer) output).address();
775                         try {
776                             result = deflateBytesBuffer(zsRef.address(),
777                                 inputArray, inputOffset + inputPos, inputRem,
778                                 outputAddress + outputPos, outputRem,
779                                 flush, params);
780                         } finally {
781                             Reference.reachabilityFence(output);
782                         }
783                     } else {
784                         byte[] outputArray = ZipUtils.getBufferArray(output);
785                         int outputOffset = ZipUtils.getBufferOffset(output);
786                         result = deflateBytesBytes(zsRef.address(),
787                             inputArray, inputOffset + inputPos, inputRem,
788                             outputArray, outputOffset + outputPos, outputRem,
789                             flush, params);
790                     }
791                 }
792             }
793             int read = (int) (result & 0x7fff_ffffL);
794             int written = (int) (result >>> 31 & 0x7fff_ffffL);
795             if ((result >>> 62 & 1) != 0) {
796                 finished = true;
797             }
798             if (params != 0 && (result >>> 63 & 1) == 0) {
799                 setParams = false;
800             }
801             if (input != null) {
802                 input.position(inputPos + read);
803             } else {
804                 this.inputPos = inputPos + read;
805             }
806             output.position(outputPos + written);
807             bytesWritten += written;
808             bytesRead += read;
809             return written;
810         }
811     }
812 
813     /**
814      * Returns the ADLER-32 value of the uncompressed data.
815      * @return the ADLER-32 value of the uncompressed data
816      */
getAdler()817     public int getAdler() {
818         synchronized (zsRef) {
819             ensureOpen();
820             return getAdler(zsRef.address());
821         }
822     }
823 
824     /**
825      * Returns the total number of uncompressed bytes input so far.
826      *
827      * <p>Since the number of bytes may be greater than
828      * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now
829      * the preferred means of obtaining this information.</p>
830      *
831      * @return the total number of uncompressed bytes input so far
832      */
getTotalIn()833     public int getTotalIn() {
834         return (int) getBytesRead();
835     }
836 
837     /**
838      * Returns the total number of uncompressed bytes input so far.
839      *
840      * @return the total (non-negative) number of uncompressed bytes input so far
841      * @since 1.5
842      */
getBytesRead()843     public long getBytesRead() {
844         synchronized (zsRef) {
845             ensureOpen();
846             return bytesRead;
847         }
848     }
849 
850     /**
851      * Returns the total number of compressed bytes output so far.
852      *
853      * <p>Since the number of bytes may be greater than
854      * Integer.MAX_VALUE, the {@link #getBytesWritten()} method is now
855      * the preferred means of obtaining this information.</p>
856      *
857      * @return the total number of compressed bytes output so far
858      */
getTotalOut()859     public int getTotalOut() {
860         return (int) getBytesWritten();
861     }
862 
863     /**
864      * Returns the total number of compressed bytes output so far.
865      *
866      * @return the total (non-negative) number of compressed bytes output so far
867      * @since 1.5
868      */
getBytesWritten()869     public long getBytesWritten() {
870         synchronized (zsRef) {
871             ensureOpen();
872             return bytesWritten;
873         }
874     }
875 
876     /**
877      * Resets deflater so that a new set of input data can be processed.
878      * Keeps current compression level and strategy settings.
879      */
reset()880     public void reset() {
881         synchronized (zsRef) {
882             ensureOpen();
883             reset(zsRef.address());
884             finish = false;
885             finished = false;
886             input = ZipUtils.defaultBuf;
887             inputArray = null;
888             bytesRead = bytesWritten = 0;
889         }
890     }
891 
892     /**
893      * Closes the compressor and discards any unprocessed input.
894      *
895      * This method should be called when the compressor is no longer
896      * being used. Once this method is called, the behavior of the
897      * Deflater object is undefined.
898      */
end()899     public void end() {
900         synchronized (zsRef) {
901             zsRef.clean();
902             // Android-added: CloseGuard support.
903             if (guard != null) {
904                 guard.close();
905             }
906             input = ZipUtils.defaultBuf;
907         }
908     }
909 
ensureOpen()910     private void ensureOpen() {
911         assert Thread.holdsLock(zsRef);
912         if (zsRef.address() == 0)
913             throw new NullPointerException("Deflater has been closed");
914     }
915 
916     /**
917      * Returns the value of 'finish' flag.
918      * 'finish' will be set to true if def.finish() method is called.
919      */
shouldFinish()920     boolean shouldFinish() {
921         synchronized (zsRef) {
922             return finish;
923         }
924     }
925 
init(int level, int strategy, boolean nowrap)926     private static native long init(int level, int strategy, boolean nowrap);
setDictionary(long addr, byte[] b, int off, int len)927     private static native void setDictionary(long addr, byte[] b, int off,
928                                              int len);
setDictionaryBuffer(long addr, long bufAddress, int len)929     private static native void setDictionaryBuffer(long addr, long bufAddress, int len);
deflateBytesBytes(long addr, byte[] inputArray, int inputOff, int inputLen, byte[] outputArray, int outputOff, int outputLen, int flush, int params)930     private native long deflateBytesBytes(long addr,
931         byte[] inputArray, int inputOff, int inputLen,
932         byte[] outputArray, int outputOff, int outputLen,
933         int flush, int params);
deflateBytesBuffer(long addr, byte[] inputArray, int inputOff, int inputLen, long outputAddress, int outputLen, int flush, int params)934     private native long deflateBytesBuffer(long addr,
935         byte[] inputArray, int inputOff, int inputLen,
936         long outputAddress, int outputLen,
937         int flush, int params);
deflateBufferBytes(long addr, long inputAddress, int inputLen, byte[] outputArray, int outputOff, int outputLen, int flush, int params)938     private native long deflateBufferBytes(long addr,
939         long inputAddress, int inputLen,
940         byte[] outputArray, int outputOff, int outputLen,
941         int flush, int params);
deflateBufferBuffer(long addr, long inputAddress, int inputLen, long outputAddress, int outputLen, int flush, int params)942     private native long deflateBufferBuffer(long addr,
943         long inputAddress, int inputLen,
944         long outputAddress, int outputLen,
945         int flush, int params);
getAdler(long addr)946     private static native int getAdler(long addr);
reset(long addr)947     private static native void reset(long addr);
end(long addr)948     private static native void end(long addr);
949 
950     /**
951      * A reference to the native zlib's z_stream structure. It also
952      * serves as the "cleaner" to clean up the native resource when
953      * the Deflater is ended, closed or cleaned.
954      */
955     static class DeflaterZStreamRef implements Runnable {
956 
957         private long address;
958         private final Cleanable cleanable;
959 
DeflaterZStreamRef(Deflater owner, long addr)960         private DeflaterZStreamRef(Deflater owner, long addr) {
961             this.cleanable = (owner != null) ? CleanerFactory.cleaner().register(owner, this) : null;
962             this.address = addr;
963         }
964 
address()965         long address() {
966             return address;
967         }
968 
clean()969         void clean() {
970             cleanable.clean();
971         }
972 
run()973         public synchronized void run() {
974             long addr = address;
975             address = 0;
976             if (addr != 0) {
977                 end(addr);
978             }
979         }
980 
981     }
982 }
983