View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.util.compression;
8   
9   import java.io.ByteArrayInputStream;
10  import java.io.IOException;
11  import java.util.zip.GZIPInputStream;
12  import java.util.zip.GZIPOutputStream;
13  
14  import org.apache.commons.io.IOUtils;
15  import org.apache.commons.io.output.ByteArrayOutputStream;
16  import org.apache.commons.logging.Log;
17  import org.apache.commons.logging.LogFactory;
18  
19  /**
20   * <code>GZipCompression</code> is a CompressionStrategy implementation using the
21   * GZip library included in the JDK java.util.zip. This is the default
22   * CompressionStrategy used by the CompressionHelper discovery when no other
23   * implementation is discovered.
24   */
25  public class GZipCompression implements CompressionStrategy
26  {
27      public static final int DEFAULT_BUFFER_SIZE = 32768;
28      
29      /**
30       * The logger for this class
31       */
32      private static final Log logger = LogFactory.getLog(GZipCompression.class);
33  
34      /**
35       * Determines if a byte array is compressed. The java.util.zip GZip
36       * implementaiton does not expose the GZip header so it is difficult to determine
37       * if a string is compressed.
38       * 
39       * @param bytes an array of bytes
40       * @return true if the array is compressed or false otherwise
41       * @throws java.io.IOException if the byte array couldn't be read
42       */
43      public boolean isCompressed(byte[] bytes) throws IOException
44      {
45          if ((bytes == null) || (bytes.length < 2))
46          {
47              return false;
48          }
49          else
50          {
51              return ((bytes[0] == (byte) (GZIPInputStream.GZIP_MAGIC)) && (bytes[1] == (byte) (GZIPInputStream.GZIP_MAGIC >> 8)));
52          }
53      }
54  
55      /**
56       * Used for compressing a byte array into a new byte array using GZIP
57       * 
58       * @param bytes An array of bytes to compress
59       * @return a compressed byte array
60       * @throws java.io.IOException if it fails to write to a GZIPOutputStream
61       * @see java.util.zip.GZIPOutputStream
62       */
63      public byte[] compressByteArray(byte[] bytes) throws IOException
64      {
65          // TODO add strict behaviour as option
66          if (bytes == null || isCompressed(bytes))
67          {
68              // nothing to compress
69              if (logger.isDebugEnabled())
70              {
71                  logger.debug("Data already compressed; doing nothing");
72              }
73              return bytes;
74          }
75  
76          if (logger.isDebugEnabled())
77          {
78              logger.debug("Compressing message of size: " + bytes.length);
79          }
80  
81          ByteArrayOutputStream baos = null;
82          GZIPOutputStream gzos = null;
83  
84          try
85          {
86              baos = new ByteArrayOutputStream(DEFAULT_BUFFER_SIZE);
87              gzos = new GZIPOutputStream(baos);
88  
89              gzos.write(bytes, 0, bytes.length);
90              gzos.finish();
91              gzos.close();
92  
93              byte[] compressedByteArray = baos.toByteArray();
94              baos.close();
95  
96              if (logger.isDebugEnabled())
97              {
98                  logger.debug("Compressed message to size: " + compressedByteArray.length);
99              }
100 
101             return compressedByteArray;
102         }
103         catch (IOException ioex)
104         {
105             throw ioex;
106         }
107         finally
108         {
109             IOUtils.closeQuietly(gzos);
110             IOUtils.closeQuietly(baos);
111         }
112     }
113 
114     /**
115      * Used for uncompressing a byte array into a uncompressed byte array using GZIP
116      * 
117      * @param bytes An array of bytes to uncompress
118      * @return an uncompressed byte array
119      * @throws java.io.IOException if it fails to read from a GZIPInputStream
120      * @see java.util.zip.GZIPInputStream
121      */
122     public byte[] uncompressByteArray(byte[] bytes) throws IOException
123     {
124         // TODO add strict behaviour as option
125         if (!isCompressed(bytes))
126         {
127             /*
128              * if (strict) { // throw a specific exception here to allow users of
129              * this method to // diffientiate between general IOExceptions and an
130              * invalid format logger.warn("Data is not of type GZIP compressed." + "
131              * The data may not have been compressed in the first place."); throw new
132              * CompressionException("Not in GZIP format"); }
133              */
134 
135             // nothing to uncompress
136             if (logger.isDebugEnabled())
137             {
138                 logger.debug("Data already uncompressed; doing nothing");
139             }
140             return bytes;
141         }
142 
143         if (logger.isDebugEnabled())
144         {
145             logger.debug("Uncompressing message of size: " + bytes.length);
146         }
147 
148         ByteArrayInputStream bais = null;
149         GZIPInputStream gzis = null;
150         ByteArrayOutputStream baos = null;
151 
152         try
153         {
154             bais = new ByteArrayInputStream(bytes);
155             gzis = new GZIPInputStream(bais);
156             baos = new ByteArrayOutputStream(DEFAULT_BUFFER_SIZE);
157 
158             IOUtils.copy(gzis, baos);
159             gzis.close();
160             bais.close();
161 
162             byte[] uncompressedByteArray = baos.toByteArray();
163             baos.close();
164 
165             if (logger.isDebugEnabled())
166             {
167                 logger.debug("Uncompressed message to size: " + uncompressedByteArray.length);
168             }
169 
170             return uncompressedByteArray;
171         }
172         catch (IOException ioex)
173         {
174             throw ioex;
175         }
176         finally
177         {
178             IOUtils.closeQuietly(gzis);
179             IOUtils.closeQuietly(bais);
180             IOUtils.closeQuietly(baos);
181         }
182     }
183 
184 }