1 /**
2 * Copyright 2003-2007 Greg Luck
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package net.sf.ehcache.constructs.web.filter;
18
19 import net.sf.ehcache.constructs.web.AlreadyGzippedException;
20 import net.sf.ehcache.constructs.web.GenericResponseWrapper;
21 import net.sf.ehcache.constructs.web.PageInfo;
22
23 import javax.servlet.FilterChain;
24 import javax.servlet.http.HttpServletRequest;
25 import javax.servlet.http.HttpServletResponse;
26 import java.io.ByteArrayOutputStream;
27 import java.io.IOException;
28
29
30 /**
31 * A Template for a page caching filter that is designed for "included" pages, eg: jsp:includes. This filter
32 * differs from the {@link CachingFilter} in that it is not writing an entire response to the output stream.
33 * <p/>
34 * This class should be sub-classed for each included page to be cached.
35 * <p/>
36 * Filter Mappings need to be set up for a cache to have effect.
37 *
38 * @author <a href="mailto:gluck@thoughtworks.com">Greg Luck</a>
39 * @version $Id: PageFragmentCachingFilter.java 512 2007-07-10 09:18:45Z gregluck $
40 */
41 public abstract class PageFragmentCachingFilter extends CachingFilter {
42
43 /**
44 * Performs the filtering for a request.
45 */
46 protected void doFilter(final HttpServletRequest request, final HttpServletResponse response,
47 final FilterChain chain) throws Exception {
48
49 PageInfo pageInfo = buildPageInfo(request, response, chain);
50
51 // Send the page to the client
52 writeResponse(response, pageInfo);
53 }
54
55 /**
56 * {@inheritDoc}
57 *
58 * @param request {@inheritDoc}
59 * @param response {@inheritDoc}
60 * @param chain {@inheritDoc}
61 * @return {@inheritDoc}
62 * @throws AlreadyGzippedException {@inheritDoc}
63 * @throws Exception {@inheritDoc}
64 */
65 protected PageInfo buildPage(final HttpServletRequest request, final HttpServletResponse response,
66 final FilterChain chain) throws AlreadyGzippedException, Exception {
67
68 // Invoke the next entity in the chain
69 final ByteArrayOutputStream outstr = new ByteArrayOutputStream();
70 final GenericResponseWrapper wrapper = new GenericResponseWrapper(response, outstr);
71 chain.doFilter(request, wrapper);
72 wrapper.flush();
73
74 // Return the page info
75 return new PageInfo(wrapper.getStatus(), wrapper.getContentType(), wrapper.getHeaders(), wrapper.getCookies(),
76 outstr.toByteArray(), false);
77 }
78
79
80 /**
81 * Assembles a response from a cached page include.
82 * These responses are never gzipped
83 * The content length should not be set in the response, because it is a fragment of a page.
84 * Don't write any headers at all.
85 */
86 protected void writeResponse(final HttpServletResponse response, final PageInfo pageInfo) throws IOException {
87 // Write the page
88 final byte[] cachedPage = pageInfo.getUngzippedBody();
89
90 String implementationVendor = response.getClass().getPackage().getImplementationVendor();
91 if (implementationVendor != null && implementationVendor.equals("\"Evermind\"")) {
92 response.getOutputStream().write(cachedPage);
93 } else {
94 response.getWriter().write(new String(cachedPage));
95 }
96 }
97 }