You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@click.apache.org by sa...@apache.org on 2009/06/05 19:48:28 UTC
svn commit: r782077 - in
/incubator/click/trunk/click/extras/src/org/apache/click/extras/filter:
CompressionFilter.java CompressionResponseStream.java
CompressionServletResponseWrapper.java PerformanceFilter.java
Author: sabob
Date: Fri Jun 5 17:48:27 2009
New Revision: 782077
URL: http://svn.apache.org/viewvc?rev=782077&view=rev
Log:
improved compression to handle included requests. CLK-557
Modified:
incubator/click/trunk/click/extras/src/org/apache/click/extras/filter/CompressionFilter.java
incubator/click/trunk/click/extras/src/org/apache/click/extras/filter/CompressionResponseStream.java
incubator/click/trunk/click/extras/src/org/apache/click/extras/filter/CompressionServletResponseWrapper.java
incubator/click/trunk/click/extras/src/org/apache/click/extras/filter/PerformanceFilter.java
Modified: incubator/click/trunk/click/extras/src/org/apache/click/extras/filter/CompressionFilter.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/extras/src/org/apache/click/extras/filter/CompressionFilter.java?rev=782077&r1=782076&r2=782077&view=diff
==============================================================================
--- incubator/click/trunk/click/extras/src/org/apache/click/extras/filter/CompressionFilter.java (original)
+++ incubator/click/trunk/click/extras/src/org/apache/click/extras/filter/CompressionFilter.java Fri Jun 5 17:48:27 2009
@@ -1,18 +1,18 @@
/*
-* Copyright 2004 The Apache Software Foundation
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
+ * Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package org.apache.click.extras.filter;
import java.io.IOException;
@@ -120,13 +120,13 @@
* It then invokes the next entity in the chain using the FilterChain object
* (<code>chain.doFilter()</code>)
*
- * @param request the servlet request
- * @param response the servlet response
+ * @param servletRequest the servlet request
+ * @param servletResponse the servlet response
* @param chain the filter chain
* @throws IOException if an I/O error occurs
* @throws ServletException if a servlet error occurs
*/
- public void doFilter(ServletRequest request, ServletResponse response,
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain chain) throws IOException, ServletException {
if (!configured) {
@@ -134,7 +134,7 @@
}
if (compressionThreshold == 0) {
- chain.doFilter(request, response);
+ chain.doFilter(servletRequest, servletResponse);
return;
}
@@ -143,7 +143,7 @@
String charset = getConfigService().getCharset();
if (charset != null) {
try {
- request.setCharacterEncoding(charset);
+ servletRequest.setCharacterEncoding(charset);
} catch (UnsupportedEncodingException ex) {
String msg =
@@ -152,43 +152,26 @@
}
}
- if (request instanceof HttpServletRequest) {
+ final HttpServletRequest request = (HttpServletRequest) servletRequest;
+ final HttpServletResponse response = (HttpServletResponse) servletResponse;
- // Are we allowed to compress ?
- String s = ((HttpServletRequest) request).getParameter("gzip");
- if ("false".equals(s)) {
- chain.doFilter(request, response);
- return;
- }
-
- Enumeration e =
- ((HttpServletRequest) request).getHeaders("Accept-Encoding");
-
- while (e.hasMoreElements()) {
- String name = (String) e.nextElement();
- if (name.indexOf("gzip") != -1) {
- supportCompression = true;
- }
- }
- }
+ final String path = ClickUtils.getResourcePath((HttpServletRequest) request);
+ supportCompression = useGzipCompression(request, response, path);
if (!supportCompression) {
chain.doFilter(request, response);
} else {
- if (response instanceof HttpServletResponse) {
- HttpServletResponse hsr = (HttpServletResponse) response;
- CompressionServletResponseWrapper wrappedResponse =
- new CompressionServletResponseWrapper(hsr);
-
- wrappedResponse.setCompressionThreshold(compressionThreshold);
-
- try {
- chain.doFilter(request, wrappedResponse);
- } finally {
- wrappedResponse.finishResponse();
- }
+ CompressionServletResponseWrapper wrappedResponse =
+ new CompressionServletResponseWrapper(response, request);
+
+ wrappedResponse.setCompressionThreshold(compressionThreshold);
+
+ try {
+ chain.doFilter(request, wrappedResponse);
+ } finally {
+ wrappedResponse.finishResponse();
}
}
}
@@ -215,6 +198,46 @@
// ------------------------------------------------------ Protected Methods
/**
+ * Return true if the response should be GZIP compressed.
+ *
+ * @param request the request to test
+ * @param response the response to test
+ * @param path the request path to test
+ * @return true if the response should be GZIP compressed
+ */
+ protected boolean useGzipCompression(HttpServletRequest request,
+ HttpServletResponse response, String path) {
+
+ // If Content-Encoding header is already set on response, skip compression
+ if (response.containsHeader("Content-Encoding")) {
+ return false;
+ }
+
+ // Are we allowed to compress ?
+ String s = ((HttpServletRequest) request).getParameter("gzip");
+ if ("false".equals(s)) {
+ return false;
+ }
+
+ if (compressionThreshold > 0) {
+ if (path.endsWith(".gif") || path.endsWith(".png") || path.endsWith(".jpg")) {
+ return false;
+ }
+
+ Enumeration e = request.getHeaders("Accept-Encoding");
+
+ while (e.hasMoreElements()) {
+ String name = (String) e.nextElement();
+ if (name.indexOf("gzip") != -1) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
* Return the application configuration service.
*
* @return the application configuration service
Modified: incubator/click/trunk/click/extras/src/org/apache/click/extras/filter/CompressionResponseStream.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/extras/src/org/apache/click/extras/filter/CompressionResponseStream.java?rev=782077&r1=782076&r2=782077&view=diff
==============================================================================
--- incubator/click/trunk/click/extras/src/org/apache/click/extras/filter/CompressionResponseStream.java (original)
+++ incubator/click/trunk/click/extras/src/org/apache/click/extras/filter/CompressionResponseStream.java Fri Jun 5 17:48:27 2009
@@ -1,25 +1,26 @@
/*
-* Copyright 2004 The Apache Software Foundation
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-
+ * Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package org.apache.click.extras.filter;
import java.io.IOException;
+import java.io.OutputStream;
import java.util.zip.GZIPOutputStream;
import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
@@ -35,23 +36,6 @@
*/
public class CompressionResponseStream extends ServletOutputStream {
- // ----------------------------------------------------------- Constructors
-
- /**
- * Construct a servlet output stream associated with the specified Response.
- *
- * @param response The associated response
- * @throws IOException if an IO error occurs reading the response stream
- */
- public CompressionResponseStream(HttpServletResponse response)
- throws IOException {
-
- super();
- closed = false;
- this.response = response;
- this.output = response.getOutputStream();
- }
-
// ----------------------------------------------------- Instance Variables
/**
@@ -74,7 +58,7 @@
/**
* The underlying gzip output stream to which we should write data.
*/
- protected GZIPOutputStream gzipstream = null;
+ protected OutputStream gzipstream = null;
/** Has this stream been closed? */
protected boolean closed = false;
@@ -85,15 +69,36 @@
*/
protected int length = -1;
+ /** The response with which this servlet output stream is associated. */
+ protected HttpServletResponse response = null;
+
+ /** The request with which this servlet is associated. */
+ protected HttpServletRequest request;
+
/**
- * The response with which this servlet output stream is associated.
+ * The underlying output stream, either gzipped or servlet, to which we
+ * should write data.
*/
- protected HttpServletResponse response = null;
+ protected OutputStream output = null;
+
+ // ----------------------------------------------------------- Constructors
/**
- * The underlying servket output stream to which we should write data.
+ * Construct a servlet output stream associated with the specified Response.
+ *
+ * @param response The associated response
+ * @param request The associated request
+ * @throws IOException if an IO error occurs reading the response stream
*/
- protected ServletOutputStream output = null;
+ public CompressionResponseStream(HttpServletResponse response,
+ HttpServletRequest request) throws IOException {
+
+ super();
+ this.closed = false;
+ this.response = response;
+ this.request = request;
+ this.output = response.getOutputStream();
+ }
// --------------------------------------------------------- Public Methods
@@ -108,35 +113,41 @@
}
/**
- * Close this output stream, causing any buffered data to be flushed and
- * any further output data to throw an IOException.
+ * Close this output stream, causing any buffered data to be flushed.
+ * Consecutive calls to this method will be ignored.
*
* @throws IOException if an error occurs closing the response
*/
public void close() throws IOException {
- if (closed) {
- throw new IOException("This output stream has already been closed");
- }
+ if (!closed) {
- if (gzipstream != null) {
- flushToGZip();
- gzipstream.close();
- gzipstream = null;
- } else {
- if (bufferCount > 0) {
- if (debug > 2) {
- System.out.print("output.write(");
- System.out.write(buffer, 0, bufferCount);
- System.out.println(")");
+ // Don't close if this is a server side include
+ if (request.getAttribute("javax.servlet.include.request_uri") != null) {
+ flush();
+
+ } else {
+ if (gzipstream != null) {
+ flushToGZip();
+ gzipstream.close();
+ gzipstream = null;
+ } else {
+ if (bufferCount > 0) {
+ if (debug > 2) {
+ System.out.print("output.write(");
+ System.out.write(buffer, 0, bufferCount);
+ System.out.println(")");
+ }
+ output.write(buffer, 0, bufferCount);
+ bufferCount = 0;
+ }
}
- output.write(buffer, 0, bufferCount);
- bufferCount = 0;
+
+ output.close();
+ output = null;
+ closed = true;
}
}
-
- output.close();
- closed = true;
}
/**
@@ -147,12 +158,11 @@
*/
public void flush() throws IOException {
- if (closed) {
- throw new IOException("Cannot flush a closed output stream");
- }
+ if (!closed) {
- if (gzipstream != null) {
- gzipstream.flush();
+ if (gzipstream != null) {
+ gzipstream.flush();
+ }
}
}
@@ -240,7 +250,6 @@
writeToGZip(b, off, len);
}
-
/**
* Writes array of bytes to the compressed output stream. This method
* will block until all the bytes are written.
@@ -248,20 +257,13 @@
* @param b the data to be written
* @param off the start offset of the data
* @param len the length of the data
- * @exception IOException If an I/O error has occurred.
+ * @throws IOException If an I/O error has occurred.
*/
public void writeToGZip(byte b[], int off, int len) throws IOException {
-
- if (gzipstream == null) {
- response.addHeader("Content-Encoding", "gzip");
- gzipstream = new GZIPOutputStream(output);
- }
-
+ initializeGzip();
gzipstream.write(b, off, len);
}
- // -------------------------------------------------------- Package Methods
-
/**
* Has this response stream been closed?
*
@@ -271,4 +273,55 @@
return (this.closed);
}
+ // ------------------------------------------------------ Protected Methods
+
+ /**
+ * Initialize the GZip output stream.
+ * <p/>
+ * This method delgates to {@link #setContentEncodingGZip()} to set the
+ * GZip response Content-Encoding header.
+ *
+ * @throws IOException If an I/O error has occurred
+ */
+ protected void initializeGzip() throws IOException {
+
+ if (gzipstream == null) {
+
+ if (debug > 1) {
+ System.out.println("new GZIPOutputStream");
+ }
+
+ if (response.isCommitted()) {
+ if (debug > 1) {
+ System.out.print("Response already committed. Using original"
+ + " output stream");
+ }
+ gzipstream = output;
+ }
+ else if (setContentEncodingGZip()) {
+ // If we can set the Content-Encoding header to gzip, create a
+ // new gzip stream
+ gzipstream = new GZIPOutputStream(response.getOutputStream());
+ } else {
+ // If we cannot set the Content-Encoding header, use original
+ // output stream
+ gzipstream = output;
+ }
+ }
+ }
+
+ /**
+ * Set the "<tt>Content-Encoding</tt>" header of the response to
+ * "<tt>gzip</tt>", returning true if the header was set, false otherwise.
+ * <p/>
+ * This method will return false when it is invoked from a server side
+ * include (<jsp:include>), since its not possible to alter the headers
+ * of an included response.
+ *
+ * @return true if the content encoding was set, false otherwise
+ */
+ protected boolean setContentEncodingGZip() {
+ response.addHeader("Content-Encoding", "gzip");
+ return response.containsHeader("Content-Encoding");
+ }
}
Modified: incubator/click/trunk/click/extras/src/org/apache/click/extras/filter/CompressionServletResponseWrapper.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/extras/src/org/apache/click/extras/filter/CompressionServletResponseWrapper.java?rev=782077&r1=782076&r2=782077&view=diff
==============================================================================
--- incubator/click/trunk/click/extras/src/org/apache/click/extras/filter/CompressionServletResponseWrapper.java (original)
+++ incubator/click/trunk/click/extras/src/org/apache/click/extras/filter/CompressionServletResponseWrapper.java Fri Jun 5 17:48:27 2009
@@ -1,19 +1,18 @@
/*
-* Copyright 2004 The Apache Software Foundation
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-
+ * Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package org.apache.click.extras.filter;
import java.io.IOException;
@@ -21,6 +20,7 @@
import java.io.PrintWriter;
import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
@@ -44,10 +44,12 @@
* wrapping the given response object.
*
* @param response the servlet response to wrap
+ * @param request The associated request
*/
- public CompressionServletResponseWrapper(HttpServletResponse response) {
+ public CompressionServletResponseWrapper(HttpServletResponse response, HttpServletRequest request) {
super(response);
origResponse = response;
+ origRequest = request;
}
// ----------------------------------------------------- Instance Variables
@@ -55,6 +57,9 @@
/** Original response. */
protected HttpServletResponse origResponse = null;
+ /** The request with which this servlet is associated. */
+ protected HttpServletRequest origRequest;
+
/** Descriptive information about this Response implementation. */
protected static final String INFO = "CompressionServletResponseWrapper";
@@ -110,7 +115,7 @@
public ServletOutputStream createOutputStream() throws IOException {
CompressionResponseStream stream =
- new CompressionResponseStream(origResponse);
+ new CompressionResponseStream(origResponse, origRequest);
stream.setBuffer(threshold);
return stream;
Modified: incubator/click/trunk/click/extras/src/org/apache/click/extras/filter/PerformanceFilter.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/extras/src/org/apache/click/extras/filter/PerformanceFilter.java?rev=782077&r1=782076&r2=782077&view=diff
==============================================================================
--- incubator/click/trunk/click/extras/src/org/apache/click/extras/filter/PerformanceFilter.java (original)
+++ incubator/click/trunk/click/extras/src/org/apache/click/extras/filter/PerformanceFilter.java Fri Jun 5 17:48:27 2009
@@ -378,10 +378,10 @@
final boolean isVersionedResourcePath = (realPath.length() != path.length());
// Apply response compression
- if (useGzipCompression(request, path)) {
+ if (useGzipCompression(request, response, path)) {
CompressionServletResponseWrapper wrappedResponse =
- new CompressionServletResponseWrapper(response);
+ new CompressionServletResponseWrapper(response, request);
wrappedResponse.setCompressionThreshold(compressionThreshold);
@@ -679,10 +679,17 @@
* Return true if the response should be GZIP compressed.
*
* @param request the request to test
+ * @param response the response to test
* @param path the request path to test
* @return true if the response should be GZIP compressed
*/
- protected boolean useGzipCompression(HttpServletRequest request, String path) {
+ protected boolean useGzipCompression(HttpServletRequest request,
+ HttpServletResponse response, String path) {
+
+ // If Content-Encoding header is already set on response, skip compression
+ if (response.containsHeader("Content-Encoding")) {
+ return false;
+ }
if (compressionThreshold > 0) {
if (path.endsWith(".gif") || path.endsWith(".png") || path.endsWith(".jpg")) {