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}