amyroh 01/03/21 13:53:16 Added: webapps/examples/WEB-INF/classes/compressionFilters CompressionServletResponseWrapper.java CompressionResponseStream.java CompressionFilterTestServlet.java CompressionFilter.java Log: Compression Filter Example Revision Changes Path 1.1 jakarta-tomcat-4.0/webapps/examples/WEB-INF/classes/compressionFilters/CompressionServletResponseWrapper.java Index: CompressionServletResponseWrapper.java =================================================================== /* * * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package compressionFilters; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.Locale; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.ServletResponse; import javax.servlet.ServletResponseWrapper; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; public class CompressionServletResponseWrapper extends HttpServletResponseWrapper { // ----------------------------------------------------- Constructor /** * Calls the parent constructor which creates a ServletResponse adaptor * wrapping the given response object. */ public CompressionServletResponseWrapper(HttpServletResponse response) { super(response); origResponse = response; //System.out.println("CompressionServletResponseWrapper constructor gets called"); } // ----------------------------------------------------- Instance Variables /** * Original response */ protected HttpServletResponse origResponse = null; /** * Descriptive information about this Response implementation. */ protected static final String info = "CompressionServletResponseWrapper"; /** * The ServletOutputStream that has been returned by * <code>getOutputStream()</code>, if any. */ protected ServletOutputStream stream = null; /** * The PrintWriter that has been returned by * <code>getWriter()</code>, if any. */ protected PrintWriter writer = null; /** * The threshold number to compress */ protected int threshold = 0; // --------------------------------------------------------- Public Methods /** * Set threshold number */ public void setCompressionThreshold(int threshold) { //System.out.println("setCompressionThreshold @ CompressionServletResponseWrapper"); this.threshold = threshold; } /** * Create and return a ServletOutputStream to write the content * associated with this Response. * * @exception IOException if an input/output error occurs */ public ServletOutputStream createOutputStream() throws IOException { //System.out.println("createOutputStream gets called"); return (new CompressionResponseStream(origResponse)); } // ------------------------------------------------ ServletResponse Methods /** * Flush the buffer and commit this response. * * @exception IOException if an input/output error occurs */ public void flushBuffer() throws IOException { // System.out.println("flush buffer @ CompressionServletResponseWrapper"); ((CompressionResponseStream)stream).flush(); } /** * Return the servlet output stream associated with this Response. * * @exception IllegalStateException if <code>getWriter</code> has * already been called for this response * @exception IOException if an input/output error occurs */ public ServletOutputStream getOutputStream() throws IOException { if (writer != null) throw new IllegalStateException("getWriter() has already been called for this response"); if (stream == null) stream = createOutputStream(); //System.out.println("stream is set to "+stream+" in getOutputStream"); ((CompressionResponseStream) stream).setCommit(true); ((CompressionResponseStream) stream).setBuffer(threshold); return (stream); } /** * Return the writer associated with this Response. * * @exception IllegalStateException if <code>getOutputStream</code> has * already been called for this response * @exception IOException if an input/output error occurs */ public PrintWriter getWriter() throws IOException { if (writer != null) return (writer); if (stream != null) throw new IllegalStateException("getOutputStream() has already been called for this response"); stream = createOutputStream(); //System.out.println("strean is set to "+stream+" in getWriter"); ((CompressionResponseStream) stream).setCommit(true); ((CompressionResponseStream) stream).setBuffer(threshold); writer = new PrintWriter(stream); return (writer); } } 1.1 jakarta-tomcat-4.0/webapps/examples/WEB-INF/classes/compressionFilters/CompressionResponseStream.java Index: CompressionResponseStream.java =================================================================== /* * * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package compressionFilters; import java.io.IOException; import java.io.OutputStream; import java.util.zip.GZIPOutputStream; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; /** * Implementation of <b>ServletOutputStream</b> that works with * the CompressionServletResponseWrapper implementation. * * @author Amy Roh */ public class CompressionResponseStream extends ServletOutputStream { // ----------------------------------------------------------- Constructors /** * Construct a servlet output stream associated with the specified Response. * * @param response The associated response */ public CompressionResponseStream(HttpServletResponse response) throws IOException{ super(); closed = false; commit = false; count = 0; this.response = response; this.output = response.getOutputStream(); } // ----------------------------------------------------- Instance Variables /** * The threshold number which decides to compress or not. * Users can configure in web.xml to set it to fit their needs. */ protected int compressionThreshold = 0; /** * The buffer through which all of our output bytes are passed. */ protected byte[] buffer = null; /** * Is it big enough to compress? */ protected boolean compressionThresholdReached = false; /** * The number of data bytes currently in the buffer. */ protected int bufferCount = 0; /** * The underlying gzip output stream to which we should write data. */ protected GZIPOutputStream gzipstream = null; /** * Has this stream been closed? */ protected boolean closed = false; /** * Should we commit the response when we are flushed? */ protected boolean commit = true; /** * The number of bytes which have already been written to this stream. */ protected int count = 0; /** * The content length past which we will not write, or -1 if there is * no defined content length. */ protected int length = -1; /** * The response with which this servlet output stream is associated. */ protected HttpServletResponse response = null; /** * The underlying servket output stream to which we should write data. */ protected ServletOutputStream output = null; // ------------------------------------------------------------- Properties /** * [Package Private] Return the "commit response on flush" flag. */ boolean getCommit() { return (this.commit); } /** * [Package Private] Set the "commit response on flush" flag. * * @param commit The new commit flag */ void setCommit(boolean commit) { this.commit = commit; } // --------------------------------------------------------- Public Methods /** * Set the compressionThreshold number and create buffer for this size */ protected void setBuffer(int threshold) { compressionThreshold = threshold; buffer = new byte[compressionThreshold]; //System.out.println("buffer is set to "+compressionThreshold); } /** * Close this output stream, causing any buffered data to be flushed and * any further output data to throw an IOException. */ public void close() throws IOException { if (closed) throw new IOException("This output stream has already been closed"); if (gzipstream!=null) { gzipstream.close(); } flush(); closed = true; } /** * Flush any buffered data for this output stream, which also causes the * response to be committed. */ public void flush() throws IOException { //System.out.println("flush() @ CompressionResponseStream"); if (closed) throw new IOException("Cannot flush a closed output stream"); if (commit) { if (bufferCount > 0) { //System.out.println("writing to original stream"); output.write(buffer, 0, bufferCount); bufferCount = 0; } } else { //System.out.println("commit false"); } } public void flushToGZip() throws IOException { //System.out.println("flushToGZip() @ CompressionResponseStream"); if (bufferCount > 0) { //System.out.println("flushing out to GZipStream"); gzipstream.write(buffer, 0, bufferCount); bufferCount = 0; } } /** * Write the specified byte to our output stream. * * @param b The byte to be written * * @exception IOException if an input/output error occurs */ public void write(int b) throws IOException { //System.out.print("write "+b+" in CompressionResponseStream "); if (closed) throw new IOException("Cannot write to a closed output stream"); if ((bufferCount >= buffer.length) || (count>=compressionThreshold)) { compressionThresholdReached = true; } if (compressionThresholdReached) { writeToGZip(b); } else { buffer[bufferCount++] = (byte) b; count++; } } /** * Write the specified byte to our compressed GZip output stream. * * @param b The byte to be written * * @exception IOException if an input/output error occurs */ public void writeToGZip(int b) throws IOException { //System.out.println("writeToGZip (int b) compressing"); if (gzipstream == null) { gzipstream = new GZIPOutputStream(output); flushToGZip(); response.addHeader("Content-Encoding", "gzip"); } gzipstream.write(b); } /** * Write <code>b.length</code> bytes from the specified byte array * to our output stream. * * @param b The byte array to be written * * @exception IOException if an input/output error occurs */ public void write(byte b[]) throws IOException { write(b, 0, b.length); } /** * Write <code>len</code> bytes from the specified byte array, starting * at the specified offset, to our output stream. * * @param b The byte array containing the bytes to be written * @param off Zero-relative starting offset of the bytes to be written * @param len The number of bytes to be written * * @exception IOException if an input/output error occurs */ public void write(byte b[], int off, int len) throws IOException { //System.out.println("second write in CompressionResponseStream"); if (closed) throw new IOException("Cannot write to a closed output stream"); if (len == 0) return; if (len <= (buffer.length - bufferCount)) { System.arraycopy(b, off, buffer, bufferCount, len); bufferCount += len; count += len; return; } // buffer full, start writing to gzipstream writeToGZip(b, off, len); count += len; } public void writeToGZip(byte b[], int off, int len) throws IOException { //System.out.println("writeToGZip 2 compressing"); if (gzipstream == null) { gzipstream = new GZIPOutputStream(output); flushToGZip(); response.addHeader("Content-Encoding", "gzip"); } gzipstream.write(b, off, len); } // -------------------------------------------------------- Package Methods /** * Has this response stream been closed? */ boolean closed() { return (this.closed); } /** * Reset the count of bytes written to this stream to zero. */ void reset() { count = 0; } } 1.1 jakarta-tomcat-4.0/webapps/examples/WEB-INF/classes/compressionFilters/CompressionFilterTestServlet.java Index: CompressionFilterTestServlet.java =================================================================== /* * * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package compressionFilters; import java.io.IOException; import java.io.PrintWriter; import java.util.Enumeration; import javax.servlet.*; import javax.servlet.http.*; /** * Very Simple test servlet to test compression filter * @author Amy Roh */ public class CompressionFilterTestServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletOutputStream out = response.getOutputStream(); response.setContentType("text/plain"); Enumeration e = ((HttpServletRequest)request).getHeaders("Accept-Encoding"); while (e.hasMoreElements()) { String name = (String)e.nextElement(); out.println(name); if (name.indexOf("gzip") != -1) { out.println("gzip supported -- able to compress"); } else out.println("gzip not supported"); } out.println("Compression Filter Test Servlet"); out.close(); } } 1.1 jakarta-tomcat-4.0/webapps/examples/WEB-INF/classes/compressionFilters/CompressionFilter.java Index: CompressionFilter.java =================================================================== /* * * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package compressionFilters; import java.io.IOException; import java.util.Enumeration; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Implementation of <code>javax.servlet.Filter</code> used to compress * the ServletResponse if it is bigger than a threshold. * * @author Amy Roh */ public class CompressionFilter implements Filter{ /** * The filter configuration object we are associated with. If this value * is null, this filter instance is not currently configured. */ private FilterConfig config = null; /** * The threshold number to compress */ protected int compressionThreshold; /** * Debug level for this filter */ private int debug = 0; /** * Place this filter into service. * * @param filterConfig The filter configuration object */ public void init(FilterConfig filterConfig) { config = filterConfig; if (filterConfig != null) { String str = filterConfig.getInitParameter("compressionThreshold"); if (str!=null) { compressionThreshold = Integer.parseInt(str); } else compressionThreshold = 0; String value = filterConfig.getInitParameter("debug"); if (value!=null) { debug = Integer.parseInt(value); } else debug = 0; if (debug > 0) { System.out.println("@init compressionThreshold set to "+compressionThreshold); } } else { compressionThreshold = 0; } } /** * Take this filter out of service. */ public void destroy() { this.config = null; } /** * The <code>doFilter</code> method of the Filter is called by the container * each time a request/response pair is passed through the chain due * to a client request for a resource at the end of the chain. The FilterChain passed into this * method allows the Filter to pass on the request and response to the next entity in the * chain.<p> * This method first examines the request to check whether the client support compression. <br> * It simply just pass the request and response if there is no support for compression.<br> * If the compression support is available, it creates a CompressionServletResponseWrapper object which * compresses the content and modifies the header if the content length is big enough. * It then invokes the next entity in the chain using the FilterChain object (<code>chain.doFilter()</code>), <br> **/ public void doFilter ( ServletRequest request, ServletResponse response, FilterChain chain ) throws IOException, ServletException { if (debug > 0) { System.out.println("@doFilter"); } boolean supportCompression = false; if (request instanceof HttpServletRequest) { Enumeration e = ((HttpServletRequest)request).getHeaders("Accept-Encoding"); while (e.hasMoreElements()) { String name = (String)e.nextElement(); if (name.indexOf("gzip") != -1) { if (debug > 0) { System.out.println("supports compression"); } supportCompression = true; } else { if (debug > 0) { System.out.println("no suuport for compresion"); } } } } if (!supportCompression) { if (debug > 0) { System.out.println("doFilter gets called wo compression"); } chain.doFilter(request, response); return; } else { if (response instanceof HttpServletResponse) { CompressionServletResponseWrapper wrappedResponse = new CompressionServletResponseWrapper((HttpServletResponse)response); wrappedResponse.setCompressionThreshold(compressionThreshold); if (debug > 0) { System.out.println("doFilter gets called with compression"); } chain.doFilter(request, wrappedResponse); return; } } } }