Coverage Report - org.apache.tapestry5.internal.gzip.BufferedGZipOutputStream
 
Classes in this File Line Coverage Branch Coverage Complexity
BufferedGZipOutputStream
84%
31/37
100%
14/14
0
 
 1  
 // Copyright 2009 The Apache Software Foundation
 2  
 //
 3  
 // Licensed under the Apache License, Version 2.0 (the "License");
 4  
 // you may not use this file except in compliance with the License.
 5  
 // You may obtain a copy of the License at
 6  
 //
 7  
 //     http://www.apache.org/licenses/LICENSE-2.0
 8  
 //
 9  
 // Unless required by applicable law or agreed to in writing, software
 10  
 // distributed under the License is distributed on an "AS IS" BASIS,
 11  
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12  
 // See the License for the specific language governing permissions and
 13  
 // limitations under the License.
 14  
 
 15  
 package org.apache.tapestry5.internal.gzip;
 16  
 
 17  
 import org.apache.tapestry5.internal.InternalConstants;
 18  
 import org.apache.tapestry5.services.ResponseCompressionAnalyzer;
 19  
 
 20  
 import javax.servlet.ServletOutputStream;
 21  
 import javax.servlet.http.HttpServletResponse;
 22  
 import java.io.BufferedOutputStream;
 23  
 import java.io.ByteArrayOutputStream;
 24  
 import java.io.IOException;
 25  
 import java.io.OutputStream;
 26  
 import java.util.zip.GZIPOutputStream;
 27  
 
 28  
 /**
 29  
  * A buffered output stream that, when a certain number of bytes is buffered (the cutover point) will open a compressed
 30  
  * stream (via {@link org.apache.tapestry5.services.Response#getOutputStream(String)}
 31  
  */
 32  
 public class BufferedGZipOutputStream extends ServletOutputStream
 33  
 {
 34  
     private final String contentType;
 35  
 
 36  
     private final HttpServletResponse response;
 37  
 
 38  
     private final ResponseCompressionAnalyzer analyzer;
 39  
 
 40  
     private final int cutover;
 41  
 
 42  
     private ByteArrayOutputStream byteArrayOutputStream;
 43  
 
 44  
     /**
 45  
      * Initially the ByteArrayOutputStream, later the response output stream (possibly wrapped with a
 46  
      * GZIPOutputStream).
 47  
      */
 48  
     private OutputStream currentOutputStream;
 49  
 
 50  
     public BufferedGZipOutputStream(String contentType, HttpServletResponse response, int cutover,
 51  
                                     ResponseCompressionAnalyzer analyzer)
 52  1088
     {
 53  1088
         this.contentType = contentType;
 54  1088
         this.response = response;
 55  1088
         this.cutover = cutover;
 56  1088
         this.analyzer = analyzer;
 57  
 
 58  1088
         byteArrayOutputStream = new ByteArrayOutputStream(cutover);
 59  
 
 60  1088
         currentOutputStream = byteArrayOutputStream;
 61  1088
     }
 62  
 
 63  
     private void checkForCutover() throws IOException
 64  
     {
 65  2316
         if (byteArrayOutputStream == null) return;
 66  
 
 67  1088
         if (byteArrayOutputStream.size() < cutover) return;
 68  
 
 69  
         // Time to switch over to GZIP.
 70  1060
         openResponseOutputStream(true);
 71  1060
     }
 72  
 
 73  
     private void openResponseOutputStream(boolean gzip) throws IOException
 74  
     {
 75  1088
         OutputStream responseOutputStream = response.getOutputStream();
 76  
 
 77  1088
         boolean useCompression = gzip && analyzer.isCompressable(contentType);
 78  
 
 79  1088
         OutputStream possiblyCompressed = useCompression
 80  
                                           ? new GZIPOutputStream(responseOutputStream)
 81  
                                           : responseOutputStream;
 82  
 
 83  1088
         if (useCompression)
 84  1042
             response.setHeader(InternalConstants.CONTENT_ENCODING_HEADER, InternalConstants.GZIP_CONTENT_ENCODING);
 85  
 
 86  1088
         currentOutputStream =
 87  
                 new BufferedOutputStream(possiblyCompressed);
 88  
 
 89  
         // Write what content we already have to the new stream.
 90  
 
 91  1088
         byteArrayOutputStream.writeTo(currentOutputStream);
 92  
 
 93  1088
         byteArrayOutputStream = null;
 94  1088
     }
 95  
 
 96  
     public void write(int b) throws IOException
 97  
     {
 98  0
         currentOutputStream.write(b);
 99  
 
 100  0
         checkForCutover();
 101  0
     }
 102  
 
 103  
     @Override
 104  
     public void write(byte[] b) throws IOException
 105  
     {
 106  0
         currentOutputStream.write(b);
 107  
 
 108  0
         checkForCutover();
 109  0
     }
 110  
 
 111  
     @Override
 112  
     public void write(byte[] b, int off, int len) throws IOException
 113  
     {
 114  2316
         currentOutputStream.write(b, off, len);
 115  
 
 116  2316
         checkForCutover();
 117  2316
     }
 118  
 
 119  
     @Override
 120  
     public void flush() throws IOException
 121  
     {
 122  10
         forceOutputStream().flush();
 123  10
     }
 124  
 
 125  
     @Override
 126  
     public void close() throws IOException
 127  
     {
 128  
         // When closing, if we haven't accumulated enough output yet to start compressing,
 129  
         // then send what we have, uncompressed.
 130  
 
 131  1078
         forceOutputStream().close();
 132  1078
     }
 133  
 
 134  
     private OutputStream forceOutputStream() throws IOException
 135  
     {
 136  1088
         if (byteArrayOutputStream != null)
 137  28
             openResponseOutputStream(false);
 138  
 
 139  1088
         return currentOutputStream;
 140  
     }
 141  
 }