Author: markt
Date: Tue Jun 12 18:57:00 2012
New Revision: 1349473
URL: http://svn.apache.org/viewvc?rev=1349473&view=rev
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=50182
Various improvements to the compression filter example.
Patch by David Becker
Modified:
tomcat/trunk/webapps/examples/WEB-INF/classes/compressionFilters/CompressionFilter.java
tomcat/trunk/webapps/examples/WEB-INF/classes/compressionFilters/CompressionFilterTestServlet.java
tomcat/trunk/webapps/examples/WEB-INF/classes/compressionFilters/CompressionResponseStream.java
tomcat/trunk/webapps/examples/WEB-INF/classes/compressionFilters/CompressionServletResponseWrapper.java
tomcat/trunk/webapps/examples/WEB-INF/web.xml
Modified:
tomcat/trunk/webapps/examples/WEB-INF/classes/compressionFilters/CompressionFilter.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/WEB-INF/classes/compressionFilters/CompressionFilter.java?rev=1349473&r1=1349472&r2=1349473&view=diff
==============================================================================
---
tomcat/trunk/webapps/examples/WEB-INF/classes/compressionFilters/CompressionFilter.java
(original)
+++
tomcat/trunk/webapps/examples/WEB-INF/classes/compressionFilters/CompressionFilter.java
Tue Jun 12 18:57:00 2012
@@ -14,11 +14,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package compressionFilters;
import java.io.IOException;
import java.util.Enumeration;
+import java.util.StringTokenizer;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
@@ -29,17 +29,14 @@ 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
* @author Dmitri Valdin
- * @version $Id$
*/
-
-public class CompressionFilter implements Filter{
+public class CompressionFilter implements Filter {
/**
* The filter configuration object we are associated with. If this value
@@ -48,18 +45,32 @@ public class CompressionFilter implement
private FilterConfig config = null;
/**
- * Minimal reasonable threshold
+ * Minimal reasonable threshold.
*/
private int minThreshold = 128;
+ /**
+ * The threshold number to compress.
+ */
+ protected int compressionThreshold = 0;
+
+ /**
+ * Minimal reasonable buffer.
+ */
+ private int minBuffer = 8192; // 8KB is what tomcat would use by default
anyway
+
+ /**
+ * The compression buffer size to avoid chunking.
+ */
+ protected int compressionBuffer = 0;
/**
- * The threshold number to compress
+ * The mime types to compress.
*/
- protected int compressionThreshold;
+ protected String[] compressionMimeTypes = {"text/html", "text/xml",
"text/plain"};
/**
- * Debug level for this filter
+ * Debug level for this filter.
*/
private int debug = 0;
@@ -68,7 +79,6 @@ public class CompressionFilter implement
*
* @param filterConfig The filter configuration object
*/
-
@Override
public void init(FilterConfig filterConfig) {
@@ -77,9 +87,8 @@ public class CompressionFilter implement
String value = filterConfig.getInitParameter("debug");
if (value!=null) {
debug = Integer.parseInt(value);
- } else {
- debug = 0;
}
+
String str = filterConfig.getInitParameter("compressionThreshold");
if (str!=null) {
compressionThreshold = Integer.parseInt(str);
@@ -90,12 +99,33 @@ public class CompressionFilter implement
}
compressionThreshold = minThreshold;
}
- } else {
- compressionThreshold = 0;
}
- } else {
- compressionThreshold = 0;
+ str = filterConfig.getInitParameter("compressionBuffer");
+ if (str!=null) {
+ compressionBuffer = Integer.parseInt(str);
+ if (compressionBuffer < minBuffer) {
+ if (debug > 0) {
+ System.out.println("compressionBuffer should be >= " +
minBuffer);
+ System.out.println("compressionBuffer set to " +
minBuffer);
+ }
+ compressionBuffer = minBuffer;
+ }
+ }
+
+ str = filterConfig.getInitParameter("compressionMimeTypes");
+ if (str!=null) {
+ compressionMimeTypes = null;
+ StringTokenizer st = new StringTokenizer(str, ",");
+
+ while (st.hasMoreTokens()) {
+ compressionMimeTypes =
addStringArray(compressionMimeTypes, st.nextToken().trim());
+ }
+
+ if (debug > 0) {
+ System.out.println("compressionMimeTypes set to " +
compressionMimeTypes);
+ }
+ }
}
}
@@ -126,7 +156,6 @@ public class CompressionFilter implement
* It then invokes the next entity in the chain using the FilterChain
object
* (<code>chain.doFilter()</code>), <br>
**/
-
@Override
public void doFilter ( ServletRequest request, ServletResponse response,
FilterChain chain ) throws IOException,
ServletException {
@@ -137,7 +166,7 @@ public class CompressionFilter implement
if (compressionThreshold == 0) {
if (debug > 0) {
- System.out.println("doFilter gets called, but
compressionTreshold is set to 0 - no compression");
+ System.out.println("doFilter got called, but
compressionTreshold is set to 0 - no compression");
}
chain.doFilter(request, response);
return;
@@ -170,33 +199,35 @@ public class CompressionFilter implement
supportCompression = true;
} else {
if (debug > 0) {
- System.out.println("no support for compresion");
+ System.out.println("no support for compression");
}
}
}
}
- if (!supportCompression) {
- if (debug > 0) {
- System.out.println("doFilter gets called wo compression");
+ if (supportCompression) {
+ if (response instanceof HttpServletResponse) {
+ CompressionServletResponseWrapper wrappedResponse =
+ new
CompressionServletResponseWrapper((HttpServletResponse)response);
+ wrappedResponse.setDebugLevel(debug);
+ wrappedResponse.setCompressionThreshold(compressionThreshold);
+ wrappedResponse.setCompressionBuffer(compressionBuffer);
+ wrappedResponse.setCompressionMimeTypes(compressionMimeTypes);
+ if (debug > 0) {
+ System.out.println("doFilter gets called with
compression");
+ }
+ try {
+ chain.doFilter(request, wrappedResponse);
+ } finally {
+ wrappedResponse.finishResponse();
+ }
+ return;
}
- chain.doFilter(request, response);
- return;
- }
-
- if (response instanceof HttpServletResponse) {
- CompressionServletResponseWrapper wrappedResponse =
- new
CompressionServletResponseWrapper((HttpServletResponse)response);
- wrappedResponse.setDebugLevel(debug);
- wrappedResponse.setCompressionThreshold(compressionThreshold);
+ } else {
if (debug > 0) {
- System.out.println("doFilter gets called with compression");
- }
- try {
- chain.doFilter(request, wrappedResponse);
- } finally {
- wrappedResponse.finishResponse();
+ System.out.println("doFilter gets called w/o compression");
}
+ chain.doFilter(request, response);
return;
}
}
@@ -219,5 +250,26 @@ public class CompressionFilter implement
return config;
}
+ /**
+ * General use method
+ *
+ * @param sArray the StringArray
+ * @param value string
+ */
+ private String[] addStringArray(String sArray[], String value) {
+ String[] result = null;
+ if (sArray == null) {
+ result = new String[1];
+ result[0] = value;
+ }
+ else {
+ result = new String[sArray.length + 1];
+ for (int i = 0; i < sArray.length; i++)
+ result[i] = sArray[i];
+ result[sArray.length] = value;
+ }
+ return result;
+ }
+
}
Modified:
tomcat/trunk/webapps/examples/WEB-INF/classes/compressionFilters/CompressionFilterTestServlet.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/WEB-INF/classes/compressionFilters/CompressionFilterTestServlet.java?rev=1349473&r1=1349472&r2=1349473&view=diff
==============================================================================
---
tomcat/trunk/webapps/examples/WEB-INF/classes/compressionFilters/CompressionFilterTestServlet.java
(original)
+++
tomcat/trunk/webapps/examples/WEB-INF/classes/compressionFilters/CompressionFilterTestServlet.java
Tue Jun 12 18:57:00 2012
@@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package compressionFilters;
import java.io.IOException;
@@ -29,9 +28,7 @@ import javax.servlet.http.HttpServletRes
/**
* Very Simple test servlet to test compression filter
* @author Amy Roh
- * @version $Id$
*/
-
public class CompressionFilterTestServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@@ -57,6 +54,11 @@ public class CompressionFilterTestServle
out.println("Compression Filter Test Servlet");
+ out.println("Minimum content length for compression is 128 bytes");
+ out.println("********** 32 bytes **********");
+ out.println("********** 32 bytes **********");
+ out.println("********** 32 bytes **********");
+ out.println("********** 32 bytes **********");
out.close();
}
Modified:
tomcat/trunk/webapps/examples/WEB-INF/classes/compressionFilters/CompressionResponseStream.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/WEB-INF/classes/compressionFilters/CompressionResponseStream.java?rev=1349473&r1=1349472&r2=1349473&view=diff
==============================================================================
---
tomcat/trunk/webapps/examples/WEB-INF/classes/compressionFilters/CompressionResponseStream.java
(original)
+++
tomcat/trunk/webapps/examples/WEB-INF/classes/compressionFilters/CompressionResponseStream.java
Tue Jun 12 18:57:00 2012
@@ -21,8 +21,6 @@ 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
@@ -30,28 +28,26 @@ import javax.servlet.http.HttpServletRes
*
* @author Amy Roh
* @author Dmitri Valdin
- * @version $Id$
*/
-
-public class CompressionResponseStream
- extends ServletOutputStream {
-
+public class CompressionResponseStream extends ServletOutputStream {
// ----------------------------------------------------------- Constructors
-
/**
* Construct a servlet output stream associated with the specified
Response.
*
* @param response The associated response
+ * @param response
+ * @param originalOutput
*/
- public CompressionResponseStream(HttpServletResponse response) throws
IOException{
+ public CompressionResponseStream(
+ CompressionServletResponseWrapper responseWrapper,
+ ServletOutputStream originalOutput) {
super();
closed = false;
- this.response = response;
- this.output = response.getOutputStream();
-
+ this.response = responseWrapper;
+ this.output = originalOutput;
}
@@ -65,6 +61,16 @@ public class CompressionResponseStream
protected int compressionThreshold = 0;
/**
+ * The compression buffer size to avoid chunking
+ */
+ protected int compressionBuffer = 0;
+
+ /**
+ * The mime types to compress
+ */
+ protected String[] compressionMimeTypes = {"text/html", "text/xml",
"text/plain"};
+
+ /**
* Debug level
*/
private int debug = 0;
@@ -98,10 +104,10 @@ public class CompressionResponseStream
/**
* The response with which this servlet output stream is associated.
*/
- protected HttpServletResponse response = null;
+ protected CompressionServletResponseWrapper response = null;
/**
- * The underlying servket output stream to which we should write data.
+ * The underlying servlet output stream to which we should write data.
*/
protected ServletOutputStream output = null;
@@ -119,11 +125,31 @@ public class CompressionResponseStream
/**
* Set the compressionThreshold number and create buffer for this size
*/
- protected void setBuffer(int threshold) {
- compressionThreshold = threshold;
- buffer = new byte[compressionThreshold];
+ protected void setCompressionThreshold(int compressionThreshold) {
+ this.compressionThreshold = compressionThreshold;
+ buffer = new byte[this.compressionThreshold];
+ if (debug > 1) {
+ System.out.println("compressionThreshold is set to "+
this.compressionThreshold);
+ }
+ }
+
+ /**
+ * The compression buffer size to avoid chunking
+ */
+ protected void setCompressionBuffer(int compressionBuffer) {
+ this.compressionBuffer = compressionBuffer;
+ if (debug > 1) {
+ System.out.println("compressionBuffer is set to "+
this.compressionBuffer);
+ }
+ }
+
+ /**
+ * Set supported mime types
+ */
+ public void setCompressionMimeTypes(String[] compressionMimeTypes) {
+ this.compressionMimeTypes = compressionMimeTypes;
if (debug > 1) {
- System.out.println("buffer is set to "+compressionThreshold);
+ System.out.println("compressionMimeTypes is set to " +
this.compressionMimeTypes);
}
}
@@ -301,22 +327,53 @@ public class CompressionResponseStream
if (debug > 1) {
System.out.println("new GZIPOutputStream");
}
+
+ boolean alreadyCompressed = false;
+ String contentEncoding = response.getHeader("Content-Encoding");
+ if (contentEncoding != null) {
+ if (contentEncoding.contains("gzip")) {
+ alreadyCompressed = true;
+ if (debug > 0) {
+ System.out.println("content is already compressed");
+ }
+ } else {
+ if (debug > 0) {
+ System.out.println("content is not compressed yet");
+ }
+ }
+ }
+
+ boolean compressibleMimeType = false;
+ // Check for compatible MIME-TYPE
+ if (compressionMimeTypes != null) {
+ if (startsWithStringArray(compressionMimeTypes,
response.getContentType())) {
+ compressibleMimeType = true;
+ if (debug > 0) {
+ System.out.println("mime type " +
response.getContentType() + " is compressible");
+ }
+ } else {
+ if (debug > 0) {
+ System.out.println("mime type " +
response.getContentType() + " is not compressible");
+ }
+ }
+ }
+
if (response.isCommitted()) {
if (debug > 1)
System.out.print("Response already committed. Using
original output stream");
gzipstream = output;
+ } else if (alreadyCompressed) {
+ if (debug > 1)
+ System.out.print("Response already compressed. Using
original output stream");
+ gzipstream = output;
+ } else if (!compressibleMimeType) {
+ if (debug > 1)
+ System.out.print("Response mime type is not compressible.
Using original output stream");
+ gzipstream = output;
} else {
response.addHeader("Content-Encoding", "gzip");
- String vary = response.getHeader("Vary");
- if (vary == null) {
- // Add a new Vary header
- response.setHeader("Vary", "Accept-Encoding");
- } else if (vary.equals("*")) {
- // No action required
- } else {
- // Merge into current header
- response.setHeader("Vary", vary + ",Accept-Encoding");
- }
+ response.setContentLength(-1); // don't use any preset
content-length as it will be wrong after gzipping
+ response.setBufferSize(compressionBuffer);
gzipstream = new GZIPOutputStream(output);
}
}
@@ -337,4 +394,20 @@ public class CompressionResponseStream
}
+ /**
+ * Checks if any entry in the string array starts with the specified value
+ *
+ * @param sArray the StringArray
+ * @param value string
+ */
+ private boolean startsWithStringArray(String sArray[], String value) {
+ if (value == null)
+ return false;
+ for (int i = 0; i < sArray.length; i++) {
+ if (value.startsWith(sArray[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
}
Modified:
tomcat/trunk/webapps/examples/WEB-INF/classes/compressionFilters/CompressionServletResponseWrapper.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/WEB-INF/classes/compressionFilters/CompressionServletResponseWrapper.java?rev=1349473&r1=1349472&r2=1349473&view=diff
==============================================================================
---
tomcat/trunk/webapps/examples/WEB-INF/classes/compressionFilters/CompressionServletResponseWrapper.java
(original)
+++
tomcat/trunk/webapps/examples/WEB-INF/classes/compressionFilters/CompressionServletResponseWrapper.java
Tue Jun 12 18:57:00 2012
@@ -19,6 +19,8 @@ package compressionFilters;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
@@ -30,10 +32,9 @@ import javax.servlet.http.HttpServletRes
*
* @author Amy Roh
* @author Dmitri Valdin
- * @version $Id$
*/
-
-public class CompressionServletResponseWrapper extends
HttpServletResponseWrapper {
+public class CompressionServletResponseWrapper
+ extends HttpServletResponseWrapper {
// ----------------------------------------------------- Constructor
@@ -41,7 +42,6 @@ public class CompressionServletResponseW
* Calls the parent constructor which creates a ServletResponse adaptor
* wrapping the given response object.
*/
-
public CompressionServletResponseWrapper(HttpServletResponse response) {
super(response);
origResponse = response;
@@ -59,6 +59,11 @@ public class CompressionServletResponseW
protected HttpServletResponse origResponse = null;
/**
+ * Descriptive information about this Response implementation.
+ */
+ protected static final String info = "GZipServletResponseWrapper";
+
+ /**
* The ServletOutputStream that has been returned by
* <code>getOutputStream()</code>, if any.
*/
@@ -74,44 +79,61 @@ public class CompressionServletResponseW
/**
* The threshold number to compress
*/
- protected int threshold = 0;
+ protected int compressionThreshold = 0;
+
+ /**
+ * The compression buffer size
+ */
+ protected int compressionBuffer = 8192; // 8KB default
+
+ /**
+ * The mime types to compress
+ */
+ protected String[] compressionMimeTypes = {"text/html", "text/xml",
"text/plain"};
/**
* Debug level
*/
- private int debug = 0;
+ protected int debug = 0;
/**
- * Content type
+ * keeps a copy of all headers set
*/
- protected String contentType = null;
+ private Map<String,String> headerCopies = new HashMap<String,String>();
+
// --------------------------------------------------------- Public Methods
/**
- * Set content type
+ * Set threshold number
*/
- @Override
- public void setContentType(String contentType) {
+ public void setCompressionThreshold(int threshold) {
if (debug > 1) {
- System.out.println("setContentType to "+contentType);
+ System.out.println("setCompressionThreshold to " + threshold);
}
- this.contentType = contentType;
- origResponse.setContentType(contentType);
+ this.compressionThreshold = threshold;
}
-
/**
- * Set threshold number
+ * Set compression buffer
*/
- public void setCompressionThreshold(int threshold) {
+ public void setCompressionBuffer(int buffer) {
if (debug > 1) {
- System.out.println("setCompressionThreshold to " + threshold);
+ System.out.println("setCompressionBuffer to " + buffer);
}
- this.threshold = threshold;
+ this.compressionBuffer = buffer;
}
+ /**
+ * Set compressible mime types
+ */
+ public void setCompressionMimeTypes(String[] mimeTypes) {
+ if (debug > 1) {
+ System.out.println("setCompressionMimeTypes to " + mimeTypes);
+ }
+ this.compressionMimeTypes = mimeTypes;
+ }
/**
* Set debug level
@@ -132,13 +154,14 @@ public class CompressionServletResponseW
System.out.println("createOutputStream gets called");
}
- CompressionResponseStream compressedStream =
- new CompressionResponseStream(origResponse);
- compressedStream.setDebugLevel(debug);
- compressedStream.setBuffer(threshold);
-
- return compressedStream;
+ CompressionResponseStream stream = new CompressionResponseStream(
+ this, origResponse.getOutputStream());
+ stream.setDebugLevel(debug);
+ stream.setCompressionThreshold(compressionThreshold);
+ stream.setCompressionBuffer(compressionBuffer);
+ stream.setCompressionMimeTypes(compressionMimeTypes);
+ return stream;
}
@@ -170,7 +193,7 @@ public class CompressionServletResponseW
@Override
public void flushBuffer() throws IOException {
if (debug > 1) {
- System.out.println("flush buffer @
CompressionServletResponseWrapper");
+ System.out.println("flush buffer @ GZipServletResponseWrapper");
}
((CompressionResponseStream)stream).flush();
@@ -219,7 +242,6 @@ public class CompressionServletResponseW
if (debug > 1) {
System.out.println("stream is set to "+stream+" in getWriter");
}
- //String charset = getCharsetFromContentType(contentType);
String charEnc = origResponse.getCharacterEncoding();
if (debug > 1) {
System.out.println("character encoding is " + charEnc);
@@ -233,12 +255,27 @@ public class CompressionServletResponseW
}
return (writer);
+ }
+ @Override
+ public String getHeader(String name) {
+ return headerCopies.get(name);
}
@Override
- public void setContentLength(int length) {
- // Don't, as compression will change it
+ public void addHeader(String name, String value) {
+ if (headerCopies.containsKey(name)) {
+ String existingValue = headerCopies.get(name);
+ if ((existingValue != null) && (existingValue.length() > 0))
headerCopies.put(name, existingValue + "," + value);
+ else headerCopies.put(name, value);
+ } else headerCopies.put(name, value);
+ super.addHeader(name, value);
}
+
+ @Override
+ public void setHeader(String name, String value) {
+ headerCopies.put(name, value);
+ super.setHeader(name, value);
+ }
}
Modified: tomcat/trunk/webapps/examples/WEB-INF/web.xml
URL:
http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/WEB-INF/web.xml?rev=1349473&r1=1349472&r2=1349473&view=diff
==============================================================================
--- tomcat/trunk/webapps/examples/WEB-INF/web.xml (original)
+++ tomcat/trunk/webapps/examples/WEB-INF/web.xml Tue Jun 12 18:57:00 2012
@@ -60,10 +60,17 @@
<filter>
<filter-name>Compression Filter</filter-name>
<filter-class>compressionFilters.CompressionFilter</filter-class>
-
<init-param>
- <param-name>compressionThreshold</param-name>
- <param-value>10</param-value>
+ <param-name>compressionThreshold</param-name>
+ <param-value>128</param-value>
+ </init-param>
+ <init-param>
+ <param-name>compressionBuffer</param-name>
+ <param-value>8192</param-value>
+ </init-param>
+ <init-param>
+ <param-name>compressionMimeTypes</param-name>
+ <param-value>text/html,text/plain,text/xml</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]