1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.struts2.dispatcher;
19
20 import java.io.IOException;
21
22 import javax.servlet.Filter;
23 import javax.servlet.FilterChain;
24 import javax.servlet.FilterConfig;
25 import javax.servlet.ServletContext;
26 import javax.servlet.ServletException;
27 import javax.servlet.ServletRequest;
28 import javax.servlet.ServletResponse;
29 import javax.servlet.http.HttpServletRequest;
30 import javax.servlet.http.HttpServletResponse;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34
35 import com.opensymphony.xwork2.ActionContext;
36 import com.opensymphony.xwork2.util.profiling.UtilTimerStack;
37
38 /***
39 * <!-- SNIPPET START: description -->
40 * Special filter designed to work with the {@link FilterDispatcher} and allow
41 * for easier integration with SiteMesh. Normally, ordering your filters to have
42 * SiteMesh go first, and then {@link FilterDispatcher} go second is perfectly fine.
43 * However, sometimes you may wish to access Struts features, including the
44 * value stack, from within your SiteMesh decorators. Because {@link FilterDispatcher}
45 * cleans up the {@link ActionContext}, your decorator won't have access to the
46 * date you want.
47 * <p/>
48 * <p/>
49 * By adding this filter, the {@link FilterDispatcher} will know to not clean up and
50 * instead defer cleanup to this filter. The ordering of the filters should then be:
51 * <p/>
52 * <ul>
53 * <li>this filter</li>
54 * <li>SiteMesh filter</li>
55 * <li>{@link FilterDispatcher}</li>
56 * </ul>
57 * <!-- SNIPPET END: description -->
58 *
59 * @version $Date: 2006-10-10 07:31:52 -0500 (Tue, 10 Oct 2006) $ $Id: ActionContextCleanUp.java 454720 2006-10-10 12:31:52Z tmjee $
60 *
61 * @see FilterDispatcher
62 */
63 public class ActionContextCleanUp implements Filter {
64
65 private static final Log LOG = LogFactory.getLog(ActionContextCleanUp.class);
66
67 private static final String COUNTER = "__cleanup_recursion_counter";
68
69 protected FilterConfig filterConfig;
70 protected Dispatcher dispatcher;
71
72 /***
73 * Initializes the filter
74 *
75 * @param filterConfig The filter configuration
76 */
77 public void init(FilterConfig filterConfig) throws ServletException {
78 this.filterConfig = filterConfig;
79 dispatcher = new Dispatcher(filterConfig.getServletContext());
80 }
81
82
83 /***
84 * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
85 */
86 public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
87
88 HttpServletRequest request = (HttpServletRequest) req;
89 HttpServletResponse response = (HttpServletResponse) res;
90
91 String timerKey = "ActionContextCleanUp_doFilter: ";
92 try {
93 UtilTimerStack.push(timerKey);
94
95
96
97 Dispatcher.setInstance(dispatcher);
98 dispatcher.prepare(request, response);
99
100 ServletContext servletContext = filterConfig.getServletContext();
101 try {
102 request = dispatcher.wrapRequest(request, servletContext);
103 } catch (IOException e) {
104 String message = "Could not wrap servlet request with MultipartRequestWrapper!";
105 LOG.error(message, e);
106 throw new ServletException(message, e);
107 }
108
109 try {
110 Integer count = (Integer)request.getAttribute(COUNTER);
111 if (count == null) {
112 count = new Integer(1);
113 }
114 else {
115 count = new Integer(count.intValue()+1);
116 }
117 request.setAttribute(COUNTER, count);
118 chain.doFilter(request, response);
119 } finally {
120 int counterVal = ((Integer)request.getAttribute(COUNTER)).intValue();
121 counterVal -= 1;
122 request.setAttribute(COUNTER, new Integer(counterVal));
123 cleanUp(request);
124 }
125 }
126 finally {
127 UtilTimerStack.pop(timerKey);
128 }
129 }
130
131 /***
132 * Clean up the request of threadlocals if this is the last execution
133 *
134 * @param req The servlet request
135 */
136 protected static void cleanUp(ServletRequest req) {
137
138 if (req.getAttribute(COUNTER) != null &&
139 ((Integer)req.getAttribute(COUNTER)).intValue() > 0 ) {
140 return;
141 }
142
143
144 ActionContext.setContext(null);
145
146 Dispatcher.setInstance(null);
147 }
148
149
150
151
152
153 public void destroy() {
154 }
155 }