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