Author: lukaszlenart
Date: Wed Sep 15 14:12:26 2010
New Revision: 997345

URL: http://svn.apache.org/viewvc?rev=997345&view=rev
Log:
Solved WW-3488 - exclude copy Action's Errors and Messages from chain

Modified:
    
struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/ChainingInterceptor.java
    
struts/struts2/trunk/xwork-core/src/test/java/com/opensymphony/xwork2/interceptor/ChainingInterceptorTest.java

Modified: 
struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/ChainingInterceptor.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/ChainingInterceptor.java?rev=997345&r1=997344&r2=997345&view=diff
==============================================================================
--- 
struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/ChainingInterceptor.java
 (original)
+++ 
struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/ChainingInterceptor.java
 Wed Sep 15 14:12:26 2010
@@ -26,12 +26,7 @@ import com.opensymphony.xwork2.util.logg
 import com.opensymphony.xwork2.util.logging.LoggerFactory;
 import com.opensymphony.xwork2.util.reflection.ReflectionProvider;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 
 /**
@@ -104,6 +99,12 @@ public class ChainingInterceptor extends
 
     private static final Logger LOG = 
LoggerFactory.getLogger(ChainingInterceptor.class);
 
+    private static final String ACTION_ERRORS = "actionErrors";
+    private static final String ACTION_MESSAGES = "actionMessages";
+
+    private boolean copyMessages = false;
+    private boolean copyErrors = false;
+
     protected Collection<String> excludes;
     protected Collection<String> includes;
 
@@ -114,37 +115,67 @@ public class ChainingInterceptor extends
         this.reflectionProvider = prov;
     }
 
+    @Inject(value = "struts.xwork.chaining.copyErrors", required = false)
+    public void setCopyErrors(String copyErrors) {
+        this.copyErrors = "true".equalsIgnoreCase(copyErrors);
+    }
+
+    @Inject(value = "struts.xwork.chaining.copyMessages", required = false)
+    public void setCopyMessages(String copyMessages) {
+        this.copyMessages = "true".equalsIgnoreCase(copyMessages);
+    }
+
     @Override
     public String intercept(ActionInvocation invocation) throws Exception {
         ValueStack stack = invocation.getStack();
         CompoundRoot root = stack.getRoot();
+        if (shouldCopyStack(invocation, root)) {
+            copyStack(invocation, root);
+        }
+        return invocation.invoke();
+    }
 
-        if (root.size() > 1 && isChainResult(invocation)) {
-            List<CompoundRoot> list = new ArrayList<CompoundRoot>(root);
-            list.remove(0);
-            Collections.reverse(list);
-
-            Map<String, Object> ctxMap = 
invocation.getInvocationContext().getContextMap();
-            Iterator<CompoundRoot> iterator = list.iterator();
-            int index = 1; // starts with 1, 0 has been removed
-            while (iterator.hasNext()) {
-                index = index + 1;
-                Object o = iterator.next();
-                if (o != null) {
-                    if (!(o instanceof Unchainable)) {
-                        reflectionProvider.copy(o, invocation.getAction(), 
ctxMap, excludes, includes);
-                    }
-                } else {
-                    LOG.warn("compound root element at index " + index + " is 
null");
+    private void copyStack(ActionInvocation invocation, CompoundRoot root) {
+        List list = prepareList(root);
+        Map<String, Object> ctxMap = 
invocation.getInvocationContext().getContextMap();
+        for (Object object : list) {
+            if (shouldCopy(object)) {
+                reflectionProvider.copy(object, invocation.getAction(), 
ctxMap, prepareExcludes(), includes);
+            }
+        }
+    }
+
+    private Collection<String> prepareExcludes() {
+        Collection<String> localExcludes = excludes;
+        if (!copyErrors || !copyMessages) {
+            if (localExcludes == null) {
+                localExcludes = new HashSet<String>();
+                if (!copyErrors) {
+                    localExcludes.add(ACTION_ERRORS);
+                }
+                if (!copyMessages) {
+                    localExcludes.add(ACTION_MESSAGES);
                 }
             }
         }
-        return invocation.invoke();
+        return localExcludes;
+    }
+
+    private boolean shouldCopy(Object o) {
+        return o != null && !(o instanceof Unchainable);
+    }
+
+    @SuppressWarnings("unchecked")
+    private List prepareList(CompoundRoot root) {
+        List list = new ArrayList(root);
+        list.remove(0);
+        Collections.reverse(list);
+        return list;
     }
 
-    private boolean isChainResult(ActionInvocation invocation) throws 
Exception {
+    private boolean shouldCopyStack(ActionInvocation invocation, CompoundRoot 
root) throws Exception {
         Result result = invocation.getResult();
-        return result != null && 
ActionChainResult.class.isAssignableFrom(result.getClass());
+        return root.size() > 1 && (result == null || 
ActionChainResult.class.isAssignableFrom(result.getClass()));
     }
 
     /**
@@ -180,7 +211,7 @@ public class ChainingInterceptor extends
      * @param includes the includes list
      */
     public void setIncludes(Collection<String> includes) {
-        this.includes = includes;
+        this.includes.addAll(includes);
     }
 
 }

