Solved WW-3488 - exclude copy Action's Errors and Messages from chain

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@997345 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Lukasz Lenart
2010-09-15 14:12:26 +00:00
parent 68c351b793
commit 6956110298
2 changed files with 91 additions and 33 deletions
@@ -26,12 +26,7 @@ import com.opensymphony.xwork2.util.logging.Logger;
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 AbstractInterceptor {
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 AbstractInterceptor {
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 (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");
}
}
if (shouldCopyStack(invocation, root)) {
copyStack(invocation, root);
}
return invocation.invoke();
}
private boolean isChainResult(ActionInvocation invocation) throws Exception {
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 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 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 AbstractInterceptor {
* @param includes the includes list
*/
public void setIncludes(Collection<String> includes) {
this.includes = includes;
this.includes.addAll(includes);
}
}
@@ -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 extends XWorkTestCase {
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 extends XWorkTestCase {
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 extends XWorkTestCase {
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 extends XWorkTestCase {
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());