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