001package org.apache.commons.jcs.utils.zip;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import org.apache.commons.logging.Log;
023import org.apache.commons.logging.LogFactory;
024
025import java.io.ByteArrayInputStream;
026import java.io.ByteArrayOutputStream;
027import java.io.IOException;
028import java.util.zip.DataFormatException;
029import java.util.zip.Deflater;
030import java.util.zip.GZIPInputStream;
031import java.util.zip.Inflater;
032
033/** Compress / Decompress. */
034public final class CompressionUtil
035{
036    /** The logger */
037    private static final Log log = LogFactory.getLog( CompressionUtil.class );
038
039    /**
040     * no instances.
041     */
042    private CompressionUtil()
043    {
044        // NO OP
045    }
046
047    /**
048     * Decompress the byte array passed using a default buffer length of 1024.
049     * <p>
050     * @param input compressed byte array webservice response
051     * @return uncompressed byte array
052     */
053    public static byte[] decompressByteArray( final byte[] input )
054    {
055        return decompressByteArray( input, 1024 );
056    }
057
058    /**
059     * Decompress the byte array passed
060     * <p>
061     * @param input compressed byte array webservice response
062     * @param bufferLength buffer length
063     * @return uncompressed byte array
064     */
065    public static byte[] decompressByteArray( final byte[] input, final int bufferLength )
066    {
067        if ( null == input )
068        {
069            throw new IllegalArgumentException( "Input was null" );
070        }
071
072        // Create the decompressor and give it the data to compress
073        final Inflater decompressor = new Inflater();
074
075        decompressor.setInput( input );
076
077        // Create an expandable byte array to hold the decompressed data
078        final ByteArrayOutputStream baos = new ByteArrayOutputStream( input.length );
079
080        // Decompress the data
081        final byte[] buf = new byte[bufferLength];
082
083        try
084        {
085            while ( !decompressor.finished() )
086            {
087                int count = decompressor.inflate( buf );
088                baos.write( buf, 0, count );
089            }
090        }
091        catch ( DataFormatException ex )
092        {
093            log.error( "Problem decompressing.", ex );
094        }
095
096        decompressor.end();
097
098        try
099        {
100            baos.close();
101        }
102        catch ( IOException ex )
103        {
104            log.error( "Problem closing stream.", ex );
105        }
106
107        return baos.toByteArray();
108    }
109
110    /**
111     * Compress the byte array passed
112     * <p>
113     * @param input byte array
114     * @return compressed byte array
115     * @throws IOException thrown if we can't close the output stream
116     */
117    public static byte[] compressByteArray( byte[] input )
118        throws IOException
119    {
120        return compressByteArray( input, 1024 );
121    }
122
123    /**
124     * Compress the byte array passed
125     * <p>
126     * @param input byte array
127     * @param bufferLength buffer length
128     * @return compressed byte array
129     * @throws IOException thrown if we can't close the output stream
130     */
131    public static byte[] compressByteArray( byte[] input, int bufferLength )
132        throws IOException
133    {
134        // Compressor with highest level of compression
135        Deflater compressor = new Deflater();
136        compressor.setLevel( Deflater.BEST_COMPRESSION );
137
138        // Give the compressor the data to compress
139        compressor.setInput( input );
140        compressor.finish();
141
142        // Create an expandable byte array to hold the compressed data.
143        // It is not necessary that the compressed data will be smaller than
144        // the uncompressed data.
145        ByteArrayOutputStream bos = new ByteArrayOutputStream( input.length );
146
147        // Compress the data
148        byte[] buf = new byte[bufferLength];
149        while ( !compressor.finished() )
150        {
151            int count = compressor.deflate( buf );
152            bos.write( buf, 0, count );
153        }
154
155        // JCS-136 ( Details here : http://www.devguli.com/blog/eng/java-deflater-and-outofmemoryerror/ )
156        compressor.end();
157        bos.close();
158
159        // Get the compressed data
160        return bos.toByteArray();
161
162    }
163
164    /**
165     * decompress a gzip byte array, using a default buffer length of 1024
166     * <p>
167     * @param compressedByteArray gzip-compressed byte array
168     * @return decompressed byte array
169     * @throws IOException thrown if there was a failure to construct the GzipInputStream
170     */
171    public static byte[] decompressGzipByteArray( byte[] compressedByteArray )
172        throws IOException
173    {
174        return decompressGzipByteArray( compressedByteArray, 1024 );
175    }
176
177    /**
178     * decompress a gzip byte array, using a default buffer length of 1024
179     * <p>
180     * @param compressedByteArray gzip-compressed byte array
181     * @param bufferlength size of the buffer in bytes
182     * @return decompressed byte array
183     * @throws IOException thrown if there was a failure to construct the GzipInputStream
184     */
185    public static byte[] decompressGzipByteArray( byte[] compressedByteArray, int bufferlength )
186        throws IOException
187    {
188        ByteArrayOutputStream uncompressedStream = new ByteArrayOutputStream();
189
190        GZIPInputStream compressedStream = new GZIPInputStream( new ByteArrayInputStream( compressedByteArray ) );
191
192        byte[] buffer = new byte[bufferlength];
193
194        int index = -1;
195
196        while ( ( index = compressedStream.read( buffer ) ) != -1 )
197        {
198            uncompressedStream.write( buffer, 0, index );
199        }
200
201        return uncompressedStream.toByteArray();
202    }
203}