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