Author: tmjee
Date: Sat Nov  4 23:47:19 2006
New Revision: 471375

URL: http://svn.apache.org/viewvc?view=rev&rev=471375
Log:
WW-1489
 - Refactor ActionContextCleanUp and DispatcherFilter to have common logics in 
an abstract super class


Added:
    
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/AbstractFilter.java
    
struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/ActionContextCleanUpTest.java
    
struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/FilterTest.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
    
struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/FilterDispatcherTest.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=471375
==============================================================================
--- 
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
 Sat Nov  4 23:47:19 2006
@@ -0,0 +1,191 @@
+/*
+ * $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 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>[EMAIL PROTECTED] 
javax.servlet.Filter#init(FilterConfig)}</code>. It is called before
+ *      [EMAIL PROTECTED] javax.servlet.Filter#init(FilterConfig)} method ends.
+ *  </li>
+ *  <li>
+ *     A default <code>[EMAIL PROTECTED] 
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. */
+       private Dispatcher _dispatcher; 
+       
+       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;
+        _dispatcher = createDispatcher();
+        postInit(filterConfig);
+    }
+    
+    /**
+     * Cleans up the dispatcher
+     * 
+     * @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();
+        }
+    }
+    
+    /**
+     * 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 [EMAIL PROTECTED] Dispatcher}, this serves as a hook for 
subclass to overried
+     * such that a custom [EMAIL PROTECTED] Dispatcher} could be created. 
+     * 
+     * @return Dispatcher
+     */
+    protected Dispatcher createDispatcher() {
+       return new Dispatcher(filterConfig.getServletContext());
+    }
+    
+    /**
+     * 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.
+     *
+     * @param session the HTTP session where, in Servlet 2.3, the servlet 
context can be retrieved
+     * @return the servlet context.
+     */
+    protected ServletContext getServletContext() {
+        return filterConfig.getServletContext();
+    }
+    
+    /** 
+     * Gets this filter's configuration
+     * 
+     * @return The filter config
+     */
+    protected FilterConfig getFilterConfig() {
+        return filterConfig;
+    }
+    
+    /**
+     * 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
+     * @param response
+     * @return HttpServletRequest
+     * @throws ServletException
+     */
+    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 = _dispatcher;
+               
+               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=471375&r1=471374&r2=471375
==============================================================================
--- 
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
 Sat Nov  4 23:47:19 2006
@@ -19,10 +19,8 @@
 
 import java.io.IOException;
 
-import javax.servlet.Filter;
 import javax.servlet.FilterChain;
 import javax.servlet.FilterConfig;
-import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
@@ -56,29 +54,28 @@
  * </ul>
  * <!-- SNIPPET END: description -->
  *
- * @version $Date$ $Id$
  *
  * @see FilterDispatcher
+ * @see AbstractFilter
+ * @see Dispatcher
+ * 
+ * @version $Date$ $Id$
  */
