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 /** 29 * This class provides support for general purpose decompression using the 30 * popular ZLIB compression library. The ZLIB compression library was 31 * initially developed as part of the PNG graphics standard and is not 32 * protected by patents. It is fully described in the specifications at 33 * the <a href="package-summary.html#package.description">java.util.zip 34 * package description</a>. 35 * 36 * <p>The following code fragment demonstrates a trivial compression 37 * and decompression of a string using {@code Deflater} and 38 * {@code Inflater}. 39 * 40 * <blockquote><pre> 41 * try { 42 * // Encode a String into bytes 43 * String inputString = "blahblahblah\u20AC\u20AC"; 44 * byte[] input = inputString.getBytes("UTF-8"); 45 * 46 * // Compress the bytes 47 * byte[] output = new byte[100]; 48 * Deflater compresser = new Deflater(); 49 * compresser.setInput(input); 50 * compresser.finish(); 51 * int compressedDataLength = compresser.deflate(output); 52 * 53 * // Decompress the bytes 54 * Inflater decompresser = new Inflater(); 55 * decompresser.setInput(output, 0, compressedDataLength); 56 * byte[] result = new byte[100]; 57 * int resultLength = decompresser.inflate(result); 58 * decompresser.end(); 59 * 60 * // Decode the bytes into a String 61 * String outputString = new String(result, 0, resultLength, "UTF-8"); 62 * } catch(java.io.UnsupportedEncodingException ex) { 63 * // handle 64 * } catch (java.util.zip.DataFormatException ex) { 65 * // handle 66 * } 67 * </pre></blockquote> 68 * 69 * @apiNote 70 * To release resources used by this {@code Inflater}, the {@link #end()} method 71 * should be called explicitly. Subclasses are responsible for the cleanup of resources 72 * acquired by the subclass. Subclasses that override {@link #finalize()} in order 73 * to perform cleanup should be modified to use alternative cleanup mechanisms such 74 * as {@link java.lang.ref.Cleaner} and remove the overriding {@code finalize} method. 75 * 76 * @implSpec 77 * If this {@code Inflater} has been subclassed and the {@code end} method has been 78 * overridden, the {@code end} method will be called by the finalization when the 79 * inflater is unreachable. But the subclasses should not depend on this specific 80 * implementation; the finalization is not reliable and the {@code finalize} method 81 * is deprecated to be removed. 82 * 83 * @see Deflater 84 * @author David Connelly 85 * @since 1.1 86 * 87 */ 88 89 public class Inflater { 90 91 private final ZStreamRef zsRef; 92 private byte[] buf = defaultBuf; 93 private int off, len; 94 private boolean finished; 95 private boolean needDict; 96 private long bytesRead; 97 private long bytesWritten; 98 99 private static final byte[] defaultBuf = new byte[0]; 100 101 static { 102 ZipUtils.loadLibrary(); 103 initIDs(); 104 } 105 106 /** 107 * Creates a new decompressor. If the parameter 'nowrap' is true then 108 * the ZLIB header and checksum fields will not be used. This provides 109 * compatibility with the compression format used by both GZIP and PKZIP. 110 * <p> 111 * Note: When using the 'nowrap' option it is also necessary to provide 112 * an extra "dummy" byte as input. This is required by the ZLIB native 113 * library in order to support certain optimizations. 114 * 115 * @param nowrap if true then support GZIP compatible compression 116 */ 117 public Inflater(boolean nowrap) { 118 this.zsRef = ZStreamRef.get(this, () -> init(nowrap), Inflater::end); 119 } 120 121 /** 122 * Creates a new decompressor. 123 */ 124 public Inflater() { 125 this(false); 126 } 127 128 /** 129 * Sets input data for decompression. Should be called whenever 130 * needsInput() returns true indicating that more input data is 131 * required. 132 * @param b the input data bytes 133 * @param off the start offset of the input data 134 * @param len the length of the input data 135 * @see Inflater#needsInput 136 */ 137 public void setInput(byte[] b, int off, int len) { 138 if (b == null) { 139 throw new NullPointerException(); 140 } 141 if (off < 0 || len < 0 || off > b.length - len) { 142 throw new ArrayIndexOutOfBoundsException(); 143 } 144 synchronized (zsRef) { 145 this.buf = b; 146 this.off = off; 147 this.len = len; 148 } 149 } 150 151 /** 152 * Sets input data for decompression. Should be called whenever 153 * needsInput() returns true indicating that more input data is 154 * required. 155 * @param b the input data bytes 156 * @see Inflater#needsInput 157 */ 158 public void setInput(byte[] b) { 159 setInput(b, 0, b.length); 160 } 161 162 /** 163 * Sets the preset dictionary to the given array of bytes. Should be 164 * called when inflate() returns 0 and needsDictionary() returns true 165 * indicating that a preset dictionary is required. The method getAdler() 166 * can be used to get the Adler-32 value of the dictionary needed. 167 * @param b the dictionary data bytes 168 * @param off the start offset of the data 169 * @param len the length of the data 170 * @see Inflater#needsDictionary 171 * @see Inflater#getAdler 172 */ 173 public void setDictionary(byte[] b, int off, int len) { 174 if (b == null) { 175 throw new NullPointerException(); 176 } 177 if (off < 0 || len < 0 || off > b.length - len) { 178 throw new ArrayIndexOutOfBoundsException(); 179 } 180 synchronized (zsRef) { 181 ensureOpen(); 182 setDictionary(zsRef.address(), b, off, len); 183 needDict = false; 184 } 185 } 186 187 /** 188 * Sets the preset dictionary to the given array of bytes. Should be 189 * called when inflate() returns 0 and needsDictionary() returns true 190 * indicating that a preset dictionary is required. The method getAdler() 191 * can be used to get the Adler-32 value of the dictionary needed. 192 * @param b the dictionary data bytes 193 * @see Inflater#needsDictionary 194 * @see Inflater#getAdler 195 */ 196 public void setDictionary(byte[] b) { 197 setDictionary(b, 0, b.length); 198 } 199 200 /** 201 * Returns the total number of bytes remaining in the input buffer. 202 * This can be used to find out what bytes still remain in the input 203 * buffer after decompression has finished. 204 * @return the total number of bytes remaining in the input buffer 205 */ 206 public int getRemaining() { 207 synchronized (zsRef) { 208 return len; 209 } 210 } 211 212 /** 213 * Returns true if no data remains in the input buffer. This can 214 * be used to determine if #setInput should be called in order 215 * to provide more input. 216 * @return true if no data remains in the input buffer 217 */ 218 public boolean needsInput() { 219 synchronized (zsRef) { 220 return len <= 0; 221 } 222 } 223 224 /** 225 * Returns true if a preset dictionary is needed for decompression. 226 * @return true if a preset dictionary is needed for decompression 227 * @see Inflater#setDictionary 228 */ 229 public boolean needsDictionary() { 230 synchronized (zsRef) { 231 return needDict; 232 } 233 } 234 235 /** 236 * Returns true if the end of the compressed data stream has been 237 * reached. 238 * @return true if the end of the compressed data stream has been 239 * reached 240 */ 241 public boolean finished() { 242 synchronized (zsRef) { 243 return finished; 244 } 245 } 246 247 /** 248 * Uncompresses bytes into specified buffer. Returns actual number 249 * of bytes uncompressed. A return value of 0 indicates that 250 * needsInput() or needsDictionary() should be called in order to 251 * determine if more input data or a preset dictionary is required. 252 * In the latter case, getAdler() can be used to get the Adler-32 253 * value of the dictionary required. 254 * @param b the buffer for the uncompressed data 255 * @param off the start offset of the data 256 * @param len the maximum number of uncompressed bytes 257 * @return the actual number of uncompressed bytes 258 * @exception DataFormatException if the compressed data format is invalid 259 * @see Inflater#needsInput 260 * @see Inflater#needsDictionary 261 */ 262 public int inflate(byte[] b, int off, int len) 263 throws DataFormatException 264 { 265 if (b == null) { 266 throw new NullPointerException(); 267 } 268 if (off < 0 || len < 0 || off > b.length - len) { 269 throw new ArrayIndexOutOfBoundsException(); 270 } 271 synchronized (zsRef) { 272 ensureOpen(); 273 int thisLen = this.len; 274 int n = inflateBytes(zsRef.address(), b, off, len); 275 bytesWritten += n; 276 bytesRead += (thisLen - this.len); 277 return n; 278 } 279 } 280 281 /** 282 * Uncompresses bytes into specified buffer. Returns actual number 283 * of bytes uncompressed. A return value of 0 indicates that 284 * needsInput() or needsDictionary() should be called in order to 285 * determine if more input data or a preset dictionary is required. 286 * In the latter case, getAdler() can be used to get the Adler-32 287 * value of the dictionary required. 288 * @param b the buffer for the uncompressed data 289 * @return the actual number of uncompressed bytes 290 * @exception DataFormatException if the compressed data format is invalid 291 * @see Inflater#needsInput 292 * @see Inflater#needsDictionary 293 */ 294 public int inflate(byte[] b) throws DataFormatException { 295 return inflate(b, 0, b.length); 296 } 297 298 /** 299 * Returns the ADLER-32 value of the uncompressed data. 300 * @return the ADLER-32 value of the uncompressed data 301 */ 302 public int getAdler() { 303 synchronized (zsRef) { 304 ensureOpen(); 305 return getAdler(zsRef.address()); 306 } 307 } 308 309 /** 310 * Returns the total number of compressed bytes input so far. 311 * 312 * <p>Since the number of bytes may be greater than 313 * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now 314 * the preferred means of obtaining this information.</p> 315 * 316 * @return the total number of compressed bytes input so far 317 */ 318 public int getTotalIn() { 319 return (int) getBytesRead(); 320 } 321 322 /** 323 * Returns the total number of compressed bytes input so far. 324 * 325 * @return the total (non-negative) number of compressed bytes input so far 326 * @since 1.5 327 */ 328 public long getBytesRead() { 329 synchronized (zsRef) { 330 ensureOpen(); 331 return bytesRead; 332 } 333 } 334 335 /** 336 * Returns the total number of uncompressed bytes output so far. 337 * 338 * <p>Since the number of bytes may be greater than 339 * Integer.MAX_VALUE, the {@link #getBytesWritten()} method is now 340 * the preferred means of obtaining this information.</p> 341 * 342 * @return the total number of uncompressed bytes output so far 343 */ 344 public int getTotalOut() { 345 return (int) getBytesWritten(); 346 } 347 348 /** 349 * Returns the total number of uncompressed bytes output so far. 350 * 351 * @return the total (non-negative) number of uncompressed bytes output so far 352 * @since 1.5 353 */ 354 public long getBytesWritten() { 355 synchronized (zsRef) { 356 ensureOpen(); 357 return bytesWritten; 358 } 359 } 360 361 /** 362 * Resets inflater so that a new set of input data can be processed. 363 */ 364 public void reset() { 365 synchronized (zsRef) { 366 ensureOpen(); 367 reset(zsRef.address()); 368 buf = defaultBuf; 369 finished = false; 370 needDict = false; 371 off = len = 0; 372 bytesRead = bytesWritten = 0; 373 } 374 } 375 376 /** 377 * Closes the decompressor and discards any unprocessed input. 378 * 379 * This method should be called when the decompressor is no longer 380 * being used. Once this method is called, the behavior of the 381 * Inflater object is undefined. 382 */ 383 public void end() { 384 synchronized (zsRef) { 385 zsRef.clean(); 386 buf = null; 387 } 388 } 389 390 /** 391 * Closes the decompressor when garbage is collected. 392 * 393 * @implSpec 394 * If this {@code Inflater} has been subclassed and the {@code end} method 395 * has been overridden, the {@code end} method will be called when the 396 * inflater is unreachable. 397 * 398 * @deprecated The {@code finalize} method has been deprecated and will be 399 * removed. It is implemented as a no-op. Subclasses that override 400 * {@code finalize} in order to perform cleanup should be modified to use 401 * alternative cleanup mechanisms and remove the overriding {@code finalize} 402 * method. The recommended cleanup for compressor is to explicitly call 403 * {@code end} method when it is no longer in use. If the {@code end} is 404 * not invoked explicitly the resource of the compressor will be released 405 * when the instance becomes unreachable, 406 */ 407 @Deprecated(since="9", forRemoval=true) 408 protected void finalize() {} 409 410 private void ensureOpen () { 411 assert Thread.holdsLock(zsRef); 412 if (zsRef.address() == 0) 413 throw new NullPointerException("Inflater has been closed"); 414 } 415 416 boolean ended() { 417 synchronized (zsRef) { 418 return zsRef.address() == 0; 419 } 420 } 421 422 private static native void initIDs(); 423 private static native long init(boolean nowrap); 424 private static native void setDictionary(long addr, byte[] b, int off, 425 int len); 426 private native int inflateBytes(long addr, byte[] b, int off, int len) 427 throws DataFormatException; 428 private static native int getAdler(long addr); 429 private static native void reset(long addr); 430 private static native void end(long addr); 431 }