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