-public class ActionContextCleanUp implements Filter {
+public class ActionContextCleanUp extends AbstractFilter {
 
     private static final Log LOG = 
LogFactory.getLog(ActionContextCleanUp.class);
 
     private static final String COUNTER = "__cleanup_recursion_counter";
 
     protected FilterConfig filterConfig;
-    protected Dispatcher dispatcher;
+
 
     /**
-     * Initializes the filter
-     * 
-     * @param filterConfig The filter configuration
+     * Empty implementation.
      */
-    public void init(FilterConfig filterConfig) throws ServletException {
-        this.filterConfig = filterConfig;
-        dispatcher = new Dispatcher(filterConfig.getServletContext());
+    protected void postInit(FilterConfig filterConfig) throws ServletException 
{
+       // does nothing.
     }
-
     
     /**
      * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, 
javax.servlet.ServletResponse, javax.servlet.FilterChain)
@@ -92,19 +89,7 @@
         try {
                UtilTimerStack.push(timerKey);
                
-               // prepare the request no matter what - this ensures that the 
proper character encoding
-               // is used before invoking the mapper (see WW-9127)
-               Dispatcher.setInstance(dispatcher);
-               dispatcher.prepare(request, response);
-
-               ServletContext servletContext = 
filterConfig.getServletContext();
-               try {
-                       request = dispatcher.wrapRequest(request, 
servletContext);
-               } catch (IOException e) {
-                       String message = "Could not wrap servlet request with 
MultipartRequestWrapper!";
-                       LOG.error(message, e);
-                       throw new ServletException(message, e);
-               }
+               request = prepareDispatcherAndWrapRequest(request, response);
 
                try {
                        Integer count = (Integer)request.getAttribute(COUNTER);
@@ -115,6 +100,11 @@
                                count = new Integer(count.intValue()+1);
                        }
                        request.setAttribute(COUNTER, count);
+                       
+                       if (LOG.isDebugEnabled()) {
+                       LOG.debug("filtering counter="+count);
+               }
+                       
                        chain.doFilter(request, response);
                } finally {
                        int counterVal = 
((Integer)request.getAttribute(COUNTER)).intValue();
@@ -135,21 +125,20 @@
      */
     protected static void cleanUp(ServletRequest req) {
         // should we clean up yet?
-        if (req.getAttribute(COUNTER) != null &&
-                 ((Integer)req.getAttribute(COUNTER)).intValue() > 0 ) {
-             return;
-         }
+       Integer count = (Integer) req.getAttribute(COUNTER);
+        if (count != null && count > 0 ) {
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("skipping cleanup counter="+count);
+               }
+            return;
+        }
 
         // always dontClean up the thread request, even if an action hasn't 
been executed
         ActionContext.setContext(null);
-        
         Dispatcher.setInstance(null);
-    }
-
-    
-    /* (non-Javadoc)
-     * @see javax.servlet.Filter#destroy()
-     */
-    public void destroy() {
+        
+        if (LOG.isDebugEnabled()) {
+               LOG.debug("clean up ");
+       }
     }
 }

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=471375&r1=471374&r2=471375
==============================================================================
--- 
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
 Sat Nov  4 23:47:19 2006
@@ -28,7 +28,6 @@
 import java.util.StringTokenizer;
 import java.util.TimeZone;
 
-import javax.servlet.Filter;
 import javax.servlet.FilterChain;
 import javax.servlet.FilterConfig;
 import javax.servlet.ServletContext;
@@ -37,7 +36,6 @@
 import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -118,49 +116,30 @@
  * 
  * @version $Date$ $Id$
  */
-public class FilterDispatcher implements Filter, StrutsStatics {
+public class FilterDispatcher extends AbstractFilter implements StrutsStatics {
+       
     private static final Log LOG = LogFactory.getLog(FilterDispatcher.class);
 
-    private FilterConfig filterConfig;
     private String[] pathPrefixes;
-    private Dispatcher dispatcher;
 
     private SimpleDateFormat df = new SimpleDateFormat("E, d MMM yyyy 
HH:mm:ss");
     private final Calendar lastModifiedCal = 
Calendar.getInstance(TimeZone.getTimeZone("GMT"));
     private final String lastModified = df.format(lastModifiedCal.getTime());
 
-    /** 
-     * Gets this filter's configuration
-     * 
-     * @return The filter config
-     */
-    protected FilterConfig getFilterConfig() {
-        return filterConfig;
-    }
-
-    /**
-     * Cleans up the dispatcher
-     */
-    public void destroy() {
-               if (dispatcher == null) {
-                       LOG.warn("something is seriously wrong, DispatcherUtil 
is not initialized (null) ");
-               } else {
-                   dispatcher.cleanup();
-        }
-    }
-
+    
     /**
-     * Initializes the dispatcher and filter
+     * Look for "packages" defined through filter-config's parameters.
+     * 
+     * @param FilterConfig
+     * @throws ServletException
      */
-    public void init(FilterConfig filterConfig) throws ServletException {
-        this.filterConfig = filterConfig;
-        String param = filterConfig.getInitParameter("packages");
+    protected 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) {
             packages = param + " " + packages;
         }
         this.pathPrefixes = parse(packages);
-        dispatcher = createDispatcher();
     }
     
     /**
@@ -188,45 +167,29 @@
     }
 
 
-    /* (non-Javadoc)
+    /**
      * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, 
javax.servlet.ServletResponse, javax.servlet.FilterChain)
      */
     public void doFilter(ServletRequest req, ServletResponse res, FilterChain 
chain) throws IOException, ServletException {
         HttpServletRequest request = (HttpServletRequest) req;
         HttpServletResponse response = (HttpServletResponse) res;
-        ServletContext servletContext = filterConfig.getServletContext();
+        ServletContext servletContext = getServletContext();
 
         String timerKey = "FilterDispatcher_doFilter: ";
         try {
                UtilTimerStack.push(timerKey);
-               Dispatcher du = Dispatcher.getInstance();
         
-               // Prepare and wrap the request if the cleanup filter hasn't 
already
-               if (du == null) {
-                       du = dispatcher;
-                       // prepare the request no matter what - this ensures 
that the proper character encoding
-                       // is used before invoking the mapper (see WW-9127)
-                       du.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 = du.wrapRequest(request, 
servletContext);
-                       } catch (IOException e) {
-                               String message = "Could not wrap servlet 
request with MultipartRequestWrapper!";
-                               LOG.error(message, e);
-                               throw new ServletException(message, e);
-                       }
-                       Dispatcher.setInstance(du);
-               }
+                       request = prepareDispatcherAndWrapRequest(request, 
response);
+
 
                ActionMapper mapper = null;
                ActionMapping mapping = null;
                try {
                        mapper = ActionMapperFactory.getMapper();
-                       mapping = mapper.getMapping(request, 
du.getConfigurationManager());
+                       mapping = mapper.getMapping(request, 
dispatcher.getConfigurationManager());
                } catch (Exception ex) {
-                       du.sendError(request, response, servletContext, 
HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex);
+                       LOG.error("error getting ActionMapping", ex);
+                       dispatcher.sendError(request, response, servletContext, 
HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex);
                        ActionContextCleanUp.cleanUp(req);
                        return;
                }
@@ -264,18 +227,6 @@
     }
 
     /**
-     * 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.
-     *
-     * @param session the HTTP session where, in Servlet 2.3, the servlet 
context can be retrieved
-     * @return the servlet context.
-     */
-    protected ServletContext getServletContext(HttpSession session) {
-        return filterConfig.getServletContext();
-    }
-
-    /**
      * Finds a static resource
      * 
      * @param name The resource name
@@ -385,15 +336,5 @@
         resourcePath = URLDecoder.decode(resourcePath, enc);
 
         return ClassLoaderUtil.getResourceAsStream(resourcePath, getClass());
-    }
-    
-    /**
-     * Create a [EMAIL PROTECTED] Dispatcher}, this serves as a hook for 
subclass to overried
-     * such that a custom [EMAIL PROTECTED] Dispatcher} could be created. 
-     * 
-     * @return Dispatcher
-     */
-    protected Dispatcher createDispatcher() {
-       return new Dispatcher(filterConfig.getServletContext());
     }
 }

Added: 
struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/ActionContextCleanUpTest.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/ActionContextCleanUpTest.java?view=auto&rev=471375
==============================================================================
--- 
struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/ActionContextCleanUpTest.java
 (added)
+++ 
struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/ActionContextCleanUpTest.java
 Sat Nov  4 23:47:19 2006
@@ -0,0 +1,205 @@
+/*
+ * $Id: FilterDispatcherTest.java 449367 2006-09-24 06:49:04Z mrdon $
+ *
+ * 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.LinkedHashMap;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts2.dispatcher.mapper.ActionMapping;
+import org.springframework.mock.web.MockFilterConfig;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.mock.web.MockServletContext;
+
+import com.mockobjects.servlet.MockFilterChain;
+
+import junit.framework.TestCase;
+
+/**
+ * @version $Date$ $Id$
+ */
+public class ActionContextCleanUpTest extends TestCase {
+       
+       
+       protected MockFilterConfig filterConfig;
+       protected MockHttpServletRequest request;
+       protected MockHttpServletResponse response;
+       protected MockFilterChain filterChain;
+       protected MockFilterChain filterChain2;
+       protected MockServletContext servletContext;
+       
+       protected Counter counter;
+       protected Map<String, Integer> _tmpStore;
+       protected InnerDispatcher _dispatcher;
+       protected InnerDispatcher _dispatcher2;
+       protected ActionContextCleanUp cleanUp;
+       protected ActionContextCleanUp cleanUp2;
+       
+       
+       @Override
+       protected void tearDown() throws Exception {
+               filterConfig = null;
+               request = null;
+               response = null;
+               filterChain = null;
+               filterChain2 = null;
+               servletContext = null;
+               counter = null;
+               _tmpStore = null;
+               _dispatcher = null;
+               _dispatcher2 = null;
+               cleanUp = null;
+               cleanUp2 = null;
+       }
+       
+       @Override
+       protected void setUp() throws Exception {
+               Dispatcher.setInstance(null);
+               
+               counter = new Counter();
+               _tmpStore = new LinkedHashMap<String, Integer>();
+               
+               filterConfig = new MockFilterConfig();
+               request = new MockHttpServletRequest();
+               response = new MockHttpServletResponse();
+               servletContext = new MockServletContext();
+               _dispatcher = new InnerDispatcher(servletContext) {
+                       @Override
+                       public String toString() {
+                               return "dispatcher";
+                       }
+               };
+               _dispatcher2 = new InnerDispatcher(servletContext){
+                       @Override
+                       public String toString() {
+                               return "dispatcher2";
+                       }
+               };
+               
+               
+               filterChain = new MockFilterChain() {
+                       @Override
+                       public void doFilter(ServletRequest request, 
ServletResponse response) throws IOException, ServletException {
+                               _tmpStore.put("counter"+(counter.count++), 
(Integer) request.getAttribute("__cleanup_recursion_counter"));
+                       }
+               };
+               
+               cleanUp = new ActionContextCleanUp() {
+                       @Override
+                       protected Dispatcher createDispatcher() {
+                               return _dispatcher;
+                       }
+               };
+               
+               cleanUp2 = new ActionContextCleanUp() {
+                       @Override
+                       protected Dispatcher createDispatcher() {
+                               return _dispatcher2;
+                       }
+               };
+               
+               filterChain2 = new MockFilterChain() {
+                       @Override
+                       public void doFilter(ServletRequest request, 
ServletResponse response) throws IOException, ServletException {
+                               _tmpStore.put("counter"+(counter.count++), 
(Integer) request.getAttribute("__cleanup_recursion_counter"));
+                               cleanUp2.doFilter(request, response, 
filterChain);
+                       }
+               };
+       }
+       
+       
+       public void testSingle() throws Exception {
+               assertFalse(_dispatcher.prepare);
+               assertFalse(_dispatcher.wrapRequest);
+               assertNull(request.getAttribute("__cleanup_recursion_counter"));
+               
+               cleanUp.init(filterConfig);
+               cleanUp.doFilter(request, response, filterChain);
+               cleanUp.destroy();
+               
+               assertEquals(_tmpStore.size(), 1);
+               assertEquals(_tmpStore.get("counter0"), new Integer(1));
+               
+               assertTrue(_dispatcher.prepare);
+               assertTrue(_dispatcher.wrapRequest);
+               
assertEquals(request.getAttribute("__cleanup_recursion_counter"), new 
Integer("0"));
+       }
+       
+       public void testMultiple() throws Exception {
+               assertFalse(_dispatcher.prepare);
+               assertFalse(_dispatcher.wrapRequest);
+               assertFalse(_dispatcher2.prepare);
+               assertFalse(_dispatcher2.wrapRequest);
+               assertNull(request.getAttribute("__cleanup_recursion_counter"));
+               
+               cleanUp.init(filterConfig);
+               cleanUp2.init(filterConfig);
+               cleanUp.doFilter(request, response, filterChain2);
+               cleanUp2.destroy();
+               cleanUp.destroy();
+               
+               assertEquals(_tmpStore.size(), 2);
+               assertEquals(_tmpStore.get("counter0"), new Integer(1));
+               assertEquals(_tmpStore.get("counter1"), new Integer(2));
+               
+               assertFalse(_dispatcher2.prepare);
+               assertFalse(_dispatcher2.wrapRequest);
+               assertTrue(_dispatcher.prepare);
+               assertTrue(_dispatcher.wrapRequest);
+               
assertEquals(request.getAttribute("__cleanup_recursion_counter"), new 
Integer("0"));
+       }
+       
+       
+       class InnerDispatcher extends Dispatcher {
+               public boolean prepare = false;
+               public boolean wrapRequest = false;
+               public boolean service = false;
+               
+               public InnerDispatcher(ServletContext servletContext) {
+                       super(servletContext);
+               }
+               
+               @Override
+               public void prepare(HttpServletRequest request, 
HttpServletResponse response) {
+                       prepare = true;
+               }
+               
+               @Override
+               public HttpServletRequest wrapRequest(HttpServletRequest 
request, ServletContext servletContext) throws IOException {
+                       wrapRequest = true;
+                       return request;
+               }
+               
+               @Override
+               public void serviceAction(HttpServletRequest request, 
HttpServletResponse response, ServletContext context, ActionMapping mapping) 
throws ServletException {
+                       service = true;
+               }
+       }
+       
+       class Counter {
+               public int count=0;
+       }
+}

Modified: 
struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/FilterDispatcherTest.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/FilterDispatcherTest.java?view=diff&rev=471375&r1=471374&r2=471375
==============================================================================
--- 
struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/FilterDispatcherTest.java
 (original)
+++ 
struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/FilterDispatcherTest.java
 Sat Nov  4 23:47:19 2006
@@ -47,11 +47,13 @@
 /**
  * FilterDispatcher TestCase.
  *
+ * @version $Date$ $Id$
  */
 public class FilterDispatcherTest extends StrutsTestCase {
 
 
     public void testParsePackages() throws Exception {
+       
         FilterDispatcher filterDispatcher = new FilterDispatcher();
         String[] result1 = filterDispatcher.parse("foo.bar.package1 
foo.bar.package2 foo.bar.package3");
         String[] result2 = 
filterDispatcher.parse("foo.bar.package1\tfoo.bar.package2\tfoo.bar.package3");
@@ -136,12 +138,12 @@
                MockHttpServletRequest req = new 
MockHttpServletRequest(servletContext);
                MockHttpServletResponse res = new MockHttpServletResponse();
                MockFilterChain chain = new MockFilterChain();
-               final NoOpDispatcher dispatcher = new 
NoOpDispatcher(servletContext);
+               final NoOpDispatcher _dispatcher = new 
NoOpDispatcher(servletContext);
                Dispatcher.setInstance(null);
 
                ConfigurationManager confManager = new ConfigurationManager();
                confManager.setConfiguration(new DefaultConfiguration());
-               dispatcher.setConfigurationManager(confManager);
+               _dispatcher.setConfigurationManager(confManager);
                
                
                ObjectFactory.setObjectFactory(new InnerObjectFactory());
@@ -152,13 +154,13 @@
        
                FilterDispatcher filter = new FilterDispatcher() {
                        protected Dispatcher createDispatcher() {
-                               return dispatcher;
+                               return _dispatcher;
                        }
                };
                filter.init(filterConfig);
                filter.doFilter(req, res, chain);
        
-               assertFalse(dispatcher.serviceRequest);
+               assertFalse(_dispatcher.serviceRequest);
        }
        finally {
                Settings.reset();
@@ -172,12 +174,12 @@
                MockHttpServletRequest req = new 
MockHttpServletRequest(servletContext);
                MockHttpServletResponse res = new MockHttpServletResponse();
                MockFilterChain chain = new MockFilterChain();
-               final InnerDispatcher dispatcher = new 
InnerDispatcher(servletContext);
+               final InnerDispatcher _dispatcher = new 
InnerDispatcher(servletContext);
                Dispatcher.setInstance(null);
 
                ConfigurationManager confManager = new ConfigurationManager();
                confManager.setConfiguration(new DefaultConfiguration());
-               dispatcher.setConfigurationManager(confManager);
+               _dispatcher.setConfigurationManager(confManager);
                
                
                ObjectFactory.setObjectFactory(new InnerObjectFactory());
@@ -189,14 +191,14 @@
        
                FilterDispatcher filter = new FilterDispatcher() {
                        protected Dispatcher createDispatcher() {
-                               return dispatcher;
+                               return _dispatcher;
                        }
                };
                filter.init(filterConfig);
                filter.doFilter(req, res, chain);
        
-               assertTrue(dispatcher.wrappedRequest);
-               assertTrue(dispatcher.serviceRequest);
+               assertTrue(_dispatcher.wrappedRequest);
+               assertTrue(_dispatcher.serviceRequest);
        }
        finally {
                Settings.reset();

Added: 
struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/FilterTest.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/FilterTest.java?view=auto&rev=471375
==============================================================================
--- 
struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/FilterTest.java
 (added)
+++ 
struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/FilterTest.java
 Sat Nov  4 23:47:19 2006
@@ -0,0 +1,344 @@
+/*
+ * $Id: FilterDispatcherTest.java 449367 2006-09-24 06:49:04Z mrdon $
+ *
+ * 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 javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import junit.framework.TestCase;
+
+import org.apache.struts2.StrutsConstants;
+import org.apache.struts2.config.Settings;
+import org.apache.struts2.dispatcher.mapper.ActionMapper;
+import org.apache.struts2.dispatcher.mapper.ActionMapping;
+import org.springframework.mock.web.MockFilterConfig;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.mock.web.MockServletContext;
+
+import com.mockobjects.servlet.MockFilterChain;
+import com.opensymphony.xwork2.ObjectFactory;
+import com.opensymphony.xwork2.config.ConfigurationManager;
+
+
+/**
+ * 
+ * @version $Date$ $Id$
+ */
+public class FilterTest extends TestCase { 
+       
+       protected MockFilterConfig filterConfig;
+       protected MockHttpServletRequest request;
+       protected MockHttpServletResponse response;
+       protected MockFilterChain filterChain;
+       protected MockFilterChain filterChain2;
+       protected MockServletContext servletContext;
+       
+       protected InnerDispatcher _dispatcher1;
+       protected InnerDispatcher _dispatcher2;
+       protected ActionContextCleanUp cleanUp;
+       protected FilterDispatcher filterDispatcher;
+       
+       protected int cleanUpFilterCreateDispatcherCount = 0; // number of 
times clean up filter create a dispatcher
+       protected int filterDispatcherCreateDispatcherCount = 0; // number of 
times FilterDispatcher create a dispatcher
+       
+       
+       @Override
+       protected void tearDown() throws Exception {
+               filterConfig = null;
+               request = null;
+               response = null;
+               filterChain = null;
+               filterChain2 = null;
+               servletContext = null;
+               _dispatcher1 = null;
+               _dispatcher2 = null;
+               cleanUp = null;
+               filterDispatcher = null;
+       }
+       
+       @Override
+       protected void setUp() throws Exception {
+               Dispatcher.setInstance(null);
+               
+               filterConfig = new MockFilterConfig();
+               request = new MockHttpServletRequest();
+               response = new MockHttpServletResponse();
+               servletContext = new MockServletContext();
+               
+               _dispatcher1 = new InnerDispatcher(servletContext){
+                       @Override
+                       public String toString() {
+                               return "dispatcher1";
+                       }
+               };
+               _dispatcher2 = new InnerDispatcher(servletContext){
+                       @Override
+                       public String toString() {
+                               return "dispatcher2";
+                       }
+               };
+               filterChain = new MockFilterChain() {
+                       @Override
+                       public void doFilter(ServletRequest req, 
ServletResponse res) throws IOException, ServletException {
+                               filterDispatcher.doFilter(req, res, 
filterChain2);
+                       }
+               };
+               filterChain2 = new MockFilterChain() {
+                       @Override
+                       public void doFilter(ServletRequest req, 
ServletResponse res) throws IOException, ServletException {
+                       }
+               };
+               
+               
+               cleanUp = new ActionContextCleanUp() {
+                       @Override
+                       protected Dispatcher createDispatcher() {
+                               cleanUpFilterCreateDispatcherCount++;
+                               return _dispatcher1;
+                       }
+                       
+                       @Override
+                       public String toString() {
+                               return "cleanUp";
+                       }
+               };
+               
+               filterDispatcher = new FilterDispatcher() {
+                       @Override
+                       protected Dispatcher createDispatcher() {
+                               filterDispatcherCreateDispatcherCount++;
+                               return _dispatcher2;
+                       }
+                       
+                       @Override
+                       public String toString() {
+                               return "filterDispatcher";
+                       }
+               };
+       }
+       
+       
+       public void testUsingFilterDispatcherOnly() throws Exception {
+               ObjectFactory oldObjecFactory = 
ObjectFactory.getObjectFactory();
+               try {
+                       ObjectFactory.setObjectFactory(new 
InnerObjectFactory());
+                       Settings.set(StrutsConstants.STRUTS_MAPPER_CLASS, 
"org.apache.struts2.dispatcher.FilterTest$InnerMapper");
+               
+                       assertEquals(cleanUpFilterCreateDispatcherCount, 0);
+                       assertEquals(filterDispatcherCreateDispatcherCount, 0);
+                       assertFalse(_dispatcher1.prepare);
+                       assertFalse(_dispatcher1.wrapRequest);
+                       assertFalse(_dispatcher1.service);
+                       assertFalse(_dispatcher2.prepare);
+                       assertFalse(_dispatcher2.wrapRequest);
+                       assertFalse(_dispatcher2.service);
+               
+                       filterDispatcher.init(filterConfig);
+                       filterDispatcher.doFilter(request, response, 
filterChain2);
+                       filterDispatcher.destroy();
+               
+                       // we are using FilterDispatcher only, so cleanUp 
filter's Dispatcher should not be created.
+                       assertEquals(cleanUpFilterCreateDispatcherCount, 0);
+                       assertEquals(filterDispatcherCreateDispatcherCount, 1);
+                       assertFalse(_dispatcher1.prepare);
+                       assertFalse(_dispatcher1.wrapRequest);
+                       assertFalse(_dispatcher1.service);
+                       assertTrue(_dispatcher2.prepare);
+                       assertTrue(_dispatcher2.wrapRequest);
+                       assertTrue(_dispatcher2.service);
+                       assertTrue(Dispatcher.getInstance() == null);
+               }
+               finally {
+                       ObjectFactory.setObjectFactory(oldObjecFactory);
+               }
+       }
+       
+       public void testUsingFilterDispatcherOnly_Multiple() throws Exception {
+               ObjectFactory oldObjecFactory = 
ObjectFactory.getObjectFactory();
+               try {
+                       ObjectFactory.setObjectFactory(new 
InnerObjectFactory());
+                       Settings.set(StrutsConstants.STRUTS_MAPPER_CLASS, 
"org.apache.struts2.dispatcher.FilterTest$InnerMapper");
+               
+                       assertEquals(cleanUpFilterCreateDispatcherCount, 0);
+                       assertEquals(filterDispatcherCreateDispatcherCount, 0);
+                       assertFalse(_dispatcher1.prepare);
+                       assertFalse(_dispatcher1.wrapRequest);
+                       assertFalse(_dispatcher1.service);
+                       assertFalse(_dispatcher2.prepare);
+                       assertFalse(_dispatcher2.wrapRequest);
+                       assertFalse(_dispatcher2.service);
+               
+                       filterDispatcher.init(filterConfig);
+                       filterDispatcher.doFilter(request, response, 
filterChain2);
+                       filterDispatcher.doFilter(request, response, 
filterChain2);
+                       filterDispatcher.destroy();
+               
+                       assertEquals(cleanUpFilterCreateDispatcherCount, 0);
+                       // We should create dispatcher once, although 
filter.doFilter(...) is called  many times.
+                       assertEquals(filterDispatcherCreateDispatcherCount, 1);
+                       assertFalse(_dispatcher1.prepare);
+                       assertFalse(_dispatcher1.wrapRequest);
+                       assertFalse(_dispatcher1.service);
+                       assertTrue(_dispatcher2.prepare);
+                       assertTrue(_dispatcher2.wrapRequest);
+                       assertTrue(_dispatcher2.service);
+                       assertTrue(Dispatcher.getInstance() == null);
+               }
+               finally {
+                       ObjectFactory.setObjectFactory(oldObjecFactory);
+               }
+       }
+       
+       public void testUsingCleanUpAndFilterDispatcher() throws Exception {
+               ObjectFactory oldObjecFactory = 
ObjectFactory.getObjectFactory();
+               try {
+                       ObjectFactory.setObjectFactory(new 
InnerObjectFactory());
+                       Settings.set(StrutsConstants.STRUTS_MAPPER_CLASS, 
"org.apache.struts2.dispatcher.FilterTest$InnerMapper");
+               
+                       assertEquals(cleanUpFilterCreateDispatcherCount, 0);
+                       assertEquals(filterDispatcherCreateDispatcherCount, 0);
+                       assertFalse(_dispatcher1.prepare);
+                       assertFalse(_dispatcher1.wrapRequest);
+                       assertFalse(_dispatcher1.service);
+                       assertFalse(_dispatcher2.prepare);
+                       assertFalse(_dispatcher2.wrapRequest);
+                       assertFalse(_dispatcher2.service);
+               
+                       cleanUp.init(filterConfig);
+                       filterDispatcher.init(filterConfig);
+                       cleanUp.doFilter(request, response, filterChain);
+                       filterDispatcher.destroy();
+                       cleanUp.destroy();
+               
+                       assertEquals(cleanUpFilterCreateDispatcherCount, 1);
+                       assertEquals(filterDispatcherCreateDispatcherCount, 1);
+                       assertTrue(_dispatcher1.prepare);
+                       assertTrue(_dispatcher1.wrapRequest);
+                       assertTrue(_dispatcher1.service);
+                       assertFalse(_dispatcher2.prepare);
+                       assertFalse(_dispatcher2.wrapRequest);
+                       assertFalse(_dispatcher2.service);
+                       assertTrue(Dispatcher.getInstance() == null);
+               }
+               finally {
+                       ObjectFactory.setObjectFactory(oldObjecFactory);
+               }
+       }
+       
+       
+       public void testUsingCleanUpAndFilterDispatcher_Multiple() throws 
Exception {
+               ObjectFactory oldObjecFactory = 
ObjectFactory.getObjectFactory();
+               try {
+                       ObjectFactory.setObjectFactory(new 
InnerObjectFactory());
+                       Settings.set(StrutsConstants.STRUTS_MAPPER_CLASS, 
"org.apache.struts2.dispatcher.FilterTest$InnerMapper");
+               
+                       assertEquals(cleanUpFilterCreateDispatcherCount, 0);
+                       assertEquals(filterDispatcherCreateDispatcherCount, 0);
+                       assertFalse(_dispatcher1.prepare);
+                       assertFalse(_dispatcher1.wrapRequest);
+                       assertFalse(_dispatcher1.service);
+                       assertFalse(_dispatcher2.prepare);
+                       assertFalse(_dispatcher2.wrapRequest);
+                       assertFalse(_dispatcher2.service);
+               
+                       cleanUp.init(filterConfig);
+                       filterDispatcher.init(filterConfig);
+                       cleanUp.doFilter(request, response, filterChain);
+                       cleanUp.doFilter(request, response, filterChain);
+                       filterDispatcher.destroy();
+                       cleanUp.destroy();
+               
+                       assertEquals(cleanUpFilterCreateDispatcherCount, 1);
+                       assertEquals(filterDispatcherCreateDispatcherCount, 1);
+                       assertTrue(_dispatcher1.prepare);
+                       assertTrue(_dispatcher1.wrapRequest);
+                       assertTrue(_dispatcher1.service);
+                       assertFalse(_dispatcher2.prepare);
+                       assertFalse(_dispatcher2.wrapRequest);
+                       assertFalse(_dispatcher2.service);
+                       assertTrue(Dispatcher.getInstance() == null);
+               }
+               finally {
+                       ObjectFactory.setObjectFactory(oldObjecFactory);
+               }
+       }
+       
+       
+       class InnerDispatcher extends Dispatcher {
+               public boolean prepare = false;
+               public boolean wrapRequest = false;
+               public boolean service = false;
+               
+               public InnerDispatcher(ServletContext servletContext) {
+                       super(servletContext);
+               }
+               
+               @Override
+               public void prepare(HttpServletRequest request, 
HttpServletResponse response) {
+                       prepare = true;
+               }
+               
+               @Override
+               public HttpServletRequest wrapRequest(HttpServletRequest 
request, ServletContext servletContext) throws IOException {
+                       wrapRequest = true;
+                       return request;
+               }
+               
+               @Override
+               public void serviceAction(HttpServletRequest request, 
HttpServletResponse response, ServletContext context, ActionMapping mapping) 
throws ServletException {
+                       service = true;
+               }
+       }
+       
+       class NullInnerMapper implements ActionMapper {
+               public ActionMapping getMapping(HttpServletRequest request, 
ConfigurationManager configManager) {
+                       return null;
+               }
+
+               public String getUriFromActionMapping(ActionMapping mapping) {
+                       return null;
+               }
+       }
+       
+       public static class InnerMapper implements ActionMapper {
+               
+               public InnerMapper() {}
+               
+               public ActionMapping getMapping(HttpServletRequest request, 
ConfigurationManager configManager) {
+                       return new ActionMapping();
+               }
+
+               public String getUriFromActionMapping(ActionMapping mapping) {
+                       return "";
+               }
+       }
+       
+       class InnerObjectFactory extends ObjectFactory {
+               public InnerObjectFactory() {
+                       super();
+               }
+       }
+}
+


Reply via email to