Modified: 
struts/struts2/trunk/xwork-core/src/test/java/com/opensymphony/xwork2/interceptor/ChainingInterceptorTest.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/xwork-core/src/test/java/com/opensymphony/xwork2/interceptor/ChainingInterceptorTest.java?rev=997345&r1=997344&r2=997345&view=diff
==============================================================================
--- 
struts/struts2/trunk/xwork-core/src/test/java/com/opensymphony/xwork2/interceptor/ChainingInterceptorTest.java
 (original)
+++ 
struts/struts2/trunk/xwork-core/src/test/java/com/opensymphony/xwork2/interceptor/ChainingInterceptorTest.java
 Wed Sep 15 14:12:26 2010
@@ -19,10 +19,7 @@ import com.mockobjects.dynamic.Mock;
 import com.opensymphony.xwork2.*;
 import com.opensymphony.xwork2.util.ValueStack;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
+import java.util.*;
 
 
 /**
@@ -45,7 +42,11 @@ public class ChainingInterceptorTest ext
         mockInvocation.matchAndReturn("getAction", action2);
         stack.push(action1);
         stack.push(action2);
+        interceptor.setCopyErrors("true");
+        interceptor.setCopyMessages("true");
+
         interceptor.intercept(invocation);
+
         assertEquals(action1.getActionErrors(), action2.getActionErrors());
         action2.addActionError("bar");
         assertEquals(1, action1.getActionErrors().size());
@@ -53,6 +54,24 @@ public class ChainingInterceptorTest ext
         assertTrue(action2.getActionErrors().contains("bar"));
     }
 
+    public void testActionErrorsNotCopiedAfterChain() throws Exception {
+        SimpleAction action1 = new SimpleAction();
+        SimpleAction action2 = new SimpleAction();
+        action1.addActionError("foo");
+        mockInvocation.matchAndReturn("getAction", action2);
+        stack.push(action1);
+        stack.push(action2);
+
+        interceptor.intercept(invocation);
+
+        assertEquals(Collections.EMPTY_LIST, action2.getActionErrors());
+        action2.addActionError("bar");
+        assertEquals(1, action1.getActionErrors().size());
+        assertEquals(1, action2.getActionErrors().size());
+        assertTrue(action2.getActionErrors().contains("bar"));
+        assertFalse(action2.getActionErrors().contains("foo"));
+    }
+
     public void testPropertiesChained() throws Exception {
         TestBean bean = new TestBean();
         TestBeanAction action = new TestBeanAction();
@@ -62,7 +81,11 @@ public class ChainingInterceptorTest ext
         bean.setCount(1);
         stack.push(bean);
         stack.push(action);
+        interceptor.setCopyErrors("true");
+        interceptor.setCopyMessages("true");
+
         interceptor.intercept(invocation);
+
         assertEquals(bean.getBirth(), action.getBirth());
         assertEquals(bean.getName(), action.getName());
         assertEquals(bean.getCount(), action.getCount());
@@ -77,11 +100,15 @@ public class ChainingInterceptorTest ext
         bean.setCount(1);
         stack.push(bean);
         stack.push(action);
+        interceptor.setCopyErrors("true");
+        interceptor.setCopyMessages("true");
 
         Collection excludes = new ArrayList();
         excludes.add("count");
         interceptor.setExcludes(excludes);
+
         interceptor.intercept(invocation);
+
         assertEquals(bean.getBirth(), action.getBirth());
         assertEquals(bean.getName(), action.getName());
         assertEquals(0, action.getCount());


Reply via email to