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    
024    import javax.servlet.ServletOutputStream;
025    import javax.servlet.http.HttpServletResponse;
026    import javax.servlet.http.HttpServletResponseWrapper;
027    
028    /**
029     * Implementation of <b>HttpServletResponseWrapper</b> that works with
030     * the CompressionServletResponseStream implementation..
031     *
032     * @author Amy Roh
033     * @author Dmitri Valdin
034     * @version $Revision: 664175 $, $Date: 2008-06-06 18:43:44 -0400 (Fri, 06 Jun 2008) $
035     */
036    
037    public class CompressionServletResponseWrapper extends HttpServletResponseWrapper {
038    
039        // ----------------------------------------------------- Constructor
040    
041        /**
042         * Calls the parent constructor which creates a ServletResponse adaptor
043         * wrapping the given response object.
044         */
045    
046        public CompressionServletResponseWrapper(HttpServletResponse response) {
047            super(response);
048            origResponse = response;
049            if (debug > 1) {
050                System.out.println("CompressionServletResponseWrapper constructor gets called");
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         * @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    }