View Javadoc

1   /*
2   * Licensed to the Apache Software Foundation (ASF) under one or more
3   * contributor license agreements.  See the NOTICE file distributed with
4   * this work for additional information regarding copyright ownership.
5   * The ASF licenses this file to You under the Apache License, Version 2.0
6   * (the "License"); you may not use this file except in compliance with
7   * the License.  You may obtain a copy of the License at
8   *
9   *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17  
18  package compressionFilters;
19  
20  import java.io.IOException;
21  import java.io.OutputStreamWriter;
22  import java.io.PrintWriter;
23  
24  import javax.servlet.ServletOutputStream;
25  import javax.servlet.http.HttpServletResponse;
26  import javax.servlet.http.HttpServletResponseWrapper;
27  
28  /**
29   * Implementation of <b>HttpServletResponseWrapper</b> that works with
30   * the CompressionServletResponseStream implementation..
31   *
32   * @author Amy Roh
33   * @author Dmitri Valdin
34   * @version $Revision: 664175 $, $Date: 2008-06-06 18:43:44 -0400 (Fri, 06 Jun 2008) $
35   */
36  
37  public class CompressionServletResponseWrapper extends HttpServletResponseWrapper {
38  
39      // ----------------------------------------------------- Constructor
40  
41      /**
42       * Calls the parent constructor which creates a ServletResponse adaptor
43       * wrapping the given response object.
44       */
45  
46      public CompressionServletResponseWrapper(HttpServletResponse response) {
47          super(response);
48          origResponse = response;
49          if (debug > 1) {
50              System.out.println("CompressionServletResponseWrapper constructor gets called");
51          }
52      }
53  
54      // ----------------------------------------------------- Instance Variables
55  
56      /**
57       * Original response
58       */
59  
60      protected HttpServletResponse origResponse = null;
61  
62      /**
63       * Descriptive information about this Response implementation.
64       */
65  
66      protected static final String info = "CompressionServletResponseWrapper";
67  
68      /**
69       * The ServletOutputStream that has been returned by
70       * <code>getOutputStream()</code>, if any.
71       */
72  
73      protected ServletOutputStream stream = null;
74  
75  
76      /**
77       * The PrintWriter that has been returned by
78       * <code>getWriter()</code>, if any.
79       */
80  
81      protected PrintWriter writer = null;
82  
83      /**
84       * The threshold number to compress
85       */
86      protected int threshold = 0;
87  
88      /**
89       * Debug level
90       */
91      private int debug = 0;
92  
93      /**
94       * Content type
95       */
96      protected String contentType = null;
97  
98      // --------------------------------------------------------- Public Methods
99  
100 
101     /**
102      * Set content type
103      */
104     public void setContentType(String contentType) {
105         if (debug > 1) {
106             System.out.println("setContentType to " + contentType);
107         }
108         this.contentType = contentType;
109         origResponse.setContentType(contentType);
110     }
111 
112 
113     /**
114      * Set threshold number
115      */
116     public void setCompressionThreshold(int threshold) {
117         if (debug > 1) {
118             System.out.println("setCompressionThreshold to " + threshold);
119         }
120         this.threshold = threshold;
121     }
122 
123 
124     /**
125      * Set debug level
126      */
127     public void setDebugLevel(int debug) {
128         this.debug = debug;
129     }
130 
131 
132     /**
133      * Create and return a ServletOutputStream to write the content
134      * associated with this Response.
135      *
136      * @throws IOException if an input/output error occurs
137      */
138     public ServletOutputStream createOutputStream() throws IOException {
139         if (debug > 1) {
140             System.out.println("createOutputStream gets called");
141         }
142 
143         CompressionResponseStream stream = new CompressionResponseStream(origResponse);
144         stream.setDebugLevel(debug);
145         stream.setBuffer(threshold);
146 
147         return stream;
148 
149     }
150 
151 
152     /**
153      * Finish a response.
154      */
155     public void finishResponse() {
156         try {
157             if (writer != null) {
158                 writer.close();
159             } else {
160                 if (stream != null)
161                     stream.close();
162             }
163         } catch (IOException e) {
164         }
165     }
166 
167     // ------------------------------------------------ ServletResponse Methods
168 
169 
170     /**
171      * Flush the buffer and commit this response.
172      *
173      * @throws IOException if an input/output error occurs
174      */
175     public void flushBuffer() throws IOException {
176         if (debug > 1) {
177             System.out.println("flush buffer @ CompressionServletResponseWrapper");
178         }
179         ((CompressionResponseStream) stream).flush();
180 
181     }
182 
183     /**
184      * Return the servlet output stream associated with this Response.
185      *
186      * @throws IllegalStateException if <code>getWriter</code> has
187      *                               already been called for this response
188      * @throws IOException           if an input/output error occurs
189      */
190     public ServletOutputStream getOutputStream() throws IOException {
191 
192         if (writer != null)
193             throw new IllegalStateException("getWriter() has already been called for this response");
194 
195         if (stream == null)
196             stream = createOutputStream();
197         if (debug > 1) {
198             System.out.println("stream is set to " + stream + " in getOutputStream");
199         }
200 
201         return (stream);
202 
203     }
204 
205     /**
206      * Return the writer associated with this Response.
207      *
208      * @throws IllegalStateException if <code>getOutputStream</code> has
209      *                               already been called for this response
210      * @throws IOException           if an input/output error occurs
211      */
212     public PrintWriter getWriter() throws IOException {
213 
214         if (writer != null)
215             return (writer);
216 
217         if (stream != null)
218             throw new IllegalStateException("getOutputStream() has already been called for this response");
219 
220         stream = createOutputStream();
221         if (debug > 1) {
222             System.out.println("stream is set to " + stream + " in getWriter");
223         }
224         //String charset = getCharsetFromContentType(contentType);
225         String charEnc = origResponse.getCharacterEncoding();
226         if (debug > 1) {
227             System.out.println("character encoding is " + charEnc);
228         }
229         // HttpServletResponse.getCharacterEncoding() shouldn't return null
230         // according the spec, so feel free to remove that "if"
231         if (charEnc != null) {
232             writer = new PrintWriter(new OutputStreamWriter(stream, charEnc));
233         } else {
234             writer = new PrintWriter(stream);
235         }
236 
237         return (writer);
238 
239     }
240 
241 
242     public void setContentLength(int length) {
243     }
244 
245 
246     /**
247      * Returns character from content type. This method was taken from tomcat.
248      *
249      * @author rajo
250      */
251     private static String getCharsetFromContentType(String type) {
252 
253         if (type == null) {
254             return null;
255         }
256         int semi = type.indexOf(";");
257         if (semi == -1) {
258             return null;
259         }
260         String afterSemi = type.substring(semi + 1);
261         int charsetLocation = afterSemi.indexOf("charset=");
262         if (charsetLocation == -1) {
263             return null;
264         } else {
265             String afterCharset = afterSemi.substring(charsetLocation + 8);
266             String encoding = afterCharset.trim();
267             return encoding;
268         }
269     }
270 
271 }