1 /* 2 * Copyright (c) 1996, 2017, 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 jdk.internal.ref.CleanerFactory; 30 31 /** 32 * This class provides support for general purpose decompression using the 33 * popular ZLIB compression library. The ZLIB compression library was 34 * initially developed as part of the PNG graphics standard and is not 35 * protected by patents. It is fully described in the specifications at 36 * the <a href="package-summary.html#package.description">java.util.zip 37 * package description</a>. 38 * 39 * <p>The following code fragment demonstrates a trivial compression 40 * and decompression of a string using {@code Deflater} and 41 * {@code Inflater}. 42 * 43 * <blockquote><pre> 44 * try { 45 * // Encode a String into bytes 46 * String inputString = "blahblahblah\u20AC\u20AC"; 47 * byte[] input = inputString.getBytes("UTF-8"); 48 * 49 * // Compress the bytes 50 * byte[] output = new byte[100]; 51 * Deflater compresser = new Deflater(); 52 * compresser.setInput(input); 53 * compresser.finish(); 54 * int compressedDataLength = compresser.deflate(output); 55 * 56 * // Decompress the bytes 57 * Inflater decompresser = new Inflater(); 58 * decompresser.setInput(output, 0, compressedDataLength); 59 * byte[] result = new byte[100]; 75 * acquired by the subclass. Subclasses that override {@link #finalize()} in order 76 * to perform cleanup should be modified to use alternative cleanup mechanisms such 77 * as {@link java.lang.ref.Cleaner} and remove the overriding {@code finalize} method. 78 * 79 * @implSpec 80 * If this {@code Inflater} has been subclassed and the {@code end} method has been 81 * overridden, the {@code end} method will be called by the finalization when the 82 * inflater is unreachable. But the subclasses should not depend on this specific 83 * implementation; the finalization is not reliable and the {@code finalize} method 84 * is deprecated to be removed. 85 * 86 * @see Deflater 87 * @author David Connelly 88 * @since 1.1 89 * 90 */ 91 92 public class Inflater { 93 94 private final InflaterZStreamRef zsRef; 95 private byte[] buf = defaultBuf; 96 private int off, len; 97 private boolean finished; 98 private boolean needDict; 99 private long bytesRead; 100 private long bytesWritten; 101 102 private static final byte[] defaultBuf = new byte[0]; 103 104 static { 105 ZipUtils.loadLibrary(); 106 initIDs(); 107 } 108 109 /** 110 * Creates a new decompressor. If the parameter 'nowrap' is true then 111 * the ZLIB header and checksum fields will not be used. This provides 112 * compatibility with the compression format used by both GZIP and PKZIP. 113 * <p> 114 * Note: When using the 'nowrap' option it is also necessary to provide 115 * an extra "dummy" byte as input. This is required by the ZLIB native 116 * library in order to support certain optimizations. 117 * 118 * @param nowrap if true then support GZIP compatible compression 119 */ 120 public Inflater(boolean nowrap) { 121 this.zsRef = InflaterZStreamRef.get(this, init(nowrap)); 122 } 123 124 /** 125 * Creates a new decompressor. 126 */ 127 public Inflater() { 128 this(false); 129 } 130 131 /** 132 * Sets input data for decompression. Should be called whenever 133 * needsInput() returns true indicating that more input data is 134 * required. 135 * @param b the input data bytes 136 * @param off the start offset of the input data 137 * @param len the length of the input data 138 * @see Inflater#needsInput 139 */ 140 public void setInput(byte[] b, int off, int len) { 141 if (b == null) { 142 throw new NullPointerException(); 143 } 144 if (off < 0 || len < 0 || off > b.length - len) { 145 throw new ArrayIndexOutOfBoundsException(); 146 } 147 synchronized (zsRef) { 148 this.buf = b; 149 this.off = off; 150 this.len = len; 151 } 152 } 153 154 /** 155 * Sets input data for decompression. Should be called whenever 156 * needsInput() returns true indicating that more input data is 157 * required. 158 * @param b the input data bytes 159 * @see Inflater#needsInput 160 */ 161 public void setInput(byte[] b) { 162 setInput(b, 0, b.length); 163 } 164 165 /** 166 * Sets the preset dictionary to the given array of bytes. Should be 167 * called when inflate() returns 0 and needsDictionary() returns true 168 * indicating that a preset dictionary is required. The method getAdler() 169 * can be used to get the Adler-32 value of the dictionary needed. 170 * @param b the dictionary data bytes 171 * @param off the start offset of the data 172 * @param len the length of the data 173 * @see Inflater#needsDictionary 174 * @see Inflater#getAdler 175 */ 176 public void setDictionary(byte[] b, int off, int len) { 177 if (b == null) { 178 throw new NullPointerException(); 179 } 180 if (off < 0 || len < 0 || off > b.length - len) { 181 throw new ArrayIndexOutOfBoundsException(); 182 } 183 synchronized (zsRef) { 184 ensureOpen(); 185 setDictionary(zsRef.address(), b, off, len); 186 needDict = false; 187 } 188 } 189 190 /** 191 * Sets the preset dictionary to the given array of bytes. Should be 192 * called when inflate() returns 0 and needsDictionary() returns true 193 * indicating that a preset dictionary is required. The method getAdler() 194 * can be used to get the Adler-32 value of the dictionary needed. 195 * @param b the dictionary data bytes 196 * @see Inflater#needsDictionary 197 * @see Inflater#getAdler 198 */ 199 public void setDictionary(byte[] b) { 200 setDictionary(b, 0, b.length); 201 } 202 203 /** 204 * Returns the total number of bytes remaining in the input buffer. 205 * This can be used to find out what bytes still remain in the input 206 * buffer after decompression has finished. 207 * @return the total number of bytes remaining in the input buffer 208 */ 209 public int getRemaining() { 210 synchronized (zsRef) { 211 return len; 212 } 213 } 214 215 /** 216 * Returns true if no data remains in the input buffer. This can 217 * be used to determine if #setInput should be called in order 218 * to provide more input. 219 * @return true if no data remains in the input buffer 220 */ 221 public boolean needsInput() { 222 synchronized (zsRef) { 223 return len <= 0; 224 } 225 } 226 227 /** 228 * Returns true if a preset dictionary is needed for decompression. 229 * @return true if a preset dictionary is needed for decompression 230 * @see Inflater#setDictionary 231 */ 232 public boolean needsDictionary() { 233 synchronized (zsRef) { 234 return needDict; 235 } 236 } 237 238 /** 239 * Returns true if the end of the compressed data stream has been 240 * reached. 241 * @return true if the end of the compressed data stream has been 242 * reached 243 */ 244 public boolean finished() { 245 synchronized (zsRef) { 246 return finished; 247 } 248 } 249 250 /** 251 * Uncompresses bytes into specified buffer. Returns actual number 252 * of bytes uncompressed. A return value of 0 indicates that 253 * needsInput() or needsDictionary() should be called in order to 254 * determine if more input data or a preset dictionary is required. 255 * In the latter case, getAdler() can be used to get the Adler-32 256 * value of the dictionary required. 257 * @param b the buffer for the uncompressed data 258 * @param off the start offset of the data 259 * @param len the maximum number of uncompressed bytes 260 * @return the actual number of uncompressed bytes 261 * @exception DataFormatException if the compressed data format is invalid 262 * @see Inflater#needsInput 263 * @see Inflater#needsDictionary 264 */ 265 public int inflate(byte[] b, int off, int len) 266 throws DataFormatException 267 { 268 if (b == null) { 269 throw new NullPointerException(); 270 } 271 if (off < 0 || len < 0 || off > b.length - len) { 272 throw new ArrayIndexOutOfBoundsException(); 273 } 274 synchronized (zsRef) { 275 ensureOpen(); 276 int thisLen = this.len; 277 int n = inflateBytes(zsRef.address(), b, off, len); 278 bytesWritten += n; 279 bytesRead += (thisLen - this.len); 280 return n; 281 } 282 } 283 284 /** 285 * Uncompresses bytes into specified buffer. Returns actual number 286 * of bytes uncompressed. A return value of 0 indicates that 287 * needsInput() or needsDictionary() should be called in order to 288 * determine if more input data or a preset dictionary is required. 289 * In the latter case, getAdler() can be used to get the Adler-32 290 * value of the dictionary required. 291 * @param b the buffer for the uncompressed data 292 * @return the actual number of uncompressed bytes 293 * @exception DataFormatException if the compressed data format is invalid 294 * @see Inflater#needsInput 295 * @see Inflater#needsDictionary 296 */ 297 public int inflate(byte[] b) throws DataFormatException { 298 return inflate(b, 0, b.length); 299 } 300 301 /** 302 * Returns the ADLER-32 value of the uncompressed data. 303 * @return the ADLER-32 value of the uncompressed data 304 */ 305 public int getAdler() { 306 synchronized (zsRef) { 307 ensureOpen(); 308 return getAdler(zsRef.address()); 309 } 310 } 311 312 /** 313 * Returns the total number of compressed bytes input so far. 314 * 315 * <p>Since the number of bytes may be greater than 316 * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now 317 * the preferred means of obtaining this information.</p> 318 * 351 /** 352 * Returns the total number of uncompressed bytes output so far. 353 * 354 * @return the total (non-negative) number of uncompressed bytes output so far 355 * @since 1.5 356 */ 357 public long getBytesWritten() { 358 synchronized (zsRef) { 359 ensureOpen(); 360 return bytesWritten; 361 } 362 } 363 364 /** 365 * Resets inflater so that a new set of input data can be processed. 366 */ 367 public void reset() { 368 synchronized (zsRef) { 369 ensureOpen(); 370 reset(zsRef.address()); 371 buf = defaultBuf; 372 finished = false; 373 needDict = false; 374 off = len = 0; 375 bytesRead = bytesWritten = 0; 376 } 377 } 378 379 /** 380 * Closes the decompressor and discards any unprocessed input. 381 * 382 * This method should be called when the decompressor is no longer 383 * being used. Once this method is called, the behavior of the 384 * Inflater object is undefined. 385 */ 386 public void end() { 387 synchronized (zsRef) { 388 zsRef.clean(); 389 buf = null; 390 } 391 } 392 393 /** 394 * Closes the decompressor when garbage is collected. 395 * 396 * @implSpec 397 * If this {@code Inflater} has been subclassed and the {@code end} method 398 * has been overridden, the {@code end} method will be called when the 399 * inflater is unreachable. 400 * 401 * @deprecated The {@code finalize} method has been deprecated and will be 402 * removed. It is implemented as a no-op. Subclasses that override 403 * {@code finalize} in order to perform cleanup should be modified to use 404 * alternative cleanup mechanisms and remove the overriding {@code finalize} 405 * method. The recommended cleanup for compressor is to explicitly call 406 * {@code end} method when it is no longer in use. If the {@code end} is 407 * not invoked explicitly the resource of the compressor will be released 408 * when the instance becomes unreachable, 409 */ 410 @Deprecated(since="9", forRemoval=true) 411 protected void finalize() {} 412 413 private void ensureOpen () { 414 assert Thread.holdsLock(zsRef); 415 if (zsRef.address() == 0) 416 throw new NullPointerException("Inflater has been closed"); 417 } 418 419 boolean ended() { 420 synchronized (zsRef) { 421 return zsRef.address() == 0; 422 } 423 } 424 425 private static native void initIDs(); 426 private static native long init(boolean nowrap); 427 private static native void setDictionary(long addr, byte[] b, int off, 428 int len); 429 private native int inflateBytes(long addr, byte[] b, int off, int len) 430 throws DataFormatException; 431 private static native int getAdler(long addr); 432 private static native void reset(long addr); 433 private static native void end(long addr); 434 435 /** 436 * A reference to the native zlib's z_stream structure. It also 437 * serves as the "cleaner" to clean up the native resource when 438 * the Inflater is ended, closed or cleaned. 439 */ 440 static class InflaterZStreamRef implements Runnable { 441 442 private long address; 443 private final Cleanable cleanable; 444 445 private InflaterZStreamRef(Inflater owner, long addr) { 446 this.cleanable = (owner != null) ? CleanerFactory.cleaner().register(owner, this) : null; 447 this.address = addr; 448 } 449 450 long address() { | 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 decompression 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 inflates sequences of ZLIB compressed bytes. The input byte 46 * sequence is provided in either byte array or byte buffer, via one of the 47 * {@code setInput()} methods. The output byte sequence is written to the 48 * output byte array or byte buffer passed to the {@code deflate()} methods. 49 * <p> 50 * The following code fragment demonstrates a trivial compression 51 * and decompression of a string using {@code Deflater} and 52 * {@code Inflater}. 53 * 54 * <blockquote><pre> 55 * try { 56 * // Encode a String into bytes 57 * String inputString = "blahblahblah\u20AC\u20AC"; 58 * byte[] input = inputString.getBytes("UTF-8"); 59 * 60 * // Compress the bytes 61 * byte[] output = new byte[100]; 62 * Deflater compresser = new Deflater(); 63 * compresser.setInput(input); 64 * compresser.finish(); 65 * int compressedDataLength = compresser.deflate(output); 66 * 67 * // Decompress the bytes 68 * Inflater decompresser = new Inflater(); 69 * decompresser.setInput(output, 0, compressedDataLength); 70 * byte[] result = new byte[100]; 86 * acquired by the subclass. Subclasses that override {@link #finalize()} in order 87 * to perform cleanup should be modified to use alternative cleanup mechanisms such 88 * as {@link java.lang.ref.Cleaner} and remove the overriding {@code finalize} method. 89 * 90 * @implSpec 91 * If this {@code Inflater} has been subclassed and the {@code end} method has been 92 * overridden, the {@code end} method will be called by the finalization when the 93 * inflater is unreachable. But the subclasses should not depend on this specific 94 * implementation; the finalization is not reliable and the {@code finalize} method 95 * is deprecated to be removed. 96 * 97 * @see Deflater 98 * @author David Connelly 99 * @since 1.1 100 * 101 */ 102 103 public class Inflater { 104 105 private final InflaterZStreamRef zsRef; 106 private ByteBuffer input = ZipUtils.defaultBuf; 107 private byte[] inputArray; 108 private int inputPos, inputLim; 109 private boolean finished; 110 private boolean needDict; 111 private long bytesRead; 112 private long bytesWritten; 113 114 /* 115 * These fields are used as an "out" parameter from JNI when a 116 * DataFormatException is thrown during the inflate operation. 117 */ 118 private int inputConsumed; 119 private int outputConsumed; 120 121 static { 122 ZipUtils.loadLibrary(); 123 initIDs(); 124 } 125 126 /** 127 * Creates a new decompressor. If the parameter 'nowrap' is true then 128 * the ZLIB header and checksum fields will not be used. This provides 129 * compatibility with the compression format used by both GZIP and PKZIP. 130 * <p> 131 * Note: When using the 'nowrap' option it is also necessary to provide 132 * an extra "dummy" byte as input. This is required by the ZLIB native 133 * library in order to support certain optimizations. 134 * 135 * @param nowrap if true then support GZIP compatible compression 136 */ 137 public Inflater(boolean nowrap) { 138 this.zsRef = InflaterZStreamRef.get(this, init(nowrap)); 139 } 140 141 /** 142 * Creates a new decompressor. 143 */ 144 public Inflater() { 145 this(false); 146 } 147 148 /** 149 * Sets input data for decompression. 150 * <p> 151 * One of the {@code setInput()} methods should be called whenever 152 * {@code needsInput()} returns true indicating that more input data 153 * is required. 154 * 155 * @param input the input data bytes 156 * @param off the start offset of the input data 157 * @param len the length of the input data 158 * @see Inflater#needsInput 159 */ 160 public void setInput(byte[] input, int off, int len) { 161 if (off < 0 || len < 0 || off > input.length - len) { 162 throw new ArrayIndexOutOfBoundsException(); 163 } 164 synchronized (zsRef) { 165 this.input = null; 166 this.inputArray = input; 167 this.inputPos = off; 168 this.inputLim = off + len; 169 } 170 } 171 172 /** 173 * Sets input data for decompression. 174 * <p> 175 * One of the {@code setInput()} methods should be called whenever 176 * {@code needsInput()} returns true indicating that more input data 177 * is required. 178 * 179 * @param input the input data bytes 180 * @see Inflater#needsInput 181 */ 182 public void setInput(byte[] input) { 183 setInput(input, 0, input.length); 184 } 185 186 /** 187 * Sets input data for decompression. 188 * <p> 189 * One of the {@code setInput()} methods should be called whenever 190 * {@code needsInput()} returns true indicating that more input data 191 * is required. 192 * <p> 193 * The given buffer's position will be advanced as inflate 194 * operations are performed, up to the buffer's limit. 195 * The input buffer may be modified (refilled) between inflate 196 * operations; doing so is equivalent to creating a new buffer 197 * and setting it with this method. 198 * <p> 199 * Modifying the input buffer's contents, position, or limit 200 * concurrently with an inflate operation will result in 201 * undefined behavior, which may include incorrect operation 202 * results or operation failure. 203 * 204 * @param input the input data bytes 205 * @see Inflater#needsInput 206 * @since 11 207 */ 208 public void setInput(ByteBuffer input) { 209 Objects.requireNonNull(input); 210 synchronized (zsRef) { 211 this.input = input; 212 this.inputArray = null; 213 } 214 } 215 216 /** 217 * Sets the preset dictionary to the given array of bytes. Should be 218 * called when inflate() returns 0 and needsDictionary() returns true 219 * indicating that a preset dictionary is required. The method getAdler() 220 * can be used to get the Adler-32 value of the dictionary needed. 221 * @param dictionary the dictionary data bytes 222 * @param off the start offset of the data 223 * @param len the length of the data 224 * @see Inflater#needsDictionary 225 * @see Inflater#getAdler 226 */ 227 public void setDictionary(byte[] dictionary, int off, int len) { 228 if (off < 0 || len < 0 || off > dictionary.length - len) { 229 throw new ArrayIndexOutOfBoundsException(); 230 } 231 synchronized (zsRef) { 232 ensureOpen(); 233 setDictionary(zsRef.address(), dictionary, off, len); 234 needDict = false; 235 } 236 } 237 238 /** 239 * Sets the preset dictionary to the given array of bytes. Should be 240 * called when inflate() returns 0 and needsDictionary() returns true 241 * indicating that a preset dictionary is required. The method getAdler() 242 * can be used to get the Adler-32 value of the dictionary needed. 243 * @param dictionary the dictionary data bytes 244 * @see Inflater#needsDictionary 245 * @see Inflater#getAdler 246 */ 247 public void setDictionary(byte[] dictionary) { 248 setDictionary(dictionary, 0, dictionary.length); 249 } 250 251 /** 252 * Sets the preset dictionary to the bytes in the given buffer. Should be 253 * called when inflate() returns 0 and needsDictionary() returns true 254 * indicating that a preset dictionary is required. The method getAdler() 255 * can be used to get the Adler-32 value of the dictionary needed. 256 * <p> 257 * The bytes in given byte buffer will be fully consumed by this method. On 258 * return, its position will equal its limit. 259 * 260 * @param dictionary the dictionary data bytes 261 * @see Inflater#needsDictionary 262 * @see Inflater#getAdler 263 * @since 11 264 */ 265 public void setDictionary(ByteBuffer dictionary) { 266 synchronized (zsRef) { 267 int position = dictionary.position(); 268 int remaining = Math.max(dictionary.limit() - position, 0); 269 ensureOpen(); 270 if (dictionary.isDirect()) { 271 long address = ((DirectBuffer) dictionary).address(); 272 try { 273 setDictionaryBuffer(zsRef.address(), address + position, remaining); 274 } finally { 275 Reference.reachabilityFence(dictionary); 276 } 277 } else { 278 byte[] array = ZipUtils.getBufferArray(dictionary); 279 int offset = ZipUtils.getBufferOffset(dictionary); 280 setDictionary(zsRef.address(), array, offset + position, remaining); 281 } 282 dictionary.position(position + remaining); 283 needDict = false; 284 } 285 } 286 287 /** 288 * Returns the total number of bytes remaining in the input buffer. 289 * This can be used to find out what bytes still remain in the input 290 * buffer after decompression has finished. 291 * @return the total number of bytes remaining in the input buffer 292 */ 293 public int getRemaining() { 294 synchronized (zsRef) { 295 ByteBuffer input = this.input; 296 return input == null ? inputLim - inputPos : input.remaining(); 297 } 298 } 299 300 /** 301 * Returns true if no data remains in the input buffer. This can 302 * be used to determine if one of the {@code setInput()} methods should be 303 * called in order to provide more input. 304 * 305 * @return true if no data remains in the input buffer 306 */ 307 public boolean needsInput() { 308 synchronized (zsRef) { 309 ByteBuffer input = this.input; 310 return input == null ? inputLim == inputPos : ! input.hasRemaining(); 311 } 312 } 313 314 /** 315 * Returns true if a preset dictionary is needed for decompression. 316 * @return true if a preset dictionary is needed for decompression 317 * @see Inflater#setDictionary 318 */ 319 public boolean needsDictionary() { 320 synchronized (zsRef) { 321 return needDict; 322 } 323 } 324 325 /** 326 * Returns true if the end of the compressed data stream has been 327 * reached. 328 * @return true if the end of the compressed data stream has been 329 * reached 330 */ 331 public boolean finished() { 332 synchronized (zsRef) { 333 return finished; 334 } 335 } 336 337 /** 338 * Uncompresses bytes into specified buffer. Returns actual number 339 * of bytes uncompressed. A return value of 0 indicates that 340 * needsInput() or needsDictionary() should be called in order to 341 * determine if more input data or a preset dictionary is required. 342 * In the latter case, getAdler() can be used to get the Adler-32 343 * value of the dictionary required. 344 * <p> 345 * If the {@link #setInput(ByteBuffer)} method was called to provide a buffer 346 * for input, the input buffer's position will be advanced by the number of bytes 347 * consumed by this operation, even in the event that a {@link DataFormatException} 348 * is thrown. 349 * <p> 350 * The {@linkplain #getRemaining() remaining byte count} will be reduced by 351 * the number of consumed input bytes. If the {@link #setInput(ByteBuffer)} 352 * method was called to provide a buffer for input, the input buffer's position 353 * will be advanced the number of consumed bytes. 354 * <p> 355 * These byte totals, as well as 356 * the {@linkplain #getBytesRead() total bytes read} 357 * and the {@linkplain #getBytesWritten() total bytes written} 358 * values, will be updated even in the event that a {@link DataFormatException} 359 * is thrown to reflect the amount of data consumed and produced before the 360 * exception occurred. 361 * 362 * @param output the buffer for the uncompressed data 363 * @param off the start offset of the data 364 * @param len the maximum number of uncompressed bytes 365 * @return the actual number of uncompressed bytes 366 * @throws DataFormatException if the compressed data format is invalid 367 * @see Inflater#needsInput 368 * @see Inflater#needsDictionary 369 */ 370 public int inflate(byte[] output, int off, int len) 371 throws DataFormatException 372 { 373 if (off < 0 || len < 0 || off > output.length - len) { 374 throw new ArrayIndexOutOfBoundsException(); 375 } 376 synchronized (zsRef) { 377 ensureOpen(); 378 ByteBuffer input = this.input; 379 long result; 380 int inputPos; 381 try { 382 if (input == null) { 383 inputPos = this.inputPos; 384 try { 385 result = inflateBytesBytes(zsRef.address(), 386 inputArray, inputPos, inputLim - inputPos, 387 output, off, len); 388 } catch (DataFormatException e) { 389 this.inputPos = inputPos + inputConsumed; 390 throw e; 391 } 392 } else { 393 inputPos = input.position(); 394 try { 395 int inputRem = Math.max(input.limit() - inputPos, 0); 396 if (input.isDirect()) { 397 try { 398 long inputAddress = ((DirectBuffer) input).address(); 399 result = inflateBufferBytes(zsRef.address(), 400 inputAddress + inputPos, inputRem, 401 output, off, len); 402 } finally { 403 Reference.reachabilityFence(input); 404 } 405 } else { 406 byte[] inputArray = ZipUtils.getBufferArray(input); 407 int inputOffset = ZipUtils.getBufferOffset(input); 408 result = inflateBytesBytes(zsRef.address(), 409 inputArray, inputOffset + inputPos, inputRem, 410 output, off, len); 411 } 412 } catch (DataFormatException e) { 413 input.position(inputPos + inputConsumed); 414 throw e; 415 } 416 } 417 } catch (DataFormatException e) { 418 bytesRead += inputConsumed; 419 inputConsumed = 0; 420 int written = outputConsumed; 421 bytesWritten += written; 422 outputConsumed = 0; 423 throw e; 424 } 425 int read = (int) (result & 0x7fff_ffffL); 426 int written = (int) (result >>> 31 & 0x7fff_ffffL); 427 if ((result >>> 62 & 1) != 0) { 428 finished = true; 429 } 430 if ((result >>> 63 & 1) != 0) { 431 needDict = true; 432 } 433 if (input != null) { 434 input.position(inputPos + read); 435 } else { 436 this.inputPos = inputPos + read; 437 } 438 bytesWritten += written; 439 bytesRead += read; 440 return written; 441 } 442 } 443 444 /** 445 * Uncompresses bytes into specified buffer. Returns actual number 446 * of bytes uncompressed. A return value of 0 indicates that 447 * needsInput() or needsDictionary() should be called in order to 448 * determine if more input data or a preset dictionary is required. 449 * In the latter case, getAdler() can be used to get the Adler-32 450 * value of the dictionary required. 451 * <p> 452 * The {@linkplain #getRemaining() remaining byte count} will be reduced by 453 * the number of consumed input bytes. If the {@link #setInput(ByteBuffer)} 454 * method was called to provide a buffer for input, the input buffer's position 455 * will be advanced the number of consumed bytes. 456 * <p> 457 * These byte totals, as well as 458 * the {@linkplain #getBytesRead() total bytes read} 459 * and the {@linkplain #getBytesWritten() total bytes written} 460 * values, will be updated even in the event that a {@link DataFormatException} 461 * is thrown to reflect the amount of data consumed and produced before the 462 * exception occurred. 463 * 464 * @param output the buffer for the uncompressed data 465 * @return the actual number of uncompressed bytes 466 * @throws DataFormatException if the compressed data format is invalid 467 * @see Inflater#needsInput 468 * @see Inflater#needsDictionary 469 */ 470 public int inflate(byte[] output) throws DataFormatException { 471 return inflate(output, 0, output.length); 472 } 473 474 /** 475 * Uncompresses bytes into specified buffer. Returns actual number 476 * of bytes uncompressed. A return value of 0 indicates that 477 * needsInput() or needsDictionary() should be called in order to 478 * determine if more input data or a preset dictionary is required. 479 * In the latter case, getAdler() can be used to get the Adler-32 480 * value of the dictionary required. 481 * <p> 482 * On success, the position of the given {@code output} byte buffer will be 483 * advanced by as many bytes as were produced by the operation, which is equal 484 * to the number returned by this method. Note that the position of the 485 * {@code output} buffer will be advanced even in the event that a 486 * {@link DataFormatException} is thrown. 487 * <p> 488 * The {@linkplain #getRemaining() remaining byte count} will be reduced by 489 * the number of consumed input bytes. If the {@link #setInput(ByteBuffer)} 490 * method was called to provide a buffer for input, the input buffer's position 491 * will be advanced the number of consumed bytes. 492 * <p> 493 * These byte totals, as well as 494 * the {@linkplain #getBytesRead() total bytes read} 495 * and the {@linkplain #getBytesWritten() total bytes written} 496 * values, will be updated even in the event that a {@link DataFormatException} 497 * is thrown to reflect the amount of data consumed and produced before the 498 * exception occurred. 499 * 500 * @param output the buffer for the uncompressed data 501 * @return the actual number of uncompressed bytes 502 * @throws DataFormatException if the compressed data format is invalid 503 * @throws ReadOnlyBufferException if the given output buffer is read-only 504 * @see Inflater#needsInput 505 * @see Inflater#needsDictionary 506 * @since 11 507 */ 508 public int inflate(ByteBuffer output) throws DataFormatException { 509 if (output.isReadOnly()) { 510 throw new ReadOnlyBufferException(); 511 } 512 synchronized (zsRef) { 513 ensureOpen(); 514 ByteBuffer input = this.input; 515 long result; 516 int inputPos; 517 int outputPos = output.position(); 518 int outputRem = Math.max(output.limit() - outputPos, 0); 519 try { 520 if (input == null) { 521 inputPos = this.inputPos; 522 try { 523 if (output.isDirect()) { 524 long outputAddress = ((DirectBuffer) output).address(); 525 try { 526 result = inflateBytesBuffer(zsRef.address(), 527 inputArray, inputPos, inputLim - inputPos, 528 outputAddress + outputPos, outputRem); 529 } finally { 530 Reference.reachabilityFence(output); 531 } 532 } else { 533 byte[] outputArray = ZipUtils.getBufferArray(output); 534 int outputOffset = ZipUtils.getBufferOffset(output); 535 result = inflateBytesBytes(zsRef.address(), 536 inputArray, inputPos, inputLim - inputPos, 537 outputArray, outputOffset + outputPos, outputRem); 538 } 539 } catch (DataFormatException e) { 540 this.inputPos = inputPos + inputConsumed; 541 throw e; 542 } 543 } else { 544 inputPos = input.position(); 545 int inputRem = Math.max(input.limit() - inputPos, 0); 546 try { 547 if (input.isDirect()) { 548 long inputAddress = ((DirectBuffer) input).address(); 549 try { 550 if (output.isDirect()) { 551 long outputAddress = ((DirectBuffer) output).address(); 552 try { 553 result = inflateBufferBuffer(zsRef.address(), 554 inputAddress + inputPos, inputRem, 555 outputAddress + outputPos, outputRem); 556 } finally { 557 Reference.reachabilityFence(output); 558 } 559 } else { 560 byte[] outputArray = ZipUtils.getBufferArray(output); 561 int outputOffset = ZipUtils.getBufferOffset(output); 562 result = inflateBufferBytes(zsRef.address(), 563 inputAddress + inputPos, inputRem, 564 outputArray, outputOffset + outputPos, outputRem); 565 } 566 } finally { 567 Reference.reachabilityFence(input); 568 } 569 } else { 570 byte[] inputArray = ZipUtils.getBufferArray(input); 571 int inputOffset = ZipUtils.getBufferOffset(input); 572 if (output.isDirect()) { 573 long outputAddress = ((DirectBuffer) output).address(); 574 try { 575 result = inflateBytesBuffer(zsRef.address(), 576 inputArray, inputOffset + inputPos, inputRem, 577 outputAddress + outputPos, outputRem); 578 } finally { 579 Reference.reachabilityFence(output); 580 } 581 } else { 582 byte[] outputArray = ZipUtils.getBufferArray(output); 583 int outputOffset = ZipUtils.getBufferOffset(output); 584 result = inflateBytesBytes(zsRef.address(), 585 inputArray, inputOffset + inputPos, inputRem, 586 outputArray, outputOffset + outputPos, outputRem); 587 } 588 } 589 } catch (DataFormatException e) { 590 input.position(inputPos + inputConsumed); 591 throw e; 592 } 593 } 594 } catch (DataFormatException e) { 595 bytesRead += inputConsumed; 596 inputConsumed = 0; 597 int written = outputConsumed; 598 output.position(outputPos + written); 599 bytesWritten += written; 600 outputConsumed = 0; 601 throw e; 602 } 603 int read = (int) (result & 0x7fff_ffffL); 604 int written = (int) (result >>> 31 & 0x7fff_ffffL); 605 if ((result >>> 62 & 1) != 0) { 606 finished = true; 607 } 608 if ((result >>> 63 & 1) != 0) { 609 needDict = true; 610 } 611 if (input != null) { 612 input.position(inputPos + read); 613 } else { 614 this.inputPos = inputPos + read; 615 } 616 // Note: this method call also serves to keep the byteBuffer ref alive 617 output.position(outputPos + written); 618 bytesWritten += written; 619 bytesRead += read; 620 return written; 621 } 622 } 623 624 /** 625 * Returns the ADLER-32 value of the uncompressed data. 626 * @return the ADLER-32 value of the uncompressed data 627 */ 628 public int getAdler() { 629 synchronized (zsRef) { 630 ensureOpen(); 631 return getAdler(zsRef.address()); 632 } 633 } 634 635 /** 636 * Returns the total number of compressed bytes input so far. 637 * 638 * <p>Since the number of bytes may be greater than 639 * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now 640 * the preferred means of obtaining this information.</p> 641 * 674 /** 675 * Returns the total number of uncompressed bytes output so far. 676 * 677 * @return the total (non-negative) number of uncompressed bytes output so far 678 * @since 1.5 679 */ 680 public long getBytesWritten() { 681 synchronized (zsRef) { 682 ensureOpen(); 683 return bytesWritten; 684 } 685 } 686 687 /** 688 * Resets inflater so that a new set of input data can be processed. 689 */ 690 public void reset() { 691 synchronized (zsRef) { 692 ensureOpen(); 693 reset(zsRef.address()); 694 input = ZipUtils.defaultBuf; 695 inputArray = null; 696 finished = false; 697 needDict = false; 698 bytesRead = bytesWritten = 0; 699 } 700 } 701 702 /** 703 * Closes the decompressor and discards any unprocessed input. 704 * 705 * This method should be called when the decompressor is no longer 706 * being used. Once this method is called, the behavior of the 707 * Inflater object is undefined. 708 */ 709 public void end() { 710 synchronized (zsRef) { 711 zsRef.clean(); 712 input = ZipUtils.defaultBuf; 713 inputArray = null; 714 } 715 } 716 717 /** 718 * Closes the decompressor when garbage is collected. 719 * 720 * @implSpec 721 * If this {@code Inflater} has been subclassed and the {@code end} method 722 * has been overridden, the {@code end} method will be called when the 723 * inflater is unreachable. 724 * 725 * @deprecated The {@code finalize} method has been deprecated and will be 726 * removed. It is implemented as a no-op. Subclasses that override 727 * {@code finalize} in order to perform cleanup should be modified to use 728 * alternative cleanup mechanisms and remove the overriding {@code finalize} 729 * method. The recommended cleanup for compressor is to explicitly call 730 * {@code end} method when it is no longer in use. If the {@code end} is 731 * not invoked explicitly the resource of the compressor will be released 732 * when the instance becomes unreachable, 733 */ 734 @Deprecated(since="9", forRemoval=true) 735 protected void finalize() {} 736 737 private void ensureOpen () { 738 assert Thread.holdsLock(zsRef); 739 if (zsRef.address() == 0) 740 throw new NullPointerException("Inflater has been closed"); 741 } 742 743 private static native void initIDs(); 744 private static native long init(boolean nowrap); 745 private static native void setDictionary(long addr, byte[] b, int off, 746 int len); 747 private static native void setDictionaryBuffer(long addr, long bufAddress, int len); 748 private native long inflateBytesBytes(long addr, 749 byte[] inputArray, int inputOff, int inputLen, 750 byte[] outputArray, int outputOff, int outputLen) throws DataFormatException; 751 private native long inflateBytesBuffer(long addr, 752 byte[] inputArray, int inputOff, int inputLen, 753 long outputAddress, int outputLen) throws DataFormatException; 754 private native long inflateBufferBytes(long addr, 755 long inputAddress, int inputLen, 756 byte[] outputArray, int outputOff, int outputLen) throws DataFormatException; 757 private native long inflateBufferBuffer(long addr, 758 long inputAddress, int inputLen, 759 long outputAddress, int outputLen) throws DataFormatException; 760 private static native int getAdler(long addr); 761 private static native void reset(long addr); 762 private static native void end(long addr); 763 764 /** 765 * A reference to the native zlib's z_stream structure. It also 766 * serves as the "cleaner" to clean up the native resource when 767 * the Inflater is ended, closed or cleaned. 768 */ 769 static class InflaterZStreamRef implements Runnable { 770 771 private long address; 772 private final Cleanable cleanable; 773 774 private InflaterZStreamRef(Inflater owner, long addr) { 775 this.cleanable = (owner != null) ? CleanerFactory.cleaner().register(owner, this) : null; 776 this.address = addr; 777 } 778 779 long address() { |