001: package com.opensymphony.webwork.dispatcher;
002:
003: import com.opensymphony.xwork.ActionContext;
004: import com.opensymphony.xwork.interceptor.component.ComponentManager;
005:
006: import javax.servlet.*;
007: import javax.servlet.http.HttpServletRequest;
008: import javax.servlet.http.HttpServletResponse;
009: import java.io.IOException;
010:
011: import org.apache.commons.logging.Log;
012: import org.apache.commons.logging.LogFactory;
013:
014: /**
015: * <!-- SNIPPET START: description -->
016: * Special filter designed to work with the {@link FilterDispatcher} and allow
017: * for easier integration with SiteMesh. Normally, ordering your filters to have
018: * SiteMesh go first, and then {@link FilterDispatcher} go second is perfectly fine.
019: * However, sometimes you may wish to access WebWork-features, including the
020: * value stack, from within your SiteMesh decorators. Because {@link FilterDispatcher}
021: * cleans up the {@link ActionContext}, your decorator won't have access to the
022: * date you want.
023: * <p/>
024: * <p/>
025: * By adding this filter, the {@link FilterDispatcher} will know to not clean up and
026: * instead defer cleanup to this filter. The ordering of the filters should then be:
027: * <p/>
028: * <ul>
029: * <li>this filter</li>
030: * <li>SiteMesh filter</li>
031: * <li>{@link FilterDispatcher}</li>
032: * </ul>
033: * <!-- SNIPPET END: description -->
034: *
035: * @author Patrick Lightbody
036: * @author Pete Matern
037: * @see FilterDispatcher
038: * @since 2.2
039: */
040: public class ActionContextCleanUp implements Filter {
041:
042: private static final Log LOG = LogFactory
043: .getLog(ActionContextCleanUp.class);
044:
045: private static final String COUNTER = "__cleanup_counter";
046:
047: protected FilterConfig filterConfig;
048:
049: public FilterConfig getFilterConfig() {
050: return filterConfig;
051: }
052:
053: public void init(FilterConfig filterConfig) throws ServletException {
054: this .filterConfig = filterConfig;
055: DispatcherUtils.initialize(filterConfig.getServletContext());
056: }
057:
058: public void doFilter(ServletRequest req, ServletResponse res,
059: FilterChain chain) throws IOException, ServletException {
060:
061: HttpServletRequest request = (HttpServletRequest) req;
062: HttpServletResponse response = (HttpServletResponse) res;
063:
064: // prepare the request no matter what - this ensures that the proper character encoding
065: // is used before invoking the mapper (see WW-9127)
066: DispatcherUtils du = DispatcherUtils.getInstance();
067: du.prepare(request, response);
068:
069: ServletContext servletContext = filterConfig
070: .getServletContext();
071: try {
072: request = du.wrapRequest(request, servletContext);
073: } catch (IOException e) {
074: String message = "Could not wrap servlet request with MultipartRequestWrapper!";
075: LOG.error(message, e);
076: throw new ServletException(message, e);
077: }
078:
079: try {
080:
081: Integer count = (Integer) request.getAttribute(COUNTER);
082: if (count == null) {
083: count = new Integer(1);
084: } else {
085: count = new Integer(count.intValue() + 1);
086: }
087: request.setAttribute(COUNTER, count);
088:
089: chain.doFilter(request, response);
090: } finally {
091:
092: int counterVal = ((Integer) request.getAttribute(COUNTER))
093: .intValue();
094: counterVal -= 1;
095: request.setAttribute(COUNTER, new Integer(counterVal));
096:
097: cleanUp(request);
098: }
099:
100: }
101:
102: protected static void cleanUp(ServletRequest req) {
103: // should we clean up yet
104: if (req.getAttribute(COUNTER) != null
105: && ((Integer) req.getAttribute(COUNTER)).intValue() > 0) {
106: return;
107: }
108:
109: // tear down the component manager if it was created
110: ComponentManager componentManager = (ComponentManager) req
111: .getAttribute(ComponentManager.COMPONENT_MANAGER_KEY);
112: if (componentManager != null) {
113: componentManager.dispose();
114: }
115:
116: // always clean up the thread request, even if an action hasn't been executed
117: ActionContext.setContext(null);
118: }
119:
120: public void destroy() {
121: }
122: }
|