1d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden// Copyright 2015 Google Inc. All rights reserved. 2d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden// 3d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden// Licensed under the Apache License, Version 2.0 (the "License"); 4d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden// you may not use this file except in compliance with the License. 5d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden// You may obtain a copy of the License at 6d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden// 7d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden// http://www.apache.org/licenses/LICENSE-2.0 8d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden// 9d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden// Unless required by applicable law or agreed to in writing, software 10d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden// distributed under the License is distributed on an "AS IS" BASIS, 11d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden// See the License for the specific language governing permissions and 13d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden// limitations under the License. 14d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden 15d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Haydenpackage com.google.archivepatcher.shared; 16d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden 17d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Haydenimport java.io.IOException; 18d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Haydenimport java.io.InputStream; 19d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Haydenimport java.io.OutputStream; 20d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Haydenimport java.util.zip.Deflater; 21d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Haydenimport java.util.zip.DeflaterOutputStream; 22d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden 23d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden/** 24d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * Implementation of {@link Compressor} based on Java's built-in {@link Deflater}. Uses default 25d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * compression, the default strategy, and no-wrap by default along with a 32k read buffer and a 32k 26d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * write buffer. Buffers are allocated on-demand and discarded after use. 27d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden */ 28d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Haydenpublic class DeflateCompressor implements Compressor { 29d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden 30d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden /** 31d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * The compression level to use. Defaults to {@link Deflater#DEFAULT_COMPRESSION}. 32d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden */ 33d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden private int compressionLevel = Deflater.DEFAULT_COMPRESSION; 34d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden 35d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden /** 36d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * The compression strategy to use. Defaults to {@link Deflater#DEFAULT_STRATEGY}. 37d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden */ 38d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden private int strategy = Deflater.DEFAULT_STRATEGY; 39d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden 40d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden /** 41d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * Whether or not to suppress wrapping the deflate output with the 42d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * standard zlib header and checksum fields. Defaults to true. 43d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden */ 44d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden private boolean nowrap = true; 45d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden 46d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden /** 47d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * The size of the buffer used for reading data in during 48d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * {@link #compress(InputStream, OutputStream)}. 49d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden */ 50d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden private int inputBufferSize = 32768; 51d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden 52d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden /** 53d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * The size of the buffer used for writing data out during 54d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * {@link #compress(InputStream, OutputStream)}. 55d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden */ 56d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden private int outputBufferSize = 32768; 57d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden 58d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden /** 59d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * Cached {@link Deflater} to be used. 60d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden */ 61d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden private Deflater deflater = null; 62d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden 63d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden /** 64d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * Whether or not to cache {@link Deflater} instances, which is a major performance tradeoff. 65d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden */ 66d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden private boolean caching = false; 67d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden 68d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden /** 69d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * Returns whether or not to suppress wrapping the deflate output with the standard zlib header 70d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * and checksum fields. 71d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * @return the value 72d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * @see Deflater#Deflater(int, boolean) 73d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden */ 74d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden public boolean isNowrap() { 75d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden return nowrap; 76d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden } 77d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden 78d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden /** 79d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * Sets whether or not to suppress wrapping the deflate output with the standard zlib header and 80d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * checksum fields. Defaults to false. 81d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * @param nowrap see {@link Deflater#Deflater(int, boolean)} 82d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden */ 83d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden public void setNowrap(boolean nowrap) { 84d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden if (nowrap != this.nowrap) { 85d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden release(); // Cannot re-use the deflater any more. 86d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden this.nowrap = nowrap; 87d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden } 88d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden } 89d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden 90d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden /** 91d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * Returns the compression level that will be used, in the range 0-9. 92d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * @return the level 93d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden */ 94d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden public int getCompressionLevel() { 95d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden return compressionLevel; 96d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden } 97d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden 98d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden /** 99d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * Sets the compression level to be used. Defaults to {@link Deflater#BEST_COMPRESSION}. 100d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * @param compressionLevel the level, in the range 0-9 101d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden */ 102d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden public void setCompressionLevel(int compressionLevel) { 103d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden if (compressionLevel < 0 || compressionLevel > 9) { 104d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden throw new IllegalArgumentException( 105d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden "compressionLevel must be in the range [0,9]: " + compressionLevel); 106d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden } 107d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden if (deflater != null && compressionLevel != this.compressionLevel) { 108d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden deflater.reset(); 109ec0fc6394e5abd1dbd47fe58d2988b997bac60dcAndrew Hayden deflater.setLevel(compressionLevel); 110d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden } 111d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden this.compressionLevel = compressionLevel; 112d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden } 113d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden 114d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden /** 115d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * Returns the strategy that will be used, from {@link Deflater}. 116d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * @return the strategy 117d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden */ 118d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden public int getStrategy() { 119d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden return strategy; 120d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden } 121d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden 122d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden /** 123d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * Sets the strategy that will be used. Valid values can be found in {@link Deflater}. Defaults to 124d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * {@link Deflater#DEFAULT_STRATEGY} 125d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * @param strategy the strategy to be used 126d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden */ 127d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden public void setStrategy(int strategy) { 128d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden if (deflater != null && strategy != this.strategy) { 129d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden deflater.reset(); 130ec0fc6394e5abd1dbd47fe58d2988b997bac60dcAndrew Hayden deflater.setStrategy(strategy); 131d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden } 132d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden this.strategy = strategy; 133d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden } 134d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden 135d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden /** 136d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * Returns the size of the buffer used for reading from the input stream in 137d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * {@link #compress(InputStream, OutputStream)}. 138d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * @return the size (default is 32768) 139d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden */ 140d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden public int getInputBufferSize() { 141d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden return inputBufferSize; 142d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden } 143d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden 144d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden /** 145d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * Sets the size of the buffer used for reading from the input stream in 146d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * {@link #compress(InputStream, OutputStream)}. 147d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * @param inputBufferSize the size to set (default is 32768) 148d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden */ 149d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden public void setInputBufferSize(int inputBufferSize) { 150d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden this.inputBufferSize = inputBufferSize; 151d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden } 152d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden 153d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden /** 154d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * Returns the size of the buffer used for writing to the output stream in 155d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * {@link #compress(InputStream, OutputStream)}. 156d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * @return the size (default is 32768) 157d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden */ 158d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden public int getOutputBufferSize() { 159d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden return outputBufferSize; 160d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden } 161d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden 162d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden /** 163d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * Sets the size of the buffer used for writing to the output stream in 164d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * {@link #compress(InputStream, OutputStream)}. 165d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * NB: {@link Deflater} uses an <em>internal</em> buffer and this method adjusts the size of that 166d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * buffer. This buffer is important for performance, <em>even if the {@link OutputStream} is 167d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * is already buffered</em>. 168d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * @param outputBufferSize the size to set (default is 32768) 169d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden */ 170d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden public void setOutputBufferSize(int outputBufferSize) { 171d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden this.outputBufferSize = outputBufferSize; 172d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden } 173d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden 174d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden /** 175d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * Returns if caching is enabled. 176d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * @return true if enabled, otherwise false 177d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * @see #setCaching(boolean) 178d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden */ 179d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden public boolean isCaching() { 180d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden return caching; 181d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden } 182d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden 183d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden /** 184d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * Sets whether or not to cache the {@link Deflater} instance. Defaults to false. If set to true, 185d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * the {@link Deflater} is kept until this object is finalized or until {@link #release()} is 186d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * called. Instances of {@link Deflater} can be surprisingly expensive, so caching is advised in 187d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * situations where many resources need to be deflated. 188d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * @param caching whether to enable caching 189d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden */ 190d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden public void setCaching(boolean caching) { 191d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden this.caching = caching; 192d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden } 193d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden 194d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden /** 195d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * Returns the {@link Deflater} to be used, creating a new one if necessary and caching it for 196d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * future use. 197d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * @return the deflater 198d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden */ 199d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden protected Deflater createOrResetDeflater() { 200d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden Deflater result = deflater; 201d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden if (result == null) { 202d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden result = new Deflater(compressionLevel, nowrap); 203d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden result.setStrategy(strategy); 204d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden if (caching) { 205d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden deflater = result; 206d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden } 207d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden } else { 208d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden result.reset(); 209d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden } 210d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden return result; 211d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden } 212d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden 213d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden /** 214d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * Immediately releases any cached {@link Deflater} instance. 215d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden */ 216d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden public void release() { 217d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden if (deflater != null) { 218d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden deflater.end(); 219d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden deflater = null; 220d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden } 221d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden } 222d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden 223d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden @Override 224d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden public void compress(InputStream uncompressedIn, OutputStream compressedOut) throws IOException { 225d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden byte[] buffer = new byte[inputBufferSize]; 226d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden DeflaterOutputStream deflaterOut = 227d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden new DeflaterOutputStream(compressedOut, createOrResetDeflater(), outputBufferSize); 228d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden int numRead = 0; 229d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden while ((numRead = uncompressedIn.read(buffer)) >= 0) { 230d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden deflaterOut.write(buffer, 0, numRead); 231d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden } 232d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden deflaterOut.finish(); 233d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden deflaterOut.flush(); 234d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden } 235d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden} 236