You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by tm...@apache.org on 2006/11/15 09:06:57 UTC
svn commit: r475154 - in
/struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher:
AbstractFilter.java ActionContextCleanUp.java FilterDispatcher.java
Author: tmjee
Date: Wed Nov 15 00:06:56 2006
New Revision: 475154
URL: http://svn.apache.org/viewvc?view=rev&rev=475154
Log:
WW-1489
- Refactor ActionContextCleanUp and DispatcherFilter to have common logics in an abstract super class
- moving this back in as discussed in Struts2 maling list.
- This basically allows, (during sitemesh integration) that sitemesh decorators have access to struts internals and request gets wrapped and properly encoded before it reaches sitemesh.
Added:
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/AbstractFilter.java
Modified:
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ActionContextCleanUp.java
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/FilterDispatcher.java
Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/AbstractFilter.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/AbstractFilter.java?view=auto&rev=475154
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/AbstractFilter.java (added)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/AbstractFilter.java Wed Nov 15 00:06:56 2006
@@ -0,0 +1,226 @@
+/*
+ * $Id: ActionContextCleanUp.java 454720 2006-10-10 12:31:52Z tmjee $
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.dispatcher;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * An abstract for superclass for Struts2 filter, encapsulating common logics and
+ * helper methods usefull to subclass, to avoid duplication.
+ *
+ * Common logics encapsulated:-
+ * <ul>
+ * <li>
+ * Dispatcher instance creation through <code>createDispatcher</code> method that acts
+ * as a hook subclass could override. By default it creates an instance of Dispatcher.
+ * </li>
+ * <li>
+ * <code>postInit(FilterConfig)</code> is a hook subclass may use to add post initialization
+ * logics in <code>{@link javax.servlet.Filter#init(FilterConfig)}</code>. It is called before
+ * {@link javax.servlet.Filter#init(FilterConfig)} method ends.
+ * </li>
+ * <li>
+ * A default <code>{@link javax.servlet.Filter#destroy()}</code> that clean up Dispatcher by
+ * calling <code>dispatcher.cleanup()</code>
+ * </li>
+ * <li>
+ * <code>prepareDispatcherAndWrapRequest(HttpServletRequest, HttpServletResponse)</code> helper method
+ * that basically called <code>dispatcher.prepare()</code>, wrap the HttpServletRequest and return the
+ * wrapped version.
+ * </li>
+ * <li>
+ * Various other common helper methods like
+ * <ul>
+ * <li>getFilterConfig</li>
+ * <li>getServletContext</li>
+ * </ul>
+ * </li>
+ * </ul>
+ *
+ *
+ * @see Dispatcher
+ * @see FilterDispatcher
+ * @see ActionContextCleanUp
+ *
+ * @version $Date$ $Id$
+ */
+public abstract class AbstractFilter implements Filter {
+
+ private static final Log LOG = LogFactory.getLog(AbstractFilter.class);
+
+ /**
+ * Internal copy of dispatcher, created when Filter instance gets initialized.
+ * This is needed when ActionContextCleanUp filter is used (Sitemesh integration),
+ * such that a {@link Dispatcher} instance could be prepared and request wrapped before
+ * Sitemesh is given a chance to handle the request. This results in Sitemesh
+ * have access to internals of Struts2. With the following filter configuration
+ * <ol>
+ * <li>ActionContextCleanUp</li>
+ * <li>Sitemesh filter</li>
+ * <li>FilterDispatcher</li>
+ * </ol>
+ * Both {@link ActionContextCleanUp} and {@link FilterDispatcher} will have a
+ * copy of a {@link Dispatcher}, however only one will be copied to
+ * {@link Dispatcher} ThreadLocal.
+ *
+ * @see {@link #prepareDispatcherAndWrapRequest(HttpServletRequest, HttpServletResponse)}
+ */
+ private Dispatcher _internalCopyOfDispatcher;
+
+ protected FilterConfig filterConfig;
+
+ /** Dispatcher instance to be used by subclass. */
+ protected Dispatcher dispatcher;
+
+
+ /**
+ * Initializes the filter
+ *
+ * @param filterConfig The filter configuration
+ */
+ public void init(FilterConfig filterConfig) throws ServletException {
+ this.filterConfig = filterConfig;
+ _internalCopyOfDispatcher = createDispatcher(filterConfig);
+ postInit(filterConfig);
+ }
+
+ /**
+ * Cleans up the dispatcher. Calls dispatcher.cleanup,
+ * which in turn releases local threads and destroys any DispatchListeners.
+ *
+ * @see javax.servlet.Filter#destroy()
+ */
+ public void destroy() {
+ if (_internalCopyOfDispatcher == null) {
+ LOG.warn("something is seriously wrong, Dispatcher is not initialized (null) ");
+ } else {
+ _internalCopyOfDispatcher.cleanup();
+ }
+ }
+
+ /**
+ * Hook for subclass todo custom initialization, called after
+ * <code>javax.servlet.Filter.init(FilterConfig)</code>.
+ *
+ * @param filterConfig
+ * @throws ServletException
+ */
+ protected abstract void postInit(FilterConfig filterConfig) throws ServletException;
+
+
+ /**
+ * Create a default {@link Dispatcher} that subclasses can override
+ * with a custom Dispatcher, if needed.
+ *
+ * @param filterConfig Our FilterConfig
+ * @return Initialized Dispatcher
+ */
+ protected Dispatcher createDispatcher(FilterConfig filterConfig) {
+ Map<String,String> params = new HashMap<String,String>();
+ for (Enumeration e = filterConfig.getInitParameterNames(); e.hasMoreElements(); ) {
+ String name = (String) e.nextElement();
+ String value = filterConfig.getInitParameter(name);
+ params.put(name, value);
+ }
+ return new Dispatcher(filterConfig.getServletContext(), params);
+ }
+
+
+ /**
+ * Provide a workaround for some versions of WebLogic.
+ * <p/>
+ * Servlet 2.3 specifies that the servlet context can be retrieved from the session. Unfortunately, some versions of
+ * WebLogic can only retrieve the servlet context from the filter config. Hence, this method enables subclasses to
+ * retrieve the servlet context from other sources.
+ *
+ * @return the servlet context.
+ */
+ protected ServletContext getServletContext() {
+ return filterConfig.getServletContext();
+ }
+
+ /**
+ * Expose the FilterConfig instance.
+ *
+ * @return Our FilterConfit instance
+ */
+ protected FilterConfig getFilterConfig() {
+ return filterConfig;
+ }
+
+ /**
+ * Wrap and return the given request, if needed, so as to to transparently
+ * handle multipart data as a wrapped class around the given request.
+ *
+ * <p/>
+ *
+ * Helper method that prepare <code>Dispatcher</code>
+ * (by calling <code>Dispatcher.prepare(HttpServletRequest, HttpServletResponse)</code>)
+ * following by wrapping and returning the wrapping <code>HttpServletRequest</code> [ through
+ * <code>dispatcher.wrapRequest(HttpServletRequest, ServletContext)</code> ]
+ *
+ * @param request Our ServletRequest object
+ * @param response Our ServerResponse object
+ * @return Wrapped HttpServletRequest object
+ * @throws ServletException on any error
+ */
+ protected HttpServletRequest prepareDispatcherAndWrapRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException {
+
+ Dispatcher du = Dispatcher.getInstance();
+
+ // Prepare and wrap the request if the cleanup filter hasn't already, cleanup filter should be
+ // configured first before struts2 dispatcher filter, hence when its cleanup filter's turn,
+ // static instance of Dispatcher should be null.
+ if (du == null) {
+ dispatcher = _internalCopyOfDispatcher;
+
+ Dispatcher.setInstance(dispatcher);
+
+ // prepare the request no matter what - this ensures that the proper character encoding
+ // is used before invoking the mapper (see WW-9127)
+ dispatcher.prepare(request, response);
+
+ try {
+ // Wrap request first, just in case it is multipart/form-data
+ // parameters might not be accessible through before encoding (ww-1278)
+ request = dispatcher.wrapRequest(request, getServletContext());
+ } catch (IOException e) {
+ String message = "Could not wrap servlet request with MultipartRequestWrapper!";
+ LOG.error(message, e);
+ throw new ServletException(message, e);
+ }
+ }
+ else {
+ dispatcher = du;
+ }
+ return request;
+ }
+}
Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ActionContextCleanUp.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ActionContextCleanUp.java?view=diff&rev=475154&r1=475153&r2=475154
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ActionContextCleanUp.java (original)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ActionContextCleanUp.java Wed Nov 15 00:06:56 2006
@@ -65,12 +65,24 @@
*
* @version $Date$ $Id$
*/
-public class ActionContextCleanUp implements Filter {
+public class ActionContextCleanUp extends AbstractFilter implements Filter {
private static final Log LOG = LogFactory.getLog(ActionContextCleanUp.class);
private static final String COUNTER = "__cleanup_recursion_counter";
+
+ /**
+ * Does nothing in this implementation.
+ *
+ * @see org.apache.struts2.dispatcher.AbstractFilter#postInit(javax.servlet.FilterConfig)
+ */
+ @Override
+ protected void postInit(FilterConfig filterConfig) throws ServletException {
+ // do nothing
+ }
+
+
/**
* @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
*/
@@ -79,10 +91,14 @@
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("doFilter");
+ }
+
String timerKey = "ActionContextCleanUp_doFilter: ";
try {
UtilTimerStack.push(timerKey);
-
+ request = prepareDispatcherAndWrapRequest(request, response);
try {
Integer count = (Integer)request.getAttribute(COUNTER);
if (count == null) {
@@ -132,11 +148,5 @@
if (LOG.isDebugEnabled()) {
LOG.debug("clean up ");
}
- }
-
- public void destroy() {
- }
-
- public void init(FilterConfig arg0) throws ServletException {
}
}
Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/FilterDispatcher.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/FilterDispatcher.java?view=diff&rev=475154&r1=475153&r2=475154
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/FilterDispatcher.java (original)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/FilterDispatcher.java Wed Nov 15 00:06:56 2006
@@ -121,7 +121,7 @@
*
* @version $Date$ $Id$
*/
-public class FilterDispatcher implements StrutsStatics, Filter {
+public class FilterDispatcher extends AbstractFilter implements StrutsStatics, Filter {
/**
* Provide a logging instance.
@@ -168,15 +168,6 @@
*/
private static ActionMapper actionMapper;
- /**
- * Provide FilterConfig instance, set on init.
- */
- private FilterConfig filterConfig;
-
- /**
- * Expose Dispatcher instance to subclass.
- */
- protected Dispatcher dispatcher;
/**
* Initializes the filter by creating a default dispatcher
@@ -184,9 +175,7 @@
*
* @param filterConfig The filter configuration
*/
- public void init(FilterConfig filterConfig) throws ServletException {
- dispatcher = createDispatcher(filterConfig);
- this.filterConfig = filterConfig;
+ public void postInit(FilterConfig filterConfig) throws ServletException {
String param = filterConfig.getInitParameter("packages");
String packages = "org.apache.struts2.static template org.apache.struts2.interceptor.debugging";
if (param != null) {
@@ -195,36 +184,6 @@
this.pathPrefixes = parse(packages);
}
- /**
- * Calls dispatcher.cleanup,
- * which in turn releases local threads and destroys any DispatchListeners.
- *
- * @see javax.servlet.Filter#destroy()
- */
- public void destroy() {
- if (dispatcher == null) {
- LOG.warn("something is seriously wrong, Dispatcher is not initialized (null) ");
- } else {
- dispatcher.cleanup();
- }
- }
-
- /**
- * Create a default {@link Dispatcher} that subclasses can override
- * with a custom Dispatcher, if needed.
- *
- * @param filterConfig Our FilterConfig
- * @return Initialized Dispatcher
- */
- protected Dispatcher createDispatcher(FilterConfig filterConfig) {
- Map<String,String> params = new HashMap<String,String>();
- for (Enumeration e = filterConfig.getInitParameterNames(); e.hasMoreElements(); ) {
- String name = (String) e.nextElement();
- String value = filterConfig.getInitParameter(name);
- params.put(name, value);
- }
- return new Dispatcher(filterConfig.getServletContext(), params);
- }
/**
* Modify state of StrutsConstants.STRUTS_SERVE_STATIC_CONTENT setting.
@@ -263,68 +222,6 @@
}
/**
- * Provide a workaround for some versions of WebLogic.
- * <p/>
- * Servlet 2.3 specifies that the servlet context can be retrieved from the session. Unfortunately, some versions of
- * WebLogic can only retrieve the servlet context from the filter config. Hence, this method enables subclasses to
- * retrieve the servlet context from other sources.
- *
- * @return the servlet context.
- */
- protected ServletContext getServletContext() {
- return filterConfig.getServletContext();
- }
-
- /**
- * Expose the FilterConfig instance.
- *
- * @return Our FilterConfit instance
- */
- protected FilterConfig getFilterConfig() {
- return filterConfig;
- }
-
- /**
- * Wrap and return the given request, if needed, so as to to transparently
- * handle multipart data as a wrapped class around the given request.
- *
- * @param request Our ServletRequest object
- * @param response Our ServerResponse object
- * @return Wrapped HttpServletRequest object
- * @throws ServletException on any error
- */
- protected HttpServletRequest prepareDispatcherAndWrapRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException {
-
- Dispatcher du = Dispatcher.getInstance();
-
- // Prepare and wrap the request if the cleanup filter hasn't already, cleanup filter should be
- // configured first before struts2 dispatcher filter, hence when its cleanup filter's turn,
- // static instance of Dispatcher should be null.
- if (du == null) {
-
- Dispatcher.setInstance(dispatcher);
-
- // prepare the request no matter what - this ensures that the proper character encoding
- // is used before invoking the mapper (see WW-9127)
- dispatcher.prepare(request, response);
-
- try {
- // Wrap request first, just in case it is multipart/form-data
- // parameters might not be accessible through before encoding (ww-1278)
- request = dispatcher.wrapRequest(request, getServletContext());
- } catch (IOException e) {
- String message = "Could not wrap servlet request with MultipartRequestWrapper!";
- LOG.error(message, e);
- throw new ServletException(message, e);
- }
- }
- else {
- dispatcher = du;
- }
- return request;
- }
-
- /**
* Create a string array from a comma-delimited list of packages.
*
* @param packages A comma-delimited String listing packages
@@ -369,6 +266,10 @@
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
ServletContext servletContext = getServletContext();
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("doFilter");
+ }
String timerKey = "FilterDispatcher_doFilter: ";
try {