1 /* 2 * Copyright (c) 1996, 2010, 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 compression 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 <tt>Deflater</tt> and 38 * <tt>Inflater</tt>. 39 * 40 * <blockquote><pre> 41 * try { 42 * // Encode a String into bytes 43 * String inputString = "blahblahblah"; 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 * compresser.end(); 53 * 54 * // Decompress the bytes 55 * Inflater decompresser = new Inflater(); 56 * decompresser.setInput(output, 0, compressedDataLength); 57 * byte[] result = new byte[100]; 58 * int resultLength = decompresser.inflate(result); 59 * decompresser.end(); 60 * 61 * // Decode the bytes into a String 62 * String outputString = new String(result, 0, resultLength, "UTF-8"); 63 * } catch(java.io.UnsupportedEncodingException ex) { 64 * // handle 65 * } catch (java.util.zip.DataFormatException ex) { 66 * // handle 67 * } 68 * </pre></blockquote> 69 * 70 * @see Inflater 71 * @author David Connelly 72 */ 73 public 74 class Deflater { 75 76 private final ZStreamRef zsRef; 77 private byte[] buf = new byte[0]; 78 private int off, len; 79 private int level, strategy; 80 private boolean setParams; 81 private boolean finish, finished; 82 83 /** 84 * Compression method for the deflate algorithm (the only one currently 85 * supported). 86 */ 87 public static final int DEFLATED = 8; 88 89 /** 90 * Compression level for no compression. 91 */ 92 public static final int NO_COMPRESSION = 0; 93 94 /** 95 * Compression level for fastest compression. 96 */ 97 public static final int BEST_SPEED = 1; 98 99 /** 100 * Compression level for best compression. 101 */ 102 public static final int BEST_COMPRESSION = 9; 103 104 /** 105 * Default compression level. 106 */ 107 public static final int DEFAULT_COMPRESSION = -1; 108 109 /** 110 * Compression strategy best used for data consisting mostly of small 111 * values with a somewhat random distribution. Forces more Huffman coding 112 * and less string matching. 113 */ 114 public static final int FILTERED = 1; 115 116 /** 117 * Compression strategy for Huffman coding only. 118 */ 119 public static final int HUFFMAN_ONLY = 2; 120 121 /** 122 * Default compression strategy. 123 */ 124 public static final int DEFAULT_STRATEGY = 0; 125 126 /** 127 * Compression flush mode used to achieve best compression result. 128 * 129 * @see Deflater#deflate(byte[], int, int, int) 130 * @since 1.7 131 */ 132 public static final int NO_FLUSH = 0; 133 134 /** 135 * Compression flush mode used to flush out all pending output; may 136 * degrade compression for some compression algorithms. 137 * 138 * @see Deflater#deflate(byte[], int, int, int) 139 * @since 1.7 140 */ 141 public static final int SYNC_FLUSH = 2; 142 143 /** 144 * Compression flush mode used to flush out all pending output and 145 * reset the deflater. Using this mode too often can seriously degrade 146 * compression. 147 * 148 * @see Deflater#deflate(byte[], int, int, int) 149 * @since 1.7 150 */ 151 public static final int FULL_FLUSH = 3; 152 153 static { 154 /* Zip library is loaded from System.initializeSystemClass */ 155 initIDs(); 156 } 157 158 /** 159 * Creates a new compressor using the specified compression level. 160 * If 'nowrap' is true then the ZLIB header and checksum fields will 161 * not be used in order to support the compression format used in 162 * both GZIP and PKZIP. 163 * @param level the compression level (0-9) 164 * @param nowrap if true then use GZIP compatible compression 165 */ 166 public Deflater(int level, boolean nowrap) { 167 this.level = level; 168 this.strategy = DEFAULT_STRATEGY; 169 this.zsRef = new ZStreamRef(init(level, DEFAULT_STRATEGY, nowrap)); 170 } 171 172 /** 173 * Creates a new compressor using the specified compression level. 174 * Compressed data will be generated in ZLIB format. 175 * @param level the compression level (0-9) 176 */ 177 public Deflater(int level) { 178 this(level, false); 179 } 180 181 /** 182 * Creates a new compressor with the default compression level. 183 * Compressed data will be generated in ZLIB format. 184 */ 185 public Deflater() { 186 this(DEFAULT_COMPRESSION, false); 187 } 188 189 /** 190 * Sets input data for compression. This should be called whenever 191 * needsInput() returns true indicating that more input data is required. 192 * @param b the input data bytes 193 * @param off the start offset of the data 194 * @param len the length of the data 195 * @see Deflater#needsInput 196 */ 197 public void setInput(byte[] b, int off, int len) { 198 if (b== null) { 199 throw new NullPointerException(); 200 } 201 if (off < 0 || len < 0 || off > b.length - len) { 202 throw new ArrayIndexOutOfBoundsException(); 203 } 204 synchronized (zsRef) { 205 this.buf = b; 206 this.off = off; 207 this.len = len; 208 } 209 } 210 211 /** 212 * Sets input data for compression. This should be called whenever 213 * needsInput() returns true indicating that more input data is required. 214 * @param b the input data bytes 215 * @see Deflater#needsInput 216 */ 217 public void setInput(byte[] b) { 218 setInput(b, 0, b.length); 219 } 220 221 /** 222 * Sets preset dictionary for compression. A preset dictionary is used 223 * when the history buffer can be predetermined. When the data is later 224 * uncompressed with Inflater.inflate(), Inflater.getAdler() can be called 225 * in order to get the Adler-32 value of the dictionary required for 226 * decompression. 227 * @param b the dictionary data bytes 228 * @param off the start offset of the data 229 * @param len the length of the data 230 * @see Inflater#inflate 231 * @see Inflater#getAdler 232 */ 233 public void setDictionary(byte[] b, int off, int len) { 234 if (b == null) { 235 throw new NullPointerException(); 236 } 237 if (off < 0 || len < 0 || off > b.length - len) { 238 throw new ArrayIndexOutOfBoundsException(); 239 } 240 synchronized (zsRef) { 241 ensureOpen(); 242 setDictionary(zsRef.address(), b, off, len); 243 } 244 } 245 246 /** 247 * Sets preset dictionary for compression. A preset dictionary is used 248 * when the history buffer can be predetermined. When the data is later 249 * uncompressed with Inflater.inflate(), Inflater.getAdler() can be called 250 * in order to get the Adler-32 value of the dictionary required for 251 * decompression. 252 * @param b the dictionary data bytes 253 * @see Inflater#inflate 254 * @see Inflater#getAdler 255 */ 256 public void setDictionary(byte[] b) { 257 setDictionary(b, 0, b.length); 258 } 259 260 /** 261 * Sets the compression strategy to the specified value. 262 * @param strategy the new compression strategy 263 * @exception IllegalArgumentException if the compression strategy is 264 * invalid 265 */ 266 public void setStrategy(int strategy) { 267 switch (strategy) { 268 case DEFAULT_STRATEGY: 269 case FILTERED: 270 case HUFFMAN_ONLY: 271 break; 272 default: 273 throw new IllegalArgumentException(); 274 } 275 synchronized (zsRef) { 276 if (this.strategy != strategy) { 277 this.strategy = strategy; 278 setParams = true; 279 } 280 } 281 } 282 283 /** 284 * Sets the current compression level to the specified value. 285 * @param level the new compression level (0-9) 286 * @exception IllegalArgumentException if the compression level is invalid 287 */ 288 public void setLevel(int level) { 289 if ((level < 0 || level > 9) && level != DEFAULT_COMPRESSION) { 290 throw new IllegalArgumentException("invalid compression level"); 291 } 292 synchronized (zsRef) { 293 if (this.level != level) { 294 this.level = level; 295 setParams = true; 296 } 297 } 298 } 299 300 /** 301 * Returns true if the input data buffer is empty and setInput() 302 * should be called in order to provide more input. 303 * @return true if the input data buffer is empty and setInput() 304 * should be called in order to provide more input 305 */ 306 public boolean needsInput() { 307 return len <= 0; 308 } 309 310 /** 311 * When called, indicates that compression should end with the current 312 * contents of the input buffer. 313 */ 314 public void finish() { 315 synchronized (zsRef) { 316 finish = true; 317 } 318 } 319 320 /** 321 * Returns true if the end of the compressed data output stream has 322 * been reached. 323 * @return true if the end of the compressed data output stream has 324 * been reached 325 */ 326 public boolean finished() { 327 synchronized (zsRef) { 328 return finished; 329 } 330 } 331 332 /** 333 * Compresses the input data and fills specified buffer with compressed 334 * data. Returns actual number of bytes of compressed data. A return value 335 * of 0 indicates that {@link #needsInput() needsInput} should be called 336 * in order to determine if more input data is required. 337 * 338 * <p>This method uses {@link #NO_FLUSH} as its compression flush mode. 339 * An invocation of this method of the form {@code deflater.deflate(b, off, len)} 340 * yields the same result as the invocation of 341 * {@code deflater.deflate(b, off, len, Deflater.NO_FLUSH)}. 342 * 343 * @param b the buffer for the compressed data 344 * @param off the start offset of the data 345 * @param len the maximum number of bytes of compressed data 346 * @return the actual number of bytes of compressed data written to the 347 * output buffer 348 */ 349 public int deflate(byte[] b, int off, int len) { 350 return deflate(b, off, len, NO_FLUSH); 351 } 352 353 /** 354 * Compresses the input data and fills specified buffer with compressed 355 * data. Returns actual number of bytes of compressed data. A return value 356 * of 0 indicates that {@link #needsInput() needsInput} should be called 357 * in order to determine if more input data is required. 358 * 359 * <p>This method uses {@link #NO_FLUSH} as its compression flush mode. 360 * An invocation of this method of the form {@code deflater.deflate(b)} 361 * yields the same result as the invocation of 362 * {@code deflater.deflate(b, 0, b.length, Deflater.NO_FLUSH)}. 363 * 364 * @param b the buffer for the compressed data 365 * @return the actual number of bytes of compressed data written to the 366 * output buffer 367 */ 368 public int deflate(byte[] b) { 369 return deflate(b, 0, b.length, NO_FLUSH); 370 } 371 372 /** 373 * Compresses the input data and fills the specified buffer with compressed 374 * data. Returns actual number of bytes of data compressed. 375 * 376 * <p>Compression flush mode is one of the following three modes: 377 * 378 * <ul> 379 * <li>{@link #NO_FLUSH}: allows the deflater to decide how much data 380 * to accumulate, before producing output, in order to achieve the best 381 * compression (should be used in normal use scenario). A return value 382 * of 0 in this flush mode indicates that {@link #needsInput()} should 383 * be called in order to determine if more input data is required. 384 * 385 * <li>{@link #SYNC_FLUSH}: all pending output in the deflater is flushed, 386 * to the specified output buffer, so that an inflater that works on 387 * compressed data can get all input data available so far (In particular 388 * the {@link #needsInput()} returns {@code true} after this invocation 389 * if enough output space is provided). Flushing with {@link #SYNC_FLUSH} 390 * may degrade compression for some compression algorithms and so it 391 * should be used only when necessary. 392 * 393 * <li>{@link #FULL_FLUSH}: all pending output is flushed out as with 394 * {@link #SYNC_FLUSH}. The compression state is reset so that the inflater 395 * that works on the compressed output data can restart from this point 396 * if previous compressed data has been damaged or if random access is 397 * desired. Using {@link #FULL_FLUSH} too often can seriously degrade 398 * compression. 399 * </ul> 400 * 401 * <p>In the case of {@link #FULL_FLUSH} or {@link #SYNC_FLUSH}, if 402 * the return value is {@code len}, the space available in output 403 * buffer {@code b}, this method should be invoked again with the same 404 * {@code flush} parameter and more output space. 405 * 406 * @param b the buffer for the compressed data 407 * @param off the start offset of the data 408 * @param len the maximum number of bytes of compressed data 409 * @param flush the compression flush mode 410 * @return the actual number of bytes of compressed data written to 411 * the output buffer 412 * 413 * @throws IllegalArgumentException if the flush mode is invalid 414 * @since 1.7 415 */ 416 public int deflate(byte[] b, int off, int len, int flush) { 417 if (b == null) { 418 throw new NullPointerException(); 419 } 420 if (off < 0 || len < 0 || off > b.length - len) { 421 throw new ArrayIndexOutOfBoundsException(); 422 } 423 synchronized (zsRef) { 424 ensureOpen(); 425 if (flush == NO_FLUSH || flush == SYNC_FLUSH || 426 flush == FULL_FLUSH) 427 return deflateBytes(zsRef.address(), b, off, len, flush); 428 throw new IllegalArgumentException(); 429 } 430 } 431 432 /** 433 * Returns the ADLER-32 value of the uncompressed data. 434 * @return the ADLER-32 value of the uncompressed data 435 */ 436 public int getAdler() { 437 synchronized (zsRef) { 438 ensureOpen(); 439 return getAdler(zsRef.address()); 440 } 441 } 442 443 /** 444 * Returns the total number of uncompressed bytes input so far. 445 * 446 * <p>Since the number of bytes may be greater than 447 * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now 448 * the preferred means of obtaining this information.</p> 449 * 450 * @return the total number of uncompressed bytes input so far 451 */ 452 public int getTotalIn() { 453 return (int) getBytesRead(); 454 } 455 456 /** 457 * Returns the total number of uncompressed bytes input so far.</p> 458 * 459 * @return the total (non-negative) number of uncompressed bytes input so far 460 * @since 1.5 461 */ 462 public long getBytesRead() { 463 synchronized (zsRef) { 464 ensureOpen(); 465 return getBytesRead(zsRef.address()); 466 } 467 } 468 469 /** 470 * Returns the total number of compressed bytes output so far. 471 * 472 * <p>Since the number of bytes may be greater than 473 * Integer.MAX_VALUE, the {@link #getBytesWritten()} method is now 474 * the preferred means of obtaining this information.</p> 475 * 476 * @return the total number of compressed bytes output so far 477 */ 478 public int getTotalOut() { 479 return (int) getBytesWritten(); 480 } 481 482 /** 483 * Returns the total number of compressed bytes output so far.</p> 484 * 485 * @return the total (non-negative) number of compressed bytes output so far 486 * @since 1.5 487 */ 488 public long getBytesWritten() { 489 synchronized (zsRef) { 490 ensureOpen(); 491 return getBytesWritten(zsRef.address()); 492 } 493 } 494 495 /** 496 * Resets deflater so that a new set of input data can be processed. 497 * Keeps current compression level and strategy settings. 498 */ 499 public void reset() { 500 synchronized (zsRef) { 501 ensureOpen(); 502 reset(zsRef.address()); 503 finish = false; 504 finished = false; 505 off = len = 0; 506 } 507 } 508 509 /** 510 * Closes the compressor and discards any unprocessed input. 511 * This method should be called when the compressor is no longer 512 * being used, but will also be called automatically by the 513 * finalize() method. Once this method is called, the behavior 514 * of the Deflater object is undefined. 515 */ 516 public void end() { 517 synchronized (zsRef) { 518 long addr = zsRef.address(); 519 zsRef.clear(); 520 if (addr != 0) { 521 end(addr); 522 buf = null; 523 } 524 } 525 } 526 527 /** 528 * Closes the compressor when garbage is collected. 529 */ 530 protected void finalize() { 531 end(); 532 } 533 534 private void ensureOpen() { 535 assert Thread.holdsLock(zsRef); 536 if (zsRef.address() == 0) 537 throw new NullPointerException("Deflater has been closed"); 538 } 539 540 private static native void initIDs(); 541 private native static long init(int level, int strategy, boolean nowrap); 542 private native static void setDictionary(long addr, byte[] b, int off, int len); 543 private native int deflateBytes(long addr, byte[] b, int off, int len, 544 int flush); 545 private native static int getAdler(long addr); 546 private native static long getBytesRead(long addr); 547 private native static long getBytesWritten(long addr); 548 private native static void reset(long addr); 549 private native static void end(long addr); 550 }