From 0ce1497cc51ef91c4b47768ea98e769b4d544d26 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 13 May 2012 11:58:12 +0200 Subject: [PATCH] added option to disable buffer for gzip filter --- .../java/sonia/scm/filter/GZipFilter.java | 39 ++++++++- .../sonia/scm/filter/GZipFilterConfig.java | 71 ++++++++++++++++ .../sonia/scm/filter/GZipResponseStream.java | 80 +++++++++++++++---- .../sonia/scm/filter/GZipResponseWrapper.java | 32 +++++++- 4 files changed, 205 insertions(+), 17 deletions(-) create mode 100644 scm-core/src/main/java/sonia/scm/filter/GZipFilterConfig.java diff --git a/scm-core/src/main/java/sonia/scm/filter/GZipFilter.java b/scm-core/src/main/java/sonia/scm/filter/GZipFilter.java index 7780ae623c..32b963053f 100644 --- a/scm-core/src/main/java/sonia/scm/filter/GZipFilter.java +++ b/scm-core/src/main/java/sonia/scm/filter/GZipFilter.java @@ -29,12 +29,17 @@ * */ + + package sonia.scm.filter; //~--- non-JDK imports -------------------------------------------------------- import com.google.inject.Singleton; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import sonia.scm.util.WebUtil; import sonia.scm.web.filter.HttpFilter; @@ -56,6 +61,27 @@ import javax.servlet.http.HttpServletResponse; public class GZipFilter extends HttpFilter { + /** + * the logger for GZipFilter + */ + private static final Logger logger = + LoggerFactory.getLogger(GZipFilter.class); + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + public GZipFilterConfig getConfig() + { + return config; + } + + //~--- methods -------------------------------------------------------------- + /** * Method description * @@ -74,7 +100,13 @@ public class GZipFilter extends HttpFilter { if (WebUtil.isGzipSupported(request)) { - GZipResponseWrapper wrappedResponse = new GZipResponseWrapper(response); + if (logger.isTraceEnabled()) + { + logger.trace("compress output with gzip"); + } + + GZipResponseWrapper wrappedResponse = new GZipResponseWrapper(response, + config); chain.doFilter(request, wrappedResponse); wrappedResponse.finishResponse(); @@ -84,4 +116,9 @@ public class GZipFilter extends HttpFilter chain.doFilter(request, response); } } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private GZipFilterConfig config = new GZipFilterConfig(); } diff --git a/scm-core/src/main/java/sonia/scm/filter/GZipFilterConfig.java b/scm-core/src/main/java/sonia/scm/filter/GZipFilterConfig.java new file mode 100644 index 0000000000..047a56c4e4 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/filter/GZipFilterConfig.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra 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. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 REGENTS OR 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. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.filter; + +/** + * + * @author Sebastian Sdorra + * @since 1.16 + */ +public class GZipFilterConfig +{ + + /** + * Method description + * + * + * @return + */ + public boolean isBufferRequest() + { + return bufferRequest; + } + + //~--- set methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param bufferRequest + * + */ + public void setBufferRequest(boolean bufferRequest) + { + this.bufferRequest = bufferRequest; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private boolean bufferRequest = true; +} diff --git a/scm-core/src/main/java/sonia/scm/filter/GZipResponseStream.java b/scm-core/src/main/java/sonia/scm/filter/GZipResponseStream.java index 564d388e47..c0768a42d6 100644 --- a/scm-core/src/main/java/sonia/scm/filter/GZipResponseStream.java +++ b/scm-core/src/main/java/sonia/scm/filter/GZipResponseStream.java @@ -35,6 +35,9 @@ package sonia.scm.filter; //~--- non-JDK imports -------------------------------------------------------- +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import sonia.scm.util.IOUtil; //~--- JDK imports ------------------------------------------------------------ @@ -55,6 +58,14 @@ import javax.servlet.http.HttpServletResponse; public class GZipResponseStream extends ServletOutputStream { + /** + * the logger for GZipResponseStream + */ + private static final Logger logger = + LoggerFactory.getLogger(GZipResponseStream.class); + + //~--- constructors --------------------------------------------------------- + /** * Constructs ... * @@ -64,13 +75,49 @@ public class GZipResponseStream extends ServletOutputStream * @throws IOException */ public GZipResponseStream(HttpServletResponse response) throws IOException + { + this(response, null); + } + + /** + * Constructs ... + * + * + * @param response + * @param config + * + * @throws IOException + * @since 1.16 + */ + public GZipResponseStream(HttpServletResponse response, + GZipFilterConfig config) + throws IOException { super(); closed = false; this.response = response; - this.output = response.getOutputStream(); - baos = new ByteArrayOutputStream(); - gzipstream = new GZIPOutputStream(baos); + response.addHeader("Content-Encoding", "gzip"); + + if ((config == null) || config.isBufferRequest()) + { + if (logger.isTraceEnabled()) + { + logger.trace("use buffered gzip stream"); + } + + this.output = response.getOutputStream(); + baos = new ByteArrayOutputStream(); + gzipstream = new GZIPOutputStream(baos); + } + else + { + if (logger.isTraceEnabled()) + { + logger.trace("use unbuffered gzip stream"); + } + + gzipstream = new GZIPOutputStream(response.getOutputStream()); + } } //~--- methods -------------------------------------------------------------- @@ -90,20 +137,23 @@ public class GZipResponseStream extends ServletOutputStream } gzipstream.finish(); + gzipstream.close(); - byte[] bytes = baos.toByteArray(); - - response.addIntHeader("Content-Length", bytes.length); - response.addHeader("Content-Encoding", "gzip"); - - try + if (baos != null) { - output.write(bytes); - output.flush(); - } - finally - { - IOUtil.close(output); + byte[] bytes = baos.toByteArray(); + + response.addIntHeader("Content-Length", bytes.length); + + try + { + output.write(bytes); + output.flush(); + } + finally + { + IOUtil.close(output); + } } closed = true; diff --git a/scm-core/src/main/java/sonia/scm/filter/GZipResponseWrapper.java b/scm-core/src/main/java/sonia/scm/filter/GZipResponseWrapper.java index 3d07db0182..d7f0a43da7 100644 --- a/scm-core/src/main/java/sonia/scm/filter/GZipResponseWrapper.java +++ b/scm-core/src/main/java/sonia/scm/filter/GZipResponseWrapper.java @@ -67,6 +67,22 @@ public class GZipResponseWrapper extends HttpServletResponseWrapper origResponse = response; } + /** + * Constructs ... + * + * + * @param response + * @since 1.16 + * @param config + */ + public GZipResponseWrapper(HttpServletResponse response, + GZipFilterConfig config) + { + super(response); + origResponse = response; + this.config = config; + } + //~--- methods -------------------------------------------------------------- /** @@ -100,6 +116,17 @@ public class GZipResponseWrapper extends HttpServletResponseWrapper //~--- get methods ---------------------------------------------------------- + /** + * Method description + * + * + * @return + */ + public GZipFilterConfig getConfig() + { + return config; + } + /** * Method description * @@ -175,11 +202,14 @@ public class GZipResponseWrapper extends HttpServletResponseWrapper */ private GZipResponseStream createOutputStream() throws IOException { - return new GZipResponseStream(origResponse); + return new GZipResponseStream(origResponse, config); } //~--- fields --------------------------------------------------------------- + /** Field description */ + protected GZipFilterConfig config = null; + /** Field description */ protected HttpServletResponse origResponse = null;