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