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