Coverage Report - org.apache.tapestry.util.io.CompressedDataEncoder
 
Classes in this File Line Coverage Branch Coverage Complexity
CompressedDataEncoder
0%
0/33
0%
0/16
6.333
 
 1  
 package org.apache.tapestry.util.io;
 2  
 
 3  
 import org.apache.commons.codec.binary.Base64;
 4  
 import org.apache.hivemind.ApplicationRuntimeException;
 5  
 import org.apache.hivemind.HiveMind;
 6  
 import org.apache.hivemind.util.Defense;
 7  
 
 8  
 import java.io.*;
 9  
 import java.util.zip.GZIPInputStream;
 10  
 import java.util.zip.GZIPOutputStream;
 11  
 
 12  
 /**
 13  
  * Utility class used by {@link org.apache.tapestry.IRequestCycle} to compress {@link org.apache.tapestry.util.IdAllocator}
 14  
  * state.
 15  
  */
 16  
 public class CompressedDataEncoder {
 17  
 
 18  
     /**
 19  
      * Prefix on the MIME encoding that indicates that the encoded data is not encoded.
 20  
      */
 21  
 
 22  
     public static final String BYTESTREAM_PREFIX = "B";
 23  
 
 24  
     /**
 25  
      * Prefix on the MIME encoding that indicates that the encoded data is encoded with GZIP.
 26  
      */
 27  
 
 28  
     public static final String GZIP_BYTESTREAM_PREFIX = "Z";
 29  
 
 30  0
     private CompressedDataEncoder() {}
 31  
 
 32  
     /**
 33  
      * Encodes the given string into a compressed string representation that can later be decoded.
 34  
      *
 35  
      * @param input
 36  
      *          String input to compress and encode into a persistable form.
 37  
      *
 38  
      * @return encoded string (possibly empty, but not null)
 39  
      */
 40  
     public static String encodeString(String input)
 41  
     {
 42  0
         Defense.notNull(input, "input");
 43  
 
 44  0
         if (HiveMind.isBlank(input))
 45  0
             return "";
 46  
 
 47  
         try {
 48  0
             ByteArrayOutputStream bosPlain = new ByteArrayOutputStream();
 49  0
             ByteArrayOutputStream bosCompressed = new ByteArrayOutputStream();
 50  
 
 51  0
             GZIPOutputStream gos = new GZIPOutputStream(bosCompressed);
 52  0
             TeeOutputStream tos = new TeeOutputStream(bosPlain, gos);
 53  0
             ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(tos));
 54  
             
 55  0
             oos.writeUTF(input);
 56  
             
 57  0
             oos.close();
 58  
 
 59  0
             boolean useCompressed = bosCompressed.size() < bosPlain.size();
 60  
 
 61  0
             byte[] data = useCompressed ? bosCompressed.toByteArray() : bosPlain.toByteArray();
 62  
             
 63  0
             byte[] encoded = Base64.encodeBase64(data);
 64  
 
 65  0
             String prefix = useCompressed ? GZIP_BYTESTREAM_PREFIX : BYTESTREAM_PREFIX;
 66  
 
 67  0
             return prefix + new String(encoded);
 68  
         }
 69  0
         catch (Exception ex) {
 70  0
             throw new ApplicationRuntimeException(IoMessages.encodeFailure(input, ex), ex);
 71  
         }
 72  
     }
 73  
 
 74  
     /**
 75  
      * Takes a string with an encoded and compressed input as produced by {@link #encodeString(String)} , and converts it back
 76  
      * into the original String representation.
 77  
      *
 78  
      * @param input
 79  
      *          The data to un-encode, which should be equivalent to the same that
 80  
      *          was passed in to {@link #encodeString(String)}.
 81  
      *
 82  
      * @return The decoded string data.
 83  
      */
 84  
     public static String decodeString(String input)
 85  
     {
 86  0
         if (HiveMind.isBlank(input))
 87  0
             return "";
 88  
 
 89  0
         String prefix = input.substring(0, 1);
 90  
 
 91  0
         if (!(prefix.equals(BYTESTREAM_PREFIX) || prefix.equals(GZIP_BYTESTREAM_PREFIX)))
 92  0
             throw new ApplicationRuntimeException(IoMessages.unknownPrefix(prefix));
 93  
 
 94  
         try {
 95  
             // Strip off the prefix, feed that in as a MIME stream.
 96  
 
 97  0
             byte[] decoded = Base64.decodeBase64(input.substring(1).getBytes());
 98  
 
 99  0
             InputStream is = new ByteArrayInputStream(decoded);
 100  
 
 101  0
             if (prefix.equals(GZIP_BYTESTREAM_PREFIX))
 102  0
                 is = new GZIPInputStream(is);
 103  
 
 104  
             // I believe this is more efficient; the buffered input stream should ask the
 105  
             // GZIP stream for large blocks of un-gzipped bytes, with should be more efficient.
 106  
             // The object input stream will probably be looking for just a few bytes at
 107  
             // a time. We use a resolving object input stream that knows how to find
 108  
             // classes not normally acessible.
 109  
 
 110  0
             ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(is));
 111  
             
 112  0
             String result = ois.readUTF();
 113  
 
 114  0
             is.close();
 115  
 
 116  0
             return result;
 117  
         }
 118  0
         catch (Exception ex) {
 119  0
             throw new ApplicationRuntimeException(IoMessages.decodeFailure(ex), ex);
 120  
         }
 121  
     }
 122  
 }