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