1 /**
2 * Licensed under the Artistic License; you may not use this file
3 * except in compliance with the License.
4 * You may obtain a copy of the License at
5 *
6 * http://displaytag.sourceforge.net/license.html
7 *
8 * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
9 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
10 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11 */
12 package org.displaytag.filter;
13
14 import java.io.IOException;
15 import java.util.HashMap;
16 import java.util.Map;
17
18 import javax.servlet.Filter;
19 import javax.servlet.FilterChain;
20 import javax.servlet.FilterConfig;
21 import javax.servlet.ServletException;
22 import javax.servlet.ServletRequest;
23 import javax.servlet.ServletResponse;
24 import javax.servlet.http.HttpServletRequest;
25 import javax.servlet.http.HttpServletResponse;
26
27 import org.apache.commons.lang.StringUtils;
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.displaytag.Messages;
31 import org.displaytag.tags.TableTag;
32 import org.displaytag.tags.TableTagParameters;
33
34
35 /**
36 * <p>
37 * Allow the author of an included JSP page to reset the content type to something else (like a binary stream), and then
38 * write the new info back as the exclusive response, clearing the buffers of all previously added content.
39 * </p>
40 * <p>
41 * This filter allows TableTag users to perform exports from pages that are run as includes, such as from Struts or a
42 * jsp:include. If that is your intention, just add this Filter to your web.xml and map it to the appropriate requests,
43 * using something like:
44 * </p>
45 *
46 * <pre>
47 * <filter>
48 * <filter-name>ResponseOverrideFilter</filter-name>
49 * <filter-class>org.displaytag.filter.ResponseOverrideFilter</filter-class>
50 * </filter>
51 * <filter-mapping>
52 * <filter-name>ResponseOverrideFilter</filter-name>
53 * <url-pattern>*.do</url-pattern>
54 * </filter-mapping>
55 * <filter-mapping>
56 * <filter-name>ResponseOverrideFilter</filter-name>
57 * <url-pattern>*.jsp</url-pattern>
58 * </filter-mapping>
59 * </pre>
60 *
61 * <p>
62 * By default the filter buffers all the export content before writing it out. You can set an optional parameter
63 * <code>buffer</code> to <code>false</code> to make the filter write directly to the output stream. This could be
64 * faster and uses less memory, but the content length will not be set.
65 * </p>
66 *
67 * <pre>
68 * <filter>
69 * <filter-name>ResponseOverrideFilter</filter-name>
70 * <filter-class>org.displaytag.filter.ResponseOverrideFilter</filter-class>
71 * <init-param>
72 * <param-name>buffer</param-name>
73 * <param-value>false</param-value>
74 * </init-param>
75 * </filter>
76 * </pre>
77 *
78 * @author rapruitt
79 * @author Fabrizio Giustina
80 * @version $Revision: 1081 $ ($Author: fgiust $)
81 */
82 public class ResponseOverrideFilter implements Filter
83 {
84
85 /**
86 * Logger.
87 */
88 private Log log;
89
90 /**
91 * Force response buffering. Enabled by default.
92 */
93 private boolean buffer = true;
94
95 /**
96 * {@inheritDoc}
97 */
98 public void init(FilterConfig filterConfig)
99 {
100 log = LogFactory.getLog(ResponseOverrideFilter.class);
101 String bufferParam = filterConfig.getInitParameter("buffer");
102 if (log.isDebugEnabled())
103 {
104 log.debug("bufferParam=" + bufferParam);
105 }
106 buffer = bufferParam == null || StringUtils.equalsIgnoreCase("true", bufferParam);
107
108 log.info("Filter initialized. Response buffering is " + (buffer ? "enabled" : "disabled"));
109 }
110
111 /**
112 * {@inheritDoc}
113 */
114 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
115 throws IOException, ServletException
116 {
117
118 if (servletRequest.getParameter(TableTagParameters.PARAMETER_EXPORTING) == null)
119 {
120 if (log.isDebugEnabled())
121 {
122 log.debug(Messages.getString("ResponseOverrideFilter.parameternotfound")); //$NON-NLS-1$
123 }
124 // don't filter!
125 filterChain.doFilter(servletRequest, servletResponse);
126 return;
127 }
128
129 HttpServletRequest request = (HttpServletRequest) servletRequest;
130
131 BufferedResponseWrapper wrapper = new BufferedResponseWrapper13Impl((HttpServletResponse) servletResponse);
132
133 Map contentBean = new HashMap(4);
134 if (buffer)
135 {
136 contentBean.put(TableTagParameters.BEAN_BUFFER, Boolean.TRUE);
137 }
138 request.setAttribute(TableTag.FILTER_CONTENT_OVERRIDE_BODY, contentBean);
139
140 filterChain.doFilter(request, wrapper);
141
142 ExportDelegate.writeExport((HttpServletResponse) servletResponse, servletRequest, wrapper);
143 }
144
145 /**
146 * {@inheritDoc}
147 */
148 public void destroy()
149 {
150 // nothing to destroy
151 }
152 }