001    /*
002    * Copyright 2004 The Apache Software Foundation
003    *
004    * Licensed under the Apache License, Version 2.0 (the "License");
005    * you may not use this file except in compliance with the License.
006    * You may obtain a copy of the License at
007    *
008    *     http://www.apache.org/licenses/LICENSE-2.0
009    *
010    * Unless required by applicable law or agreed to in writing, software
011    * distributed under the License is distributed on an "AS IS" BASIS,
012    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013    * See the License for the specific language governing permissions and
014    * limitations under the License.
015    */
016    
017    package compressionFilters;
018    
019    import java.io.IOException;
020    import java.io.OutputStream;
021    import java.io.OutputStreamWriter;
022    import java.io.PrintWriter;
023    import java.util.Locale;
024    import javax.servlet.ServletRequest;
025    import javax.servlet.ServletResponse;
026    import javax.servlet.ServletException;
027    import javax.servlet.ServletOutputStream;
028    import javax.servlet.ServletResponse;
029    import javax.servlet.ServletResponseWrapper;
030    import javax.servlet.http.HttpServletResponse;
031    import javax.servlet.http.HttpServletResponseWrapper;
032    
033    /**
034     * Implementation of <b>HttpServletResponseWrapper</b> that works with
035     * the CompressionServletResponseStream implementation..
036     *
037     * @author Amy Roh
038     * @author Dmitri Valdin
039     * @version $Revision: 267129 $, $Date: 2004-03-18 08:40:35 -0800 (Thu, 18 Mar 2004) $
040     */
041    
042    public class CompressionServletResponseWrapper extends HttpServletResponseWrapper {
043    
044        // ----------------------------------------------------- Constructor
045    
046        /**
047         * Calls the parent constructor which creates a ServletResponse adaptor
048         * wrapping the given response object.
049         */
050    
051        public CompressionServletResponseWrapper(HttpServletResponse response) {
052            super(response);
053            origResponse = response;
054            if (debug > 1) {
055                System.out.println("CompressionServletResponseWrapper constructor gets called");
056            }
057        }
058    
059    
060        // ----------------------------------------------------- Instance Variables
061    
062        /**
063         * Original response
064         */
065    
066        protected HttpServletResponse origResponse = null;
067    
068        /**
069         * Descriptive information about this Response implementation.
070         */
071    
072        protected static final String info = "CompressionServletResponseWrapper";
073    
074        /**
075         * The ServletOutputStream that has been returned by
076         * <code>getOutputStream()</code>, if any.
077         */
078    
079        protected ServletOutputStream stream = null;
080    
081    
082        /**
083         * The PrintWriter that has been returned by
084         * <code>getWriter()</code>, if any.
085         */
086    
087        protected PrintWriter writer = null;
088    
089        /**
090         * The threshold number to compress
091         */
092        protected int threshold = 0;
093    
094        /**
095         * Debug level
096         */
097        private int debug = 0;
098    
099        /**
100         * Content type
101         */
102        protected String contentType = null;
103    
104        // --------------------------------------------------------- Public Methods
105    
106    
107        /**
108         * Set content type
109         */
110        public void setContentType(String contentType) {
111            if (debug > 1) {
112                System.out.println("setContentType to "+contentType);
113            }
114            this.contentType = contentType;
115            origResponse.setContentType(contentType);
116        }
117    
118    
119        /**
120         * Set threshold number
121         */
122        public void setCompressionThreshold(int threshold) {
123            if (debug > 1) {
124                System.out.println("setCompressionThreshold to " + threshold);
125            }
126            this.threshold = threshold;
127        }
128    
129    
130        /**
131         * Set debug level
132         */
133        public void setDebugLevel(int debug) {
134            this.debug = debug;
135        }
136    
137    
138        /**
139         * Create and return a ServletOutputStream to write the content
140         * associated with this Response.
141         *
142         * @exception IOException if an input/output error occurs
143         */
144        public ServletOutputStream createOutputStream() throws IOException {
145            if (debug > 1) {
146                System.out.println("createOutputStream gets called");
147            }
148    
149            CompressionResponseStream stream = new CompressionResponseStream(origResponse);
150            stream.setDebugLevel(debug);
151            stream.setBuffer(threshold);
152    
153            return stream;
154    
155        }
156    
157    
158        /**
159         * Finish a response.
160         */
161        public void finishResponse() {
162            try {
163                if (writer != null) {
164                    writer.close();
165                } else {
166                    if (stream != null)
167                        stream.close();
168                }
169            } catch (IOException e) {
170            }
171        }
172    
173    
174        // ------------------------------------------------ ServletResponse Methods
175    
176    
177        /**
178         * Flush the buffer and commit this response.
179         *
180         * @exception IOException if an input/output error occurs
181         */
182        public void flushBuffer() throws IOException {
183            if (debug > 1) {
184                System.out.println("flush buffer @ CompressionServletResponseWrapper");
185            }
186            ((CompressionResponseStream)stream).flush();
187    
188        }
189    
190        /**
191         * Return the servlet output stream associated with this Response.
192         *
193         * @exception IllegalStateException if <code>getWriter</code> has
194         *  already been called for this response
195         * @exception IOException if an input/output error occurs
196         */
197        public ServletOutputStream getOutputStream() throws IOException {
198    
199            if (writer != null)
200                throw new IllegalStateException("getWriter() has already been called for this response");
201    
202            if (stream == null)
203                stream = createOutputStream();
204            if (debug > 1) {
205                System.out.println("stream is set to "+stream+" in getOutputStream");
206            }
207    
208            return (stream);
209    
210        }
211    
212        /**
213         * Return the writer associated with this Response.
214         *
215         * @exception IllegalStateException if <code>getOutputStream</code> has
216         *  already been called for this response
217         * @exception IOException if an input/output error occurs
218         */
219        public PrintWriter getWriter() throws IOException {
220    
221            if (writer != null)
222                return (writer);
223    
224            if (stream != null)
225                throw new IllegalStateException("getOutputStream() has already been called for this response");
226    
227            stream = createOutputStream();
228            if (debug > 1) {
229                System.out.println("stream is set to "+stream+" in getWriter");
230            }
231            //String charset = getCharsetFromContentType(contentType);
232            String charEnc = origResponse.getCharacterEncoding();
233            if (debug > 1) {
234                System.out.println("character encoding is " + charEnc);
235            }
236            // HttpServletResponse.getCharacterEncoding() shouldn't return null
237            // according the spec, so feel free to remove that "if"
238            if (charEnc != null) {
239                writer = new PrintWriter(new OutputStreamWriter(stream, charEnc));
240            } else {
241                writer = new PrintWriter(stream);
242            }
243            
244            return (writer);
245    
246        }
247    
248    
249        public void setContentLength(int length) {
250        }
251    
252    
253        /**
254         * Returns character from content type. This method was taken from tomcat.
255         * @author rajo
256         */
257        private static String getCharsetFromContentType(String type) {
258    
259            if (type == null) {
260                return null;
261            }
262            int semi = type.indexOf(";");
263            if (semi == -1) {
264                return null;
265            }
266            String afterSemi = type.substring(semi + 1);
267            int charsetLocation = afterSemi.indexOf("charset=");
268            if(charsetLocation == -1) {
269                return null;
270            } else {
271                String afterCharset = afterSemi.substring(charsetLocation + 8);
272                String encoding = afterCharset.trim();
273                return encoding;
274            }
275        }
276    
277    }