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