Clover icon

Magnolia Module Cache 5.5.9

  1. Project Clover database Mon Nov 25 2019 16:46:50 CET
  2. Package info.magnolia.module.cache.filter

File GZipFilter.java

 

Coverage histogram

../../../../../img/srcFileCovDistChart8.png
37% of files have more coverage

Code metrics

12
33
11
4
191
100
18
0.55
3
2.75
1.64
6.7% of code in this file is excluded from these metrics.

Classes

Class Line # Actions
GZipFilter 58 17 0% 6 4
0.8484%
GZipFilter.GZipCacheResponseWrapper 109 6 26.7% 4 6
0.4545454745.5%
GZipFilter.GZipCacheResponseWrapper.DeferredServletOutputStream 146 9 0% 6 5
0.705882470.6%
GZipFilter.GzipThresholdingCacheOutputStream 179 1 0% 2 0
1.0100%
 

Contributing tests

This file is covered by 4 tests. .

Source view

1    /**
2    * This file Copyright (c) 2008-2018 Magnolia International
3    * Ltd. (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10    * This file is distributed in the hope that it will be
11    * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12    * implied warranty of MERCHANTABILITY or FITNESS FOR A
13    * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14    * Redistribution, except as permitted by whichever of the GPL
15    * or MNA you select, is prohibited.
16    *
17    * 1. For the GPL license (GPL), you can redistribute and/or
18    * modify this file under the terms of the GNU General
19    * Public License, Version 3, as published by the Free Software
20    * Foundation. You should have received a copy of the GNU
21    * General Public License, Version 3 along with this program;
22    * if not, write to the Free Software Foundation, Inc., 51
23    * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24    *
25    * 2. For the Magnolia Network Agreement (MNA), this file
26    * and the accompanying materials are made available under the
27    * terms of the MNA which accompanies this distribution, and
28    * is available at http://www.magnolia-cms.com/mna.html
29    *
30    * Any modifications to this file must keep this entire header
31    * intact.
32    *
33    */
34    package info.magnolia.module.cache.filter;
35   
36    import info.magnolia.cms.filters.OncePerRequestAbstractMgnlFilter;
37    import info.magnolia.cms.util.RequestHeaderUtil;
38    import info.magnolia.module.cache.util.GZipUtil;
39   
40    import java.io.IOException;
41   
42    import javax.servlet.FilterChain;
43    import javax.servlet.ServletException;
44    import javax.servlet.ServletOutputStream;
45    import javax.servlet.http.HttpServletRequest;
46    import javax.servlet.http.HttpServletResponse;
47   
48    /**
49    * This GZipFilter does not take care of the Accept-Encoding request header. The CacheFilter will
50    * take care of serving the unzipped content if appropriate.
51    * <strong>By default, the Magnolia main filter is not dispatched to in case of include requests - if
52    * this is the case this filter has to be bypassed for such requests !</strong>
53    *
54    * @see info.magnolia.module.cache.filter.StandaloneGZipFilter if the cache filter is not in use.
55    * @author gjoseph
56    * @version $Revision: $ ($Author: $)
57    */
 
