001    /*
002    * Licensed to the Apache Software Foundation (ASF) under one or more
003    * contributor license agreements.  See the NOTICE file distributed with
004    * this work for additional information regarding copyright ownership.
005    * The ASF licenses this file to You under the Apache License, Version 2.0
006    * (the "License"); you may not use this file except in compliance with
007    * the License.  You may obtain a copy of the License at
008    *
009    *     http://www.apache.org/licenses/LICENSE-2.0
010    *
011    * Unless required by applicable law or agreed to in writing, software
012    * distributed under the License is distributed on an "AS IS" BASIS,
013    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014    * See the License for the specific language governing permissions and
015    * limitations under the License.
016    */
017    
018    package compressionFilters;
019    
020    import java.io.IOException;
021    import java.io.OutputStreamWriter;
022    import java.io.PrintWriter;
023    import javax.servlet.ServletOutputStream;
024    import javax.servlet.http.HttpServletResponse;
025    import javax.servlet.http.HttpServletResponseWrapper;
026    
027    /**
028     * Implementation of <b>HttpServletResponseWrapper</b> that works with
029     * the CompressionServletResponseStream implementation..
030     *
031     * @author Amy Roh
032     * @author Dmitri Valdin
033     * @version $Revision: 514091 $, $Date: 2007-03-03 01:26:39 -0500 (Sat, 03 Mar 2007) $
034     */
035    
036    public class CompressionServletResponseWrapper extends HttpServletResponseWrapper {
037    
038        // ----------------------------------------------------- Constructor
039    
040        /**
041         * Calls the parent constructor which creates a ServletResponse adaptor
042         * wrapping the given response object.
043         */
044    
045        public CompressionServletResponseWrapper(HttpServletResponse response) {
046            super(response);
047            origResponse = response;
048            if (debug > 1) {
049                System.out.println("CompressionServletResponseWrapper constructor gets called");
050            }
051        }
052    
053    
054        // ----------------------------------------------------- Instance Variables
055    
056        /**
057         * Original response
058         */
059    
060        protected HttpServletResponse origResponse = null;
061    
062        /**
063         * Descriptive information about this Response implementation.
064         */
065    
066        protected static final String info = "CompressionServletResponseWrapper";
067    
068        /**
069         * The ServletOutputStream that has been returned by
070         * <code>getOutputStream()</code>, if any.
071         */
072    
073        protected ServletOutputStream stream = null;
074    
075    
076        /**
077         * The PrintWriter that has been returned by
078         * <code>getWriter()</code>, if any.
079         */
080    
081        protected PrintWriter writer = null;
082    
083        /**
084         * The threshold number to compress
085         */
086        protected int threshold = 0;
087    
088        /**
089         * Debug level
090         */
091        private int debug = 0;
092    
093        /**
094         * Content type
095         */
096        protected String contentType = null;
097    
098        // --------------------------------------------------------- Public Methods
099    
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         * @exception 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    
168        // ------------------------------------------------ ServletResponse Methods
169    
170    
171        /**
172         * Flush the buffer and commit this response.
173         *
174         * @exception IOException if an input/output error occurs
175         */
176        public void flushBuffer() throws IOException {
177            if (debug > 1) {
178                System.out.println("flush buffer @ CompressionServletResponseWrapper");
179            }
180            ((CompressionResponseStream)stream).flush();
181    
182        }
183    
184        /**
185         * Return the servlet output stream associated with this Response.
186         *
187         * @exception IllegalStateException if <code>getWriter</code> has
188         *  already been called for this response
189         * @exception IOException if an input/output error occurs
190         */
191        public ServletOutputStream getOutputStream() throws IOException {
192    
193            if (writer != null)
194                throw new IllegalStateException("getWriter() has already been called for this response");
195    
196            if (stream == null)
197                stream = createOutputStream();
198            if (debug > 1) {
199                System.out.println("stream is set to "+stream+" in getOutputStream");
200            }
201    
202            return (stream);
203    
204        }
205    
206        /**
207         * Return the writer associated with this Response.
208         *
209         * @exception IllegalStateException if <code>getOutputStream</code> has
210         *  already been called for this response
211         * @exception IOException if an input/output error occurs
212         */
213        public PrintWriter getWriter() throws IOException {
214    
215            if (writer != null)
216                return (writer);
217    
218            if (stream != null)
219                throw new IllegalStateException("getOutputStream() has already been called for this response");
220    
221            stream = createOutputStream();
222            if (debug > 1) {
223                System.out.println("stream is set to "+stream+" in getWriter");
224            }
225            //String charset = getCharsetFromContentType(contentType);
226            String charEnc = origResponse.getCharacterEncoding();
227            if (debug > 1) {
228                System.out.println("character encoding is " + charEnc);
229            }
230            // HttpServletResponse.getCharacterEncoding() shouldn't return null
231            // according the spec, so feel free to remove that "if"
232            if (charEnc != null) {
233                writer = new PrintWriter(new OutputStreamWriter(stream, charEnc));
234            } else {
235                writer = new PrintWriter(stream);
236            }
237            
238            return (writer);
239    
240        }
241    
242    
243        public void setContentLength(int length) {
244        }
245    
246    
247        /**
248         * Returns character from content type. This method was taken from tomcat.
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    }