1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. Oracle designates this 9 * particular file as subject to the "Classpath" exception as provided 10 * by Oracle in the LICENSE file that accompanied this code. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 */ 26 27 package java.util.zip; 28 29 import dalvik.annotation.optimization.ReachabilitySensitive; 30 import dalvik.system.CloseGuard; 31 32 /** 33 * This class provides support for general purpose decompression using the 34 * popular ZLIB compression library. The ZLIB compression library was 35 * initially developed as part of the PNG graphics standard and is not 36 * protected by patents. It is fully described in the specifications at 37 * the <a href="package-summary.html#package_description">java.util.zip 38 * package description</a>. 39 * 40 * <p>The following code fragment demonstrates a trivial compression 41 * and decompression of a string using <tt>Deflater</tt> and 42 * <tt>Inflater</tt>. 43 * 44 * <blockquote><pre> 45 * try { 46 * // Encode a String into bytes 47 * String inputString = "blahblahblah\u20AC\u20AC"; 48 * byte[] input = inputString.getBytes("UTF-8"); 49 * 50 * // Compress the bytes 51 * byte[] output = new byte[100]; 52 * Deflater compresser = new Deflater(); 53 * compresser.setInput(input); 54 * compresser.finish(); 55 * int compressedDataLength = compresser.deflate(output); 56 * 57 * // Decompress the bytes 58 * Inflater decompresser = new Inflater(); 59 * decompresser.setInput(output, 0, compressedDataLength); 60 * byte[] result = new byte[100]; 61 * int resultLength = decompresser.inflate(result); 62 * decompresser.end(); 63 * 64 * // Decode the bytes into a String 65 * String outputString = new String(result, 0, resultLength, "UTF-8"); 66 * } catch(java.io.UnsupportedEncodingException ex) { 67 * // handle 68 * } catch (java.util.zip.DataFormatException ex) { 69 * // handle 70 * } 71 * </pre></blockquote> 72 * 73 * @see Deflater 74 * @author David Connelly 75 * 76 */ 77 public 78 class Inflater { 79 80 // Android-added: @ReachabilitySensitive 81 // Finalization clears zsRef, and thus can't be allowed to occur early. 82 // Unlike some other CloseGuard uses, the spec allows clients to rely on finalization 83 // here. Thus dropping a deflater without calling end() should work correctly. 84 // It thus does not suffice to just rely on the CloseGuard annotation. 85 @ReachabilitySensitive 86 private final ZStreamRef zsRef; 87 private byte[] buf = defaultBuf; 88 private int off, len; 89 private boolean finished; 90 private boolean needDict; 91 private long bytesRead; 92 private long bytesWritten; 93 94 // Android-added: CloseGuard support. 95 @ReachabilitySensitive 96 private final CloseGuard guard = CloseGuard.get(); 97 98 private static final byte[] defaultBuf = new byte[0]; 99 100 // Android-removed: initIDs handled in register method. 101 /* 102 static { 103 /* Zip library is loaded from System.initializeSystemClass * 104 initIDs(); 105 } 106 */ 107 108 /** 109 * Creates a new decompressor. If the parameter 'nowrap' is true then 110 * the ZLIB header and checksum fields will not be used. This provides 111 * compatibility with the compression format used by both GZIP and PKZIP. 112 * <p> 113 * Note: When using the 'nowrap' option it is also necessary to provide 114 * an extra "dummy" byte as input. This is required by the ZLIB native 115 * library in order to support certain optimizations. 116 * 117 * @param nowrap if true then support GZIP compatible compression 118 */ Inflater(boolean nowrap)119 public Inflater(boolean nowrap) { 120 zsRef = new ZStreamRef(init(nowrap)); 121 // Android-added: CloseGuard support. 122 guard.open("end"); 123 } 124 125 /** 126 * Creates a new decompressor. 127 */ Inflater()128 public Inflater() { 129 this(false); 130 } 131 132 /** 133 * Sets input data for decompression. Should be called whenever 134 * needsInput() returns true indicating that more input data is 135 * required. 136 * @param b the input data bytes 137 * @param off the start offset of the input data 138 * @param len the length of the input data 139 * @see Inflater#needsInput 140 */ setInput(byte[] b, int off, int len)141 public void setInput(byte[] b, int off, int len) { 142 if (b == null) { 143 throw new NullPointerException(); 144 } 145 if (off < 0 || len < 0 || off > b.length - len) { 146 throw new ArrayIndexOutOfBoundsException(); 147 } 148 synchronized (zsRef) { 149 this.buf = b; 150 this.off = off; 151 this.len = len; 152 } 153 } 154 155 /** 156 * Sets input data for decompression. Should be called whenever 157 * needsInput() returns true indicating that more input data is 158 * required. 159 * @param b the input data bytes 160 * @see Inflater#needsInput 161 */ setInput(byte[] b)162 public void setInput(byte[] b) { 163 setInput(b, 0, b.length); 164 } 165 166 /** 167 * Sets the preset dictionary to the given array of bytes. Should be 168 * called when inflate() returns 0 and needsDictionary() returns true 169 * indicating that a preset dictionary is required. The method getAdler() 170 * can be used to get the Adler-32 value of the dictionary needed. 171 * @param b the dictionary data bytes 172 * @param off the start offset of the data 173 * @param len the length of the data 174 * @see Inflater#needsDictionary 175 * @see Inflater#getAdler 176 */ setDictionary(byte[] b, int off, int len)177 public void setDictionary(byte[] b, int off, int len) { 178 if (b == null) { 179 throw new NullPointerException(); 180 } 181 if (off < 0 || len < 0 || off > b.length - len) { 182 throw new ArrayIndexOutOfBoundsException(); 183 } 184 synchronized (zsRef) { 185 ensureOpen(); 186 setDictionary(zsRef.address(), b, off, len); 187 needDict = false; 188 } 189 } 190 191 /** 192 * Sets the preset dictionary to the given array of bytes. Should be 193 * called when inflate() returns 0 and needsDictionary() returns true 194 * indicating that a preset dictionary is required. The method getAdler() 195 * can be used to get the Adler-32 value of the dictionary needed. 196 * @param b the dictionary data bytes 197 * @see Inflater#needsDictionary 198 * @see Inflater#getAdler 199 */ setDictionary(byte[] b)200 public void setDictionary(byte[] b) { 201 setDictionary(b, 0, b.length); 202 } 203 204 /** 205 * Returns the total number of bytes remaining in the input buffer. 206 * This can be used to find out what bytes still remain in the input 207 * buffer after decompression has finished. 208 * @return the total number of bytes remaining in the input buffer 209 */ getRemaining()210 public int getRemaining() { 211 synchronized (zsRef) { 212 return len; 213 } 214 } 215 216 /** 217 * Returns true if no data remains in the input buffer. This can 218 * be used to determine if #setInput should be called in order 219 * to provide more input. 220 * @return true if no data remains in the input buffer 221 */ needsInput()222 public boolean needsInput() { 223 synchronized (zsRef) { 224 return len <= 0; 225 } 226 } 227 228 /** 229 * Returns true if a preset dictionary is needed for decompression. 230 * @return true if a preset dictionary is needed for decompression 231 * @see Inflater#setDictionary 232 */ needsDictionary()233 public boolean needsDictionary() { 234 synchronized (zsRef) { 235 return needDict; 236 } 237 } 238 239 /** 240 * Returns true if the end of the compressed data stream has been 241 * reached. 242 * @return true if the end of the compressed data stream has been 243 * reached 244 */ finished()245 public boolean finished() { 246 synchronized (zsRef) { 247 return finished; 248 } 249 } 250 251 /** 252 * Uncompresses bytes into specified buffer. Returns actual number 253 * of bytes uncompressed. A return value of 0 indicates that 254 * needsInput() or needsDictionary() should be called in order to 255 * determine if more input data or a preset dictionary is required. 256 * In the latter case, getAdler() can be used to get the Adler-32 257 * value of the dictionary required. 258 * @param b the buffer for the uncompressed data 259 * @param off the start offset of the data 260 * @param len the maximum number of uncompressed bytes 261 * @return the actual number of uncompressed bytes 262 * @exception DataFormatException if the compressed data format is invalid 263 * @see Inflater#needsInput 264 * @see Inflater#needsDictionary 265 */ inflate(byte[] b, int off, int len)266 public int inflate(byte[] b, int off, int len) 267 throws DataFormatException 268 { 269 if (b == null) { 270 throw new NullPointerException(); 271 } 272 if (off < 0 || len < 0 || off > b.length - len) { 273 throw new ArrayIndexOutOfBoundsException(); 274 } 275 synchronized (zsRef) { 276 ensureOpen(); 277 int thisLen = this.len; 278 int n = inflateBytes(zsRef.address(), b, off, len); 279 bytesWritten += n; 280 bytesRead += (thisLen - this.len); 281 return n; 282 } 283 } 284 285 /** 286 * Uncompresses bytes into specified buffer. Returns actual number 287 * of bytes uncompressed. A return value of 0 indicates that 288 * needsInput() or needsDictionary() should be called in order to 289 * determine if more input data or a preset dictionary is required. 290 * In the latter case, getAdler() can be used to get the Adler-32 291 * value of the dictionary required. 292 * @param b the buffer for the uncompressed data 293 * @return the actual number of uncompressed bytes 294 * @exception DataFormatException if the compressed data format is invalid 295 * @see Inflater#needsInput 296 * @see Inflater#needsDictionary 297 */ inflate(byte[] b)298 public int inflate(byte[] b) throws DataFormatException { 299 return inflate(b, 0, b.length); 300 } 301 302 /** 303 * Returns the ADLER-32 value of the uncompressed data. 304 * @return the ADLER-32 value of the uncompressed data 305 */ getAdler()306 public int getAdler() { 307 synchronized (zsRef) { 308 ensureOpen(); 309 return getAdler(zsRef.address()); 310 } 311 } 312 313 /** 314 * Returns the total number of compressed bytes input so far. 315 * 316 * <p>Since the number of bytes may be greater than 317 * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now 318 * the preferred means of obtaining this information.</p> 319 * 320 * @return the total number of compressed bytes input so far 321 */ getTotalIn()322 public int getTotalIn() { 323 return (int) getBytesRead(); 324 } 325 326 /** 327 * Returns the total number of compressed bytes input so far. 328 * 329 * @return the total (non-negative) number of compressed bytes input so far 330 * @since 1.5 331 */ getBytesRead()332 public long getBytesRead() { 333 synchronized (zsRef) { 334 ensureOpen(); 335 return bytesRead; 336 } 337 } 338 339 /** 340 * Returns the total number of uncompressed bytes output so far. 341 * 342 * <p>Since the number of bytes may be greater than 343 * Integer.MAX_VALUE, the {@link #getBytesWritten()} method is now 344 * the preferred means of obtaining this information.</p> 345 * 346 * @return the total number of uncompressed bytes output so far 347 */ getTotalOut()348 public int getTotalOut() { 349 return (int) getBytesWritten(); 350 } 351 352 /** 353 * Returns the total number of uncompressed bytes output so far. 354 * 355 * @return the total (non-negative) number of uncompressed bytes output so far 356 * @since 1.5 357 */ getBytesWritten()358 public long getBytesWritten() { 359 synchronized (zsRef) { 360 ensureOpen(); 361 return bytesWritten; 362 } 363 } 364 365 /** 366 * Resets inflater so that a new set of input data can be processed. 367 */ reset()368 public void reset() { 369 synchronized (zsRef) { 370 ensureOpen(); 371 reset(zsRef.address()); 372 buf = defaultBuf; 373 finished = false; 374 needDict = false; 375 off = len = 0; 376 bytesRead = bytesWritten = 0; 377 } 378 } 379 380 /** 381 * Closes the decompressor and discards any unprocessed input. 382 * This method should be called when the decompressor is no longer 383 * being used, but will also be called automatically by the finalize() 384 * method. Once this method is called, the behavior of the Inflater 385 * object is undefined. 386 */ end()387 public void end() { 388 synchronized (zsRef) { 389 // Android-added: CloseGuard support. 390 guard.close(); 391 392 long addr = zsRef.address(); 393 zsRef.clear(); 394 if (addr != 0) { 395 end(addr); 396 buf = null; 397 } 398 } 399 } 400 401 /** 402 * Closes the decompressor when garbage is collected. 403 */ finalize()404 protected void finalize() { 405 // Android-added: CloseGuard support. 406 if (guard != null) { 407 guard.warnIfOpen(); 408 } 409 410 end(); 411 } 412 ensureOpen()413 private void ensureOpen () { 414 assert Thread.holdsLock(zsRef); 415 if (zsRef.address() == 0) 416 throw new NullPointerException("Inflater has been closed"); 417 } 418 ended()419 boolean ended() { 420 synchronized (zsRef) { 421 return zsRef.address() == 0; 422 } 423 } 424 425 // Android-changed: initIDs handled in register method. 426 // private native static void initIDs(); init(boolean nowrap)427 private native static long init(boolean nowrap); setDictionary(long addr, byte[] b, int off, int len)428 private native static void setDictionary(long addr, byte[] b, int off, 429 int len); inflateBytes(long addr, byte[] b, int off, int len)430 private native int inflateBytes(long addr, byte[] b, int off, int len) 431 throws DataFormatException; getAdler(long addr)432 private native static int getAdler(long addr); reset(long addr)433 private native static void reset(long addr); end(long addr)434 private native static void end(long addr); 435 } 436