58    public class GZipFilter extends OncePerRequestAbstractMgnlFilter {
59   
 
60  0 toggle @Override
61    public boolean bypasses(HttpServletRequest request) {
62  0 return !GZipUtil.isAcceptsGzip(request) || super.bypasses(request);
63    }
64   
 
65  4 toggle @Override
66    public void doFilter(HttpServletRequest request, final HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
67    // we need to setContentLength before writing content ...
68    // (otherwise Tomcat adds a Transfer-Encoding: chunked header, which seems to cause trouble
69    // to browsers ...)
70   
71  4 final GZipCacheResponseWrapper responseWrapper = new GZipCacheResponseWrapper(response, CacheResponseWrapper.DEFAULT_THRESHOLD, true);
72   
73  4 chain.doFilter(request, responseWrapper);
74   
75    // flush only internal buffers, not the actual response's !
76  4 responseWrapper.flush();
77   
78    // otherwise the content was already streamed
79  4 if (!responseWrapper.isGzipResponseDetected()) {
80  4 byte[] array = responseWrapper.getBufferedContent();
81   
82    // GZIP only 200 SC_OK responses as in other cases response might be already committed - only dump bytes and flush ...
83  4 int statusCode = responseWrapper.getStatus();
84  4 if (statusCode == HttpServletResponse.SC_OK && !GZipUtil.isGZipped(array)) {
85  3 responseWrapper.replayHeadersAndStatus(response);
86   
87  3 RequestHeaderUtil.addAndVerifyHeader(response, "Content-Encoding", "gzip");
88  3 RequestHeaderUtil.addAndVerifyHeader(response, "Vary", "Accept-Encoding"); // needed for proxies
89   
90  3 array = GZipUtil.gzip(array);
91  3 response.setContentLength(array.length);
92  3 if (array.length > 0) {
93  3 response.getOutputStream().write(array);
94    }
95    }
96    else {
97  1 responseWrapper.replay(response);
98    }
99   
100  4 response.flushBuffer();
101    }
102    }
103   
104    /**
105    * Detects if the response has the "Content-Encoding" header set. If so it will stream it through.
106    *
107    * @version $Id$
108    */
 
109    public static final class GZipCacheResponseWrapper extends CacheResponseWrapper {
110   
111    private final HttpServletResponse response;
112   
113    private boolean gzipResponseDetected;
114   
115    private ServletOutputStream deferredOutputStream = new DeferredServletOutputStream();
116   
 
117    toggle public boolean isGzipResponseDetected() {
118    return gzipResponseDetected;
119    }
120   
 
121  4 toggle private GZipCacheResponseWrapper(HttpServletResponse response, int threshold, boolean serveIfThresholdReached) {
122  4 super(response, threshold, serveIfThresholdReached, new GzipThresholdingCacheOutputStream(threshold));
123  4 this.response = response;
124    }
125   
 
126  0 toggle @Override
127    public void addHeader(String name, String value) {
128  0 if (name.equals("Content-Encoding")) {
129  0 gzipResponseDetected = true;
130    }
131  0 super.addHeader(name, value);
132    }
133   
 
134  3 toggle private ServletOutputStream getWrappedOutputStream() throws IOException {
135  3 return super.getOutputStream();
136    }
137   
 
138    toggle @Override
139    public ServletOutputStream getOutputStream() {
140    return deferredOutputStream;
141    }
142   
143    /**
144    * Only gets the real output stream once we are writing. If we have detected a gzip response we will just stream it through.
145    */
 
146    private final class DeferredServletOutputStream extends ServletOutputStream {
147   
148    private ServletOutputStream stream;
149   
 
150  1016217 toggle @Override
151    public void write(int b) throws IOException {
152  1016217 getStream().write(b);
153    }
154   
 
155  0 toggle @Override
156    public void write(byte[] b) throws IOException {
157  0 getStream().write(b);
158    }
159   
 
160  8 toggle @Override
161    public void write(byte[] b, int off, int len) throws IOException {
162  8 getStream().write(b, off, len);
163    }
164   
 
165  1016225 toggle private ServletOutputStream getStream() throws IOException {
166  1016225 if (stream == null) {
167  3 if (gzipResponseDetected) {
168  0 replayHeadersAndStatus(response);
169  0 stream = response.getOutputStream();
170    } else {
171  3 stream = getWrappedOutputStream();
172    }
173    }
174  1016225 return stream;
175    }
176    }
177    }
178   
 
179    private final static class GzipThresholdingCacheOutputStream extends AbstractThresholdingCacheOutputStream {
180   
 
181  4 toggle public GzipThresholdingCacheOutputStream(int threshold) {
182  4 super(threshold);
183    }
184   
 
185  1 toggle @Override
186    protected void thresholdReached() throws IOException {
187    // do nothing
188    }
189    }
190   
191    }