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    package compressionFilters;
018    
019    import java.io.IOException;
020    import java.io.OutputStreamWriter;
021    import java.io.PrintWriter;
022    
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: 664175 $, $Date: 2008-06-06 18:43:44 -0400 (Fri, 06 Jun 2008) $
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        // ----------------------------------------------------- Instance Variables
054    
055        /**
056         * Original response
057         */
058    
059        protected HttpServletResponse origResponse = null;
060    
061        /**
062         * Descriptive information about this Response implementation.
063         */
064    
065        protected static final String info = "CompressionServletResponseWrapper";
066    
067        /**
068         * The ServletOutputStream that has been returned by
069         * <code>getOutputStream()</code>, if any.
070         */
071    
072        protected ServletOutputStream stream = null;
073    
074    
075        /**
076         * The PrintWriter that has been returned by
077         * <code>getWriter()</code>, if any.
078         */
079    
080        protected PrintWriter writer = null;
081    
082        /**
083         * The threshold number to compress
084         */
085        protected int threshold = 0;
086    
087        /**
088         * Debug level
089         */
090        private int debug = 0;
091    
092        /**
093         * Content type
094         */
095        protected String contentType = null;
096    
097        // --------------------------------------------------------- Public Methods
098    
099    
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    }