mirror of
https://github.com/apache/struts.git
synced 2026-08-11 01:27:14 +00:00
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:
+60
-29
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+31
-4
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user