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 {
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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)
917 protected void finalize() {}
918
919 private void ensureOpen() {
920 assert Thread.holdsLock(zsRef);
921 if (zsRef.address() == 0)
922 throw new NullPointerException("Deflater has been closed");
923 }
924
925 private static native long init(int level, int strategy, boolean nowrap);
926 private static native void setDictionary(long addr, byte[] b, int off,
927 int len);
928 private static native void setDictionaryBuffer(long addr, long bufAddress, int len);
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);
933 private native long deflateBytesBuffer(long addr,
934 byte[] inputArray, int inputOff, int inputLen,
935 long outputAddress, int outputLen,
936 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);
941 private native long deflateBufferBuffer(long addr,
942 long inputAddress, int inputLen,
943 long outputAddress, int outputLen,
944 int flush, int params);
945 private static native int getAdler(long addr);
946 private static native void reset(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
959 private DeflaterZStreamRef(Deflater owner, long addr) {
960 this.cleanable = (owner != null) ? CleanerFactory.cleaner().register(owner, this) : null;
961 this.address = addr;
962 }
963
964 long address() {
965 return address;
966 }
967
968 void clean() {
969 cleanable.clean();
970 }
971
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 */
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
1002 FinalizableZStreamRef (Deflater owner, long addr) {
1003 super(null, addr);
1004 this.owner = owner;
1005 }
1006
1007 @Override
1008 void clean() {
1009 run();
1010 }
1011
1012 @Override
1013 @SuppressWarnings("deprecation")
1014 protected void finalize() {
1015 owner.end();
1016 }
1017 }
1018 }
1019 }
1020