001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. The ASF licenses this file to You
004: * under the Apache License, Version 2.0 (the "License"); you may not
005: * 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. For additional information regarding
015: * copyright in this work, please see the NOTICE file in the top level
016: * directory of this distribution.
017: */
018:
019: package org.apache.roller.ui.core.filters;
020:
021: import java.io.ByteArrayOutputStream;
022: import java.io.IOException;
023: import java.util.zip.GZIPOutputStream;
024: import javax.servlet.Filter;
025: import javax.servlet.FilterChain;
026: import javax.servlet.FilterConfig;
027: import javax.servlet.ServletException;
028: import javax.servlet.ServletRequest;
029: import javax.servlet.ServletResponse;
030: import javax.servlet.http.HttpServletRequest;
031: import javax.servlet.http.HttpServletResponse;
032: import org.apache.commons.logging.Log;
033: import org.apache.commons.logging.LogFactory;
034: import org.apache.roller.config.RollerConfig;
035: import org.apache.roller.ui.core.util.ByteArrayOutputStreamWrapper;
036: import org.apache.roller.ui.core.util.ByteArrayResponseWrapper;
037:
038: /**
039: * Filter that compresses output with gzip (assuming that browser supports gzip).
040: * <P>
041: * Taken from More Servlets and JavaServer Pages from Prentice Hall and
042: * Sun Microsystems Press, http://www.moreservlets.com/.
043: * © 2002 Marty Hall; may be freely used or adapted.
044: *
045: * @web.filter name="CompressionFilter"
046: */
047:
048: public class CompressionFilter implements Filter {
049:
050: private static Log mLogger = LogFactory
051: .getLog(CompressionFilter.class);
052:
053: private boolean enabled = true;
054:
055: /**
056: * If browser does not support gzip, invoke resource normally. If browser
057: * does support gzip, set the Content-Encoding response header and invoke
058: * resource with a wrapped response that collects all the output. Extract
059: * the output and write it into a gzipped byte array. Finally, write that
060: * array to the client's output stream.
061: */
062: public void doFilter(ServletRequest request,
063: ServletResponse response, FilterChain chain)
064: throws ServletException, IOException {
065:
066: HttpServletRequest req = (HttpServletRequest) request;
067: HttpServletResponse res = (HttpServletResponse) response;
068:
069: if (!this .enabled || !isGzipSupported(req)) {
070: // Invoke resource normally.
071: chain.doFilter(req, res);
072: } else {
073: // Tell browser we are sending it gzipped data.
074: res.setHeader("Content-Encoding", "gzip");
075:
076: // Invoke resource, accumulating output in the wrapper.
077: ByteArrayResponseWrapper responseWrapper = new ByteArrayResponseWrapper(
078: response);
079:
080: chain.doFilter(req, responseWrapper);
081:
082: ByteArrayOutputStream outputStream = responseWrapper
083: .getByteArrayOutputStream();
084:
085: // Get character array representing output.
086: mLogger.debug("Pre-zip size:" + outputStream.size());
087:
088: // Make a writer that compresses data and puts
089: // it into a byte array.
090: ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
091: GZIPOutputStream zipOut = new GZIPOutputStream(byteStream);
092:
093: // Compress original output and put it into byte array.
094: zipOut.write(responseWrapper.getByteArrayOutputStream()
095: .toByteArray());
096:
097: // Gzip streams must be explicitly closed.
098: zipOut.close();
099:
100: mLogger.debug("Gzip size:" + byteStream.size());
101:
102: // Update the Content-Length header.
103: res.setContentLength(byteStream.size());
104:
105: ByteArrayOutputStreamWrapper newOut = (ByteArrayOutputStreamWrapper) responseWrapper
106: .getOutputStream();
107: newOut.clear();
108: newOut.setFinallized();
109:
110: /* now force close of OutputStream */
111: newOut.write(byteStream.toByteArray());
112: newOut.close();
113: }
114:
115: }
116:
117: public void init(FilterConfig config) throws ServletException {
118:
119: // is compression enabled?
120: if (RollerConfig
121: .getBooleanProperty("compression.gzipResponse.enabled")) {
122: this .enabled = true;
123: mLogger.info("Compressed Output ENABLED");
124: } else {
125: this .enabled = false;
126: mLogger.info("Compressed Output DISABLED");
127: }
128: }
129:
130: public void destroy() {
131: }
132:
133: private boolean isGzipSupported(HttpServletRequest req) {
134: String browserEncodings = req.getHeader("Accept-Encoding");
135: return ((browserEncodings != null) && (browserEncodings
136: .indexOf("gzip") != -1));
137: }
138:
139: }
|