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