http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/java/com/opensymphony/xwork2/validator/URLValidatorTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/com/opensymphony/xwork2/validator/URLValidatorTest.java 
b/core/src/test/java/com/opensymphony/xwork2/validator/URLValidatorTest.java
new file mode 100644
index 0000000..2895d80
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/validator/URLValidatorTest.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2002-2003,2009 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 com.opensymphony.xwork2.validator;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.XWorkTestCase;
+import com.opensymphony.xwork2.util.ValueStack;
+import com.opensymphony.xwork2.validator.validators.URLValidator;
+
+import java.util.regex.Pattern;
+
+/**
+ * Test case for URLValidator
+ * 
+ * @author tm_jee
+ * @version $Date$ $Id$
+ */
+public class URLValidatorTest extends XWorkTestCase {
+
+       
+       ValueStack stack;
+       ActionContext actionContext;
+       
+       public void testAcceptNullValueForMutualExclusionOfValidators() throws 
Exception {
+               
+               URLValidator validator = new URLValidator();
+               validator.setValidatorContext(new GenericValidatorContext(new 
Object()));
+               validator.setFieldName("testingUrl1");
+        validator.setValueStack(ActionContext.getContext().getValueStack());
+        validator.validate(new MyObject());
+               
+               assertFalse(validator.getValidatorContext().hasErrors());
+               assertFalse(validator.getValidatorContext().hasActionErrors());
+               
assertFalse(validator.getValidatorContext().hasActionMessages());
+               assertFalse(validator.getValidatorContext().hasFieldErrors());
+       }
+       
+       public void testInvalidEmptyValue() throws Exception {
+               
+               URLValidator validator = new URLValidator();
+               validator.setValidatorContext(new GenericValidatorContext(new 
Object()));
+               validator.setFieldName("testingUrl2");
+        validator.setValueStack(ActionContext.getContext().getValueStack());
+        validator.validate(new MyObject());
+               
+               assertFalse(validator.getValidatorContext().hasErrors());
+               assertFalse(validator.getValidatorContext().hasActionErrors());
+               
assertFalse(validator.getValidatorContext().hasActionMessages());
+               assertFalse(validator.getValidatorContext().hasFieldErrors());
+       }
+       
+       public void testInvalidValue() throws Exception {
+               
+               URLValidator validator = new URLValidator();
+               validator.setValidatorContext(new GenericValidatorContext(new 
Object()));
+               validator.setFieldName("testingUrl3");
+        validator.setValueStack(ActionContext.getContext().getValueStack());
+        validator.validate(new MyObject());
+               
+               assertTrue(validator.getValidatorContext().hasErrors());
+               assertFalse(validator.getValidatorContext().hasActionErrors());
+               
assertFalse(validator.getValidatorContext().hasActionMessages());
+               assertTrue(validator.getValidatorContext().hasFieldErrors());
+       }
+       
+       
+       public void testValidUrl1() throws Exception {
+               
+               URLValidator validator = new URLValidator();
+               validator.setValidatorContext(new GenericValidatorContext(new 
Object()));
+               validator.setFieldName("testingUrl4");
+        validator.setValueStack(ActionContext.getContext().getValueStack());
+        validator.validate(new MyObject());
+               
+               assertFalse(validator.getValidatorContext().hasErrors());
+               assertFalse(validator.getValidatorContext().hasActionErrors());
+               
assertFalse(validator.getValidatorContext().hasActionMessages());
+               assertFalse(validator.getValidatorContext().hasFieldErrors());
+       }
+       
+       public void testValidUrl2() throws Exception {
+               
+               URLValidator validator = new URLValidator();
+               validator.setValidatorContext(new GenericValidatorContext(new 
Object()));
+               validator.setFieldName("testingUrl5");
+        validator.setValueStack(ActionContext.getContext().getValueStack());
+        validator.validate(new MyObject());
+               
+               assertFalse(validator.getValidatorContext().hasErrors());
+               assertFalse(validator.getValidatorContext().hasActionErrors());
+               
assertFalse(validator.getValidatorContext().hasActionMessages());
+               assertFalse(validator.getValidatorContext().hasFieldErrors());
+       }
+       
+       public void testValidUrlWithRegex() throws Exception {
+               URLValidator validator = new URLValidator();
+
+        validator.setUrlRegex("^myapp:\\/\\/[a-z]*\\.com$");
+
+        Pattern pattern = Pattern.compile(validator.getUrlRegex());
+
+        assertTrue(pattern.matcher("myapp://test.com").matches());
+        assertFalse(pattern.matcher("myap://test.com").matches());
+       }
+
+       public void testValidUrlWithRegexExpression() throws Exception {
+               URLValidator validator = new URLValidator();
+        ActionContext.getContext().getValueStack().push(new MyAction());
+        validator.setValueStack(ActionContext.getContext().getValueStack());
+        validator.setUrlRegexExpression("${urlRegex}");
+
+        Pattern pattern = Pattern.compile(validator.getUrlRegex());
+
+        assertTrue(pattern.matcher("myapp://test.com").matches());
+        assertFalse(pattern.matcher("myap://test.com").matches());
+       }
+
+       public void testValidUrlWithDefaultRegex() throws Exception {
+               URLValidator validator = new URLValidator();
+
+        Pattern pattern = Pattern.compile(validator.getUrlRegex());
+
+        assertFalse(pattern.matcher("myapp://test.com").matches());
+        assertFalse(pattern.matcher("myap://test.com").matches());
+        assertFalse(pattern.matcher("").matches());
+        assertFalse(pattern.matcher("   ").matches());
+        assertFalse(pattern.matcher("no url").matches());
+
+        assertTrue(pattern.matcher("http://www.opensymphony.com";).matches());
+        assertTrue(pattern.matcher("https://www.opensymphony.com";).matches());
+        
assertTrue(pattern.matcher("https://www.opensymphony.com:443/login";).matches());
+        assertTrue(pattern.matcher("http://localhost:8080/myapp";).matches());
+    }
+
+       @Override
+    protected void setUp() throws Exception {
+           super.setUp();
+               stack = ActionContext.getContext().getValueStack();
+               actionContext = ActionContext.getContext();
+       }
+       
+       @Override
+    protected void tearDown() throws Exception {
+           super.tearDown();
+               stack = null;
+               actionContext = null;
+       }
+       
+       
+       class MyObject {
+               public String getTestingUrl1() {
+                       return null;
+               }
+               
+               public String getTestingUrl2() {
+                       return "";
+               }
+               
+               public String getTestingUrl3() {
+                       return "sasdasd@asddd";
+               }
+               
+               public String getTestingUrl4() {
+                       //return "http://yahoo.com/";;
+                       return "http://www.jroller.com1?qwe=qwe";;
+               }
+               
+               public String getTestingUrl5() {
+                       return "http://yahoo.com/articles?id=123";;
+               }
+       }
+
+    class MyAction {
+
+        public String getUrlRegex() {
+            return "myapp:\\/\\/[a-z]*\\.com";
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/java/com/opensymphony/xwork2/validator/ValidatorAnnotationTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/com/opensymphony/xwork2/validator/ValidatorAnnotationTest.java
 
b/core/src/test/java/com/opensymphony/xwork2/validator/ValidatorAnnotationTest.java
new file mode 100644
index 0000000..3991288
--- /dev/null
+++ 
b/core/src/test/java/com/opensymphony/xwork2/validator/ValidatorAnnotationTest.java
@@ -0,0 +1,120 @@
+package com.opensymphony.xwork2.validator;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionProxy;
+import com.opensymphony.xwork2.ValidationAware;
+import com.opensymphony.xwork2.XWorkTestCase;
+import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider;
+
+import java.util.Collection;
+import java.util.HashMap;
+
+/**
+ * Unit test for annotated Validators.
+ *
+ * @author Rainer Hermanns
+ */
+public class ValidatorAnnotationTest extends XWorkTestCase {
+
+    public void testNotAnnotatedMethodSuccess() throws Exception {
+        HashMap<String, Object> params = new HashMap<>();
+        params.put("date", "12/23/2002");
+        params.put("foo", "5");
+        params.put("bar", "7");
+
+        HashMap<String, Object> extraContext = new HashMap<>();
+        extraContext.put(ActionContext.PARAMETERS, params);
+
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", 
"notAnnotatedMethod", extraContext);
+        proxy.execute();
+        assertFalse(((ValidationAware) proxy.getAction()).hasActionErrors());
+
+        Collection errors = ((ValidationAware) 
proxy.getAction()).getActionErrors();
+        assertEquals(0, errors.size());
+    }
+
+    public void testNotAnnotatedMethodSuccess2() throws Exception {
+        HashMap<String, Object> params = new HashMap<>();
+
+        HashMap<String, Object> extraContext = new HashMap<>();
+        extraContext.put(ActionContext.PARAMETERS, params);
+
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", 
"notAnnotatedMethod", extraContext);
+        proxy.execute();
+        assertFalse(((ValidationAware) proxy.getAction()).hasActionErrors());
+
+        Collection errors = ((ValidationAware) 
proxy.getAction()).getActionErrors();
+        assertEquals(0, errors.size());
+    }
+
+    public void testAnnotatedMethodFailure() throws Exception {
+        HashMap<String, Object> params = new HashMap<>();
+
+        HashMap<String, Object> extraContext = new HashMap<>();
+        extraContext.put(ActionContext.PARAMETERS, params);
+
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", 
"annotatedMethod", extraContext);
+        proxy.execute();
+        assertTrue(((ValidationAware) proxy.getAction()).hasActionErrors());
+        Collection errors = ((ValidationAware) 
proxy.getAction()).getActionErrors();
+        assertEquals(1, errors.size());
+
+        assertEquals("Need param1 or param2.", errors.iterator().next());
+
+    }
+
+    public void testAnnotatedMethodSuccess() throws Exception {
+        HashMap<String, Object> params = new HashMap<>();
+
+        //make it not fail
+        params.put("param1", "key1");
+        params.put("param2", "key2");
+
+        HashMap<String, Object> extraContext = new HashMap<>();
+        extraContext.put(ActionContext.PARAMETERS, params);
+
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", 
"annotatedMethod", extraContext);
+        proxy.execute();
+        assertFalse(((ValidationAware) proxy.getAction()).hasActionErrors());
+    }
+
+    public void testAnnotatedMethodSuccess2() throws Exception {
+        HashMap<String, Object> params = new HashMap<>();
+
+        //make it not fail
+        params.put("param2", "key2");
+
+        HashMap<String, Object> extraContext = new HashMap<>();
+        extraContext.put(ActionContext.PARAMETERS, params);
+
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", 
"annotatedMethod", extraContext);
+        proxy.execute();
+        assertFalse(((ValidationAware) proxy.getAction()).hasActionErrors());
+    }
+
+    public void testAnnotatedMethodSuccess3() throws Exception {
+        HashMap<String, Object> params = new HashMap<>();
+
+        //make it not fail
+        params.put("param1", "key1");
+
+        HashMap<String, Object> extraContext = new HashMap<>();
+        extraContext.put(ActionContext.PARAMETERS, params);
+
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", 
"annotatedMethod", extraContext);
+        proxy.execute();
+        assertFalse(((ValidationAware) proxy.getAction()).hasActionErrors());
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        XmlConfigurationProvider provider1 = new 
XmlConfigurationProvider("xwork-default.xml");
+        container.inject(provider1);
+        XmlConfigurationProvider provider2 = new 
XmlConfigurationProvider("xwork-test-validation.xml");
+        container.inject(provider2);
+        loadConfigurationProviders(provider1, provider2);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/java/com/opensymphony/xwork2/validator/VisitorFieldValidatorModelTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/com/opensymphony/xwork2/validator/VisitorFieldValidatorModelTest.java
 
b/core/src/test/java/com/opensymphony/xwork2/validator/VisitorFieldValidatorModelTest.java
new file mode 100644
index 0000000..22488b2
--- /dev/null
+++ 
b/core/src/test/java/com/opensymphony/xwork2/validator/VisitorFieldValidatorModelTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2002-2003,2009 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 com.opensymphony.xwork2.validator;
+
+import com.opensymphony.xwork2.*;
+import com.opensymphony.xwork2.config.entities.ActionConfig;
+import com.opensymphony.xwork2.test.TestBean2;
+
+import java.util.*;
+
+import org.easymock.EasyMock;
+
+
+/**
+ * VisitorFieldValidatorModelTest
+ *
+ * @author Jason Carreira
+ *         Date: Mar 18, 2004 2:51:42 PM
+ */
+public class VisitorFieldValidatorModelTest extends XWorkTestCase {
+
+    protected VisitorValidatorModelAction action;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        action = new VisitorValidatorModelAction();
+
+        TestBean bean = action.getBean();
+        Calendar cal = new GregorianCalendar(1900, 01, 01);
+        bean.setBirth(cal.getTime());
+        bean.setCount(-1);
+
+        ActionConfig config = new ActionConfig.Builder("", "name", "").build();
+        ActionInvocation invocation = 
EasyMock.createNiceMock(ActionInvocation.class);
+        ActionProxy proxy = EasyMock.createNiceMock(ActionProxy.class);
+
+        EasyMock.expect(invocation.getProxy()).andReturn(proxy).anyTimes();
+        EasyMock.expect(invocation.getAction()).andReturn(null).anyTimes();
+        
EasyMock.expect(invocation.invoke()).andReturn(Action.SUCCESS).anyTimes();
+        EasyMock.expect(proxy.getMethod()).andReturn("execute").anyTimes();
+        EasyMock.expect(proxy.getConfig()).andReturn(config).anyTimes();
+
+
+        EasyMock.replay(invocation);
+        EasyMock.replay(proxy);
+
+        ActionContext.getContext().setActionInvocation(invocation);
+
+    }
+
+    public void testModelFieldErrorsAddedWithoutFieldPrefix() throws Exception 
{
+        container.getInstance(ActionValidatorManager.class).validate(action, 
null);
+        assertTrue(action.hasFieldErrors());
+
+        Map<String, List<String>> fieldErrors = action.getFieldErrors();
+
+        // the required string validation inherited from the 
VisitorValidatorTestAction
+        assertTrue(fieldErrors.containsKey("context"));
+
+        // the bean validation which is now at the top level because we set 
the appendPrefix to false
+        assertTrue(fieldErrors.containsKey("name"));
+
+        List<String> nameMessages = fieldErrors.get("name");
+        assertEquals(1, nameMessages.size());
+
+        String nameMessage = (String) nameMessages.get(0);
+        assertEquals("You must enter a name.", nameMessage);
+    }
+
+    public void testModelFieldErrorsAddedWithoutFieldPrefixForInterface() 
throws Exception {
+        TestBean origBean = action.getBean();
+        TestBean2 bean = new TestBean2();
+        bean.setBirth(origBean.getBirth());
+        bean.setCount(origBean.getCount());
+        action.setBean(bean);
+        assertTrue(action.getBean() instanceof TestBean2);
+
+        container.getInstance(ActionValidatorManager.class).validate(action, 
null);
+        assertTrue(action.hasFieldErrors());
+
+        Map<String, List<String>> fieldErrors = action.getFieldErrors();
+
+        // the required string validation inherited from the 
VisitorValidatorTestAction
+        assertTrue(fieldErrors.containsKey("context"));
+
+        // the bean validation which is now at the top level because we set 
the appendPrefix to false
+        assertTrue(fieldErrors.containsKey("name"));
+
+        List<String> nameMessages = fieldErrors.get("name");
+        assertEquals(1, nameMessages.size());
+
+        String nameMessage = nameMessages.get(0);
+        assertEquals("You must enter a name.", nameMessage);
+
+        // should also have picked up validation check for DataAware interface
+        assertTrue(fieldErrors.containsKey("data"));
+
+        List<String> dataMessages = fieldErrors.get("data");
+        assertEquals(1, dataMessages.size());
+
+        String dataMessage = dataMessages.get(0);
+        assertEquals("You must enter a value for data.", dataMessage);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        ActionContext.setContext(null);
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/java/com/opensymphony/xwork2/validator/VisitorFieldValidatorTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/com/opensymphony/xwork2/validator/VisitorFieldValidatorTest.java
 
b/core/src/test/java/com/opensymphony/xwork2/validator/VisitorFieldValidatorTest.java
new file mode 100644
index 0000000..c36f761
--- /dev/null
+++ 
b/core/src/test/java/com/opensymphony/xwork2/validator/VisitorFieldValidatorTest.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2002-2003,2009 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 com.opensymphony.xwork2.validator;
+
+import com.opensymphony.xwork2.*;
+import com.opensymphony.xwork2.config.entities.ActionConfig;
+import org.easymock.EasyMock;
+
+import java.util.*;
+
+/**
+ * VisitorFieldValidatorTest
+ *
+ * @author Jason Carreira
+ *         Created Aug 4, 2003 1:26:01 AM
+ */
+public class VisitorFieldValidatorTest extends XWorkTestCase {
+
+    protected VisitorValidatorTestAction action;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        action = new VisitorValidatorTestAction();
+
+        TestBean bean = action.getBean();
+        Calendar cal = new GregorianCalendar(1900, 01, 01);
+        bean.setBirth(cal.getTime());
+        bean.setCount(-1);
+
+        ActionConfig config = new ActionConfig.Builder("", "name", "").build();
+        ActionInvocation invocation = 
EasyMock.createNiceMock(ActionInvocation.class);
+        ActionProxy proxy = EasyMock.createNiceMock(ActionProxy.class);
+
+        EasyMock.expect(invocation.getProxy()).andReturn(proxy).anyTimes();
+        EasyMock.expect(invocation.getAction()).andReturn(action).anyTimes();
+        
EasyMock.expect(invocation.invoke()).andReturn(Action.SUCCESS).anyTimes();
+        EasyMock.expect(proxy.getMethod()).andReturn("execute").anyTimes();
+        EasyMock.expect(proxy.getConfig()).andReturn(config).anyTimes();
+        
+
+        EasyMock.replay(invocation);
+        EasyMock.replay(proxy);
+
+        ActionContext.getContext().setActionInvocation(invocation);
+    }
+
+    public void testArrayValidation() throws Exception {
+        TestBean[] beanArray = action.getTestBeanArray();
+        TestBean testBean = beanArray[0];
+        testBean.setName("foo");
+        validate("validateArray");
+
+        assertTrue(action.hasFieldErrors());
+
+        Map<String, List<String>> fieldErrors = action.getFieldErrors();
+
+        //4 errors for the array, one for context
+        assertEquals(5, fieldErrors.size());
+        assertTrue(fieldErrors.containsKey("testBeanArray[1].name"));
+
+        //the error from the action should be there too
+        assertTrue(fieldErrors.containsKey("context"));
+
+        List<String> errors = fieldErrors.get("testBeanArray[1].name");
+        assertEquals(1, errors.size());
+        errors = fieldErrors.get("testBeanArray[2].name");
+        assertEquals(1, errors.size());
+        errors = fieldErrors.get("testBeanArray[3].name");
+        assertEquals(1, errors.size());
+        errors = fieldErrors.get("testBeanArray[4].name");
+        assertEquals(1, errors.size());
+    }
+
+    public void testBeanMessagesUseBeanResourceBundle() throws Exception {
+        validate("beanMessageBundle");
+        assertTrue(action.hasFieldErrors());
+
+        Map<String, List<String>> fieldErrors = action.getFieldErrors();
+        assertTrue(fieldErrors.containsKey("bean.count"));
+
+        List<String> beanCountMessages = fieldErrors.get("bean.count");
+        assertEquals(1, beanCountMessages.size());
+
+        String beanCountMessage = beanCountMessages.get(0);
+        assertEquals("bean: Invalid count value, must be between 1 and 100, 
current value -1!", beanCountMessage);
+    }
+
+    public void testCollectionValidation() throws Exception {
+        List testBeanList = action.getTestBeanList();
+        TestBean testBean = (TestBean) testBeanList.get(0);
+        testBean.setName("foo");
+        validate("validateList");
+
+        assertTrue(action.hasFieldErrors());
+
+        Map<String, List<String>> fieldErrors = action.getFieldErrors();
+
+        //4 for the list, 1 for context
+        assertEquals(5, fieldErrors.size());
+        assertTrue(fieldErrors.containsKey("testBeanList[1].name"));
+
+        //the error from the action should be there too
+        assertTrue(fieldErrors.containsKey("context"));
+
+        List<String> errors = fieldErrors.get("testBeanList[1].name");
+        assertEquals(1, errors.size());
+        errors = fieldErrors.get("testBeanList[2].name");
+        assertEquals(1, errors.size());
+        errors = fieldErrors.get("testBeanList[3].name");
+        assertEquals(1, errors.size());
+        errors = fieldErrors.get("testBeanList[4].name");
+        assertEquals(1, errors.size());
+    }
+
+    public void testContextIsOverriddenByContextParamInValidationXML() throws 
Exception {
+        validate("visitorValidationAlias");
+        assertTrue(action.hasFieldErrors());
+
+        Map<String, List<String>> fieldErrors = action.getFieldErrors();
+        assertEquals(3, fieldErrors.size());
+        assertTrue(fieldErrors.containsKey("bean.count"));
+        assertTrue(fieldErrors.containsKey("bean.name"));
+        assertTrue(!fieldErrors.containsKey("bean.birth"));
+
+        //the error from the action should be there too
+        assertTrue(fieldErrors.containsKey("context"));
+    }
+
+    public void testContextIsPropagated() throws Exception {
+        validate("visitorValidation");
+        assertTrue(action.hasFieldErrors());
+
+        Map<String, List<String>> fieldErrors = action.getFieldErrors();
+        assertEquals(3, fieldErrors.size());
+        assertTrue(!fieldErrors.containsKey("bean.count"));
+        assertTrue(fieldErrors.containsKey("bean.name"));
+        assertTrue(fieldErrors.containsKey("bean.birth"));
+
+        //the error from the action should be there too
+        assertTrue(fieldErrors.containsKey("context"));
+    }
+
+    public void testVisitorChildValidation() throws Exception {
+        validate("visitorChildValidation");
+        assertTrue(action.hasFieldErrors());
+
+        Map<String, List<String>> fieldErrors = action.getFieldErrors();
+        assertEquals(5, fieldErrors.size());
+        assertTrue(!fieldErrors.containsKey("bean.count"));
+        assertTrue(fieldErrors.containsKey("bean.name"));
+        assertTrue(fieldErrors.containsKey("bean.birth"));
+
+        assertTrue(fieldErrors.containsKey("bean.child.name"));
+        assertTrue(fieldErrors.containsKey("bean.child.birth"));
+        
+        //the error from the action should be there too
+        assertTrue(fieldErrors.containsKey("context"));
+    }
+
+    public void testVisitorChildConversionValidation() throws Exception {
+        //add conversion error
+        Map<String, Object> conversionErrors = new HashMap<>();
+        conversionErrors.put("bean.child.count", "bar");
+        ActionContext.getContext().setConversionErrors(conversionErrors);
+
+        validate("visitorChildValidation");
+        assertTrue(action.hasFieldErrors());
+
+        Map<String, List<String>> fieldErrors = action.getFieldErrors();
+        assertEquals(6, fieldErrors.size());
+        assertTrue(!fieldErrors.containsKey("bean.count"));
+        assertTrue(fieldErrors.containsKey("bean.name"));
+        assertTrue(fieldErrors.containsKey("bean.birth"));
+
+        assertTrue(fieldErrors.containsKey("bean.child.name"));
+        assertTrue(fieldErrors.containsKey("bean.child.birth"));
+
+        //the error from the action should be there too
+        assertTrue(fieldErrors.containsKey("context"));
+
+        //nested visitor conversion error
+        assertTrue(fieldErrors.containsKey("bean.child.count"));
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        ActionContext.setContext(null);
+    }
+
+    private void validate(String context) throws ValidationException {
+        ActionContext actionContext = ActionContext.getContext();
+        actionContext.setName(context);
+        container.getInstance(ActionValidatorManager.class).validate(action, 
context);
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/java/com/opensymphony/xwork2/validator/VisitorValidatorModelAction.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/com/opensymphony/xwork2/validator/VisitorValidatorModelAction.java
 
b/core/src/test/java/com/opensymphony/xwork2/validator/VisitorValidatorModelAction.java
new file mode 100644
index 0000000..9f16e3e
--- /dev/null
+++ 
b/core/src/test/java/com/opensymphony/xwork2/validator/VisitorValidatorModelAction.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2002-2003,2009 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 com.opensymphony.xwork2.validator;
+
+import com.opensymphony.xwork2.ModelDriven;
+
+
+/**
+ * VisitorValidatorModelAction
+ *
+ * @author Jason Carreira
+ *         Date: Mar 18, 2004 11:26:46 AM
+ */
+public class VisitorValidatorModelAction extends VisitorValidatorTestAction 
implements ModelDriven {
+
+    /**
+     * @return the model to be pushed onto the ValueStack instead of the 
Action itself
+     */
+    public Object getModel() {
+        return getBean();
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/java/com/opensymphony/xwork2/validator/VisitorValidatorTestAction.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/com/opensymphony/xwork2/validator/VisitorValidatorTestAction.java
 
b/core/src/test/java/com/opensymphony/xwork2/validator/VisitorValidatorTestAction.java
new file mode 100644
index 0000000..fad95fb
--- /dev/null
+++ 
b/core/src/test/java/com/opensymphony/xwork2/validator/VisitorValidatorTestAction.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2002-2003,2009 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 com.opensymphony.xwork2.validator;
+
+import com.opensymphony.xwork2.ActionSupport;
+import com.opensymphony.xwork2.TestBean;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * VisitorValidatorTestAction
+ *
+ * @author Jason Carreira
+ *         Created Aug 4, 2003 1:00:04 AM
+ */
+public class VisitorValidatorTestAction extends ActionSupport {
+
+    private List<TestBean> testBeanList = new ArrayList<>();
+    private String context;
+    private TestBean bean = new TestBean();
+    private TestBean[] testBeanArray;
+
+
+    public VisitorValidatorTestAction() {
+        testBeanArray = new TestBean[5];
+
+        for (int i = 0; i < 5; i++) {
+            testBeanArray[i] = new TestBean();
+            testBeanList.add(new TestBean());
+        }
+    }
+
+
+    public void setBean(TestBean bean) {
+        this.bean = bean;
+    }
+
+    public TestBean getBean() {
+        return bean;
+    }
+
+    public void setContext(String context) {
+        this.context = context;
+    }
+
+    public String getContext() {
+        return context;
+    }
+
+    public void setTestBeanArray(TestBean[] testBeanArray) {
+        this.testBeanArray = testBeanArray;
+    }
+
+    public TestBean[] getTestBeanArray() {
+        return testBeanArray;
+    }
+
+    public void setTestBeanList(List<TestBean> testBeanList) {
+        this.testBeanList = testBeanList;
+    }
+
+    public List<TestBean> getTestBeanList() {
+        return testBeanList;
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/resources/PackagelessAction.properties
----------------------------------------------------------------------
diff --git a/core/src/test/resources/PackagelessAction.properties 
b/core/src/test/resources/PackagelessAction.properties
new file mode 100644
index 0000000..577c6d3
--- /dev/null
+++ b/core/src/test/resources/PackagelessAction.properties
@@ -0,0 +1 @@
+actionProperty = action property

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/resources/includeTest.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/includeTest.xml 
b/core/src/test/resources/includeTest.xml
new file mode 100644
index 0000000..d8b2a19
--- /dev/null
+++ b/core/src/test/resources/includeTest.xml
@@ -0,0 +1,10 @@
+<!DOCTYPE xwork PUBLIC
+    "-//Apache Struts//XWork 1.1.1//EN"
+    "http://struts.apache.org/dtds/xwork-1.1.1.dtd";
+ >
+
+<xwork>
+    <package name="includeTest" extends="default" namespace="includeTest">
+        <action name="includeTest" 
class="com.opensymphony.xwork2.SimpleAction"></action>
+    </package>
+</xwork>

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/resources/log4j2.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/log4j2.xml 
b/core/src/test/resources/log4j2.xml
index 4b13539..263585e 100644
--- a/core/src/test/resources/log4j2.xml
+++ b/core/src/test/resources/log4j2.xml
@@ -2,11 +2,11 @@
 <Configuration>
     <Appenders>
         <Console name="STDOUT" target="SYSTEM_OUT">
-            <PatternLayout pattern="%d{ISO8601} %-5p [%F:%L] : %m%n"/>
+            <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
         </Console>
     </Appenders>
     <Loggers>
-        <Root level="warn">
+        <Root level="info">
             <AppenderRef ref="STDOUT"/>
         </Root>
     </Loggers>

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/resources/my-validators.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/my-validators.xml 
b/core/src/test/resources/my-validators.xml
new file mode 100644
index 0000000..ac5f2e7
--- /dev/null
+++ b/core/src/test/resources/my-validators.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE validators PUBLIC
+        "-//Apache Struts//XWork Validator Config 1.0//EN"
+        "http://struts.apache.org/dtds/xwork-validator-config-1.0.dtd";>
+<validators>
+    <validator name="requiredAdditional" 
class="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"/>
+</validators>

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/resources/myOther-validators.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/myOther-validators.xml 
b/core/src/test/resources/myOther-validators.xml
new file mode 100644
index 0000000..c8fd91b
--- /dev/null
+++ b/core/src/test/resources/myOther-validators.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE validators PUBLIC
+        "-//Apache Struts//XWork Validator Config 1.0//EN"
+        "http://struts.apache.org/dtds/xwork-validator-config-1.0.dtd";>
+<validators>
+    <validator name="requiredAnother" 
class="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"/>
+</validators>

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/resources/validators.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/validators.xml 
b/core/src/test/resources/validators.xml
index 5e539bc..48369fa 100644
--- a/core/src/test/resources/validators.xml
+++ b/core/src/test/resources/validators.xml
@@ -1,26 +1,4 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
- * $Id$
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
--->
 <!DOCTYPE validators PUBLIC
         "-//Apache Struts//XWork Validator Config 1.0//EN"
         "http://struts.apache.org/dtds/xwork-validator-config-1.0.dtd";>
@@ -38,4 +16,5 @@
     <validator name="conversion" 
class="com.opensymphony.xwork2.validator.validators.ConversionErrorFieldValidator"/>
     <validator name="stringlength" 
class="com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator"/>
     <validator name="regex" 
class="com.opensymphony.xwork2.validator.validators.RegexFieldValidator"/>
+    <validator name="conditionalvisitor" 
class="com.opensymphony.xwork2.validator.validators.ConditionalVisitorFieldValidator"/>
 </validators>

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/resources/xwork
 - jar.jar
----------------------------------------------------------------------
diff --git a/core/src/test/resources/xwork - jar.jar 
b/core/src/test/resources/xwork - jar.jar
new file mode 100644
index 0000000..00497c2
Binary files /dev/null and b/core/src/test/resources/xwork - jar.jar differ

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/resources/xwork
 - zip.zip
----------------------------------------------------------------------
diff --git a/core/src/test/resources/xwork - zip.zip 
b/core/src/test/resources/xwork - zip.zip
new file mode 100644
index 0000000..9fcbeee
Binary files /dev/null and b/core/src/test/resources/xwork - zip.zip differ

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/resources/xwork-1.0.dtd
----------------------------------------------------------------------
diff --git a/core/src/test/resources/xwork-1.0.dtd 
b/core/src/test/resources/xwork-1.0.dtd
new file mode 100644
index 0000000..d04fb7b
--- /dev/null
+++ b/core/src/test/resources/xwork-1.0.dtd
@@ -0,0 +1 @@
+Duplicate file test
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/resources/xwork-class-param-test.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/xwork-class-param-test.xml 
b/core/src/test/resources/xwork-class-param-test.xml
new file mode 100644
index 0000000..f12c083
--- /dev/null
+++ b/core/src/test/resources/xwork-class-param-test.xml
@@ -0,0 +1,11 @@
+<!DOCTYPE xwork PUBLIC
+        "-//Apache Struts//XWork 2.0//EN"
+        "http://struts.apache.org/dtds/xwork-2.0.dtd";>
+
+<xwork>
+
+    <constant name="devMode" value="true" />
+    <constant name="ognlExcludedClasses" 
value="java.lang.Object,java.lang.Runtime" />
+    <constant name="overrideExcludedPatterns" value="not-existing-pattern"/>
+
+</xwork>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/resources/xwork-jar.jar
----------------------------------------------------------------------
diff --git a/core/src/test/resources/xwork-jar.jar 
b/core/src/test/resources/xwork-jar.jar
new file mode 100644
index 0000000..1818394
Binary files /dev/null and b/core/src/test/resources/xwork-jar.jar differ

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/resources/xwork-param-test.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/xwork-param-test.xml 
b/core/src/test/resources/xwork-param-test.xml
new file mode 100644
index 0000000..7a97df1
--- /dev/null
+++ b/core/src/test/resources/xwork-param-test.xml
@@ -0,0 +1,9 @@
+<!DOCTYPE xwork PUBLIC
+        "-//Apache Struts//XWork 2.0//EN"
+        "http://struts.apache.org/dtds/xwork-2.0.dtd";>
+
+<xwork>
+       <constant name="devMode" value="true" />
+    <constant name="ognlExcludedClasses" 
value="java.lang.Object,java.lang.Runtime" />
+    <constant name="additionalExcludedPatterns" 
value=".*(^|\.|\[|\'|&quot;)class(\.|\[|\'|&quot;).*" />
+</xwork>

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/resources/xwork-proxyinvoke.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/xwork-proxyinvoke.xml 
b/core/src/test/resources/xwork-proxyinvoke.xml
new file mode 100644
index 0000000..7338496
--- /dev/null
+++ b/core/src/test/resources/xwork-proxyinvoke.xml
@@ -0,0 +1,48 @@
+<!DOCTYPE xwork PUBLIC
+        "-//Apache Struts//XWork 2.0//EN"
+        "http://struts.apache.org/dtds/xwork-2.0.dtd";>
+
+<xwork>
+    <bean type="com.opensymphony.xwork2.ObjectFactory" name="default" 
class="com.opensymphony.xwork2.ProxyObjectFactory" />
+
+       <bean type="com.opensymphony.xwork2.ActionProxyFactory" name="default" 
class="com.opensymphony.xwork2.DefaultActionProxyFactory"/>
+       <constant name="devMode" value="false" />
+
+    <package name="xwork-test-default">
+        <result-types>
+            <result-type name="chain" 
class="com.opensymphony.xwork2.ActionChainResult" default="true"/>
+            <result-type name="void" 
class="com.opensymphony.xwork2.VoidResult"/>
+            <result-type name="mock" 
class="com.opensymphony.xwork2.mock.MockResult"/>
+        </result-types>
+
+        <interceptors>
+            <interceptor name="timer" 
class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>
+            <interceptor name="logger" 
class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/>
+            <interceptor name="chain" 
class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>
+            <interceptor name="params" 
class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
+            <interceptor name="staticParams" 
class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
+            <interceptor name="modelDriven" 
class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
+            <interceptor name="validation" 
class="com.opensymphony.xwork2.validator.ValidationInterceptor"/>
+                       <interceptor name="alias" 
class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
+            <interceptor name="test" 
class="com.opensymphony.xwork2.mock.MockInterceptor">
+                <param name="foo">expectedFoo</param>
+            </interceptor>
+
+            <interceptor-stack name="defaultStack">
+                <interceptor-ref name="staticParams"/>
+                <interceptor-ref name="modelDriven"/>
+                <interceptor-ref name="params"/>
+            </interceptor-stack>
+
+            <interceptor-stack name="debugStack">
+                <interceptor-ref name="timer"/>
+                <interceptor-ref name="logger"/>
+            </interceptor-stack>
+        </interceptors>
+    </package>
+
+    <package name="default" extends="xwork-test-default">
+
+        <action name="ProxyInvocation" method="show" 
class="com.opensymphony.xwork2.ProxyInvocationAction"/>
+    </package>
+</xwork>

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/resources/xwork-sample.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/xwork-sample.xml 
b/core/src/test/resources/xwork-sample.xml
new file mode 100644
index 0000000..3705298
--- /dev/null
+++ b/core/src/test/resources/xwork-sample.xml
@@ -0,0 +1,238 @@
+<!DOCTYPE xwork PUBLIC
+    "-//Apache Struts//XWork 2.0//EN"
+    "http://struts.apache.org/dtds/xwork-2.0.dtd";
+ >
+ <!-- "file:///temp/ross/xwork/src/etc/xwork-1.0.dtd"  -->
+
+<xwork>
+    <include file="xwork-test-default.xml"/>
+    <package name="default" extends="xwork-test-default">
+
+        <global-results>
+            <result name="login"> <!-- should be chain type since it is the 
default -->
+                <param name="actionName">login</param>
+            </result>
+        </global-results>
+
+        <action name="Foo" class="com.opensymphony.xwork2.SimpleAction">
+            <param name="foo">17</param>
+            <param name="bar">23</param>
+            <result name="success" type="chain">
+                <param name="actionName">Bar</param>
+            </result>
+            <interceptor-ref name="debugStack"/>
+            <interceptor-ref name="defaultStack"/>
+        </action>
+
+        <action name="WildCard" class="com.opensymphony.xwork2.SimpleAction">
+            <param name="foo">17</param>
+            <param name="bar">23</param>
+            <result name="success" type="void" />
+            <result name="*" type="mock" />
+            <interceptor-ref name="defaultStack"/>
+        </action>
+
+        <action name="WildCardInput" 
class="com.opensymphony.xwork2.SimpleAction" method="input">
+            <param name="foo">17</param>
+            <param name="bar">23</param>
+            <result name="success" type="void" />
+            <result name="*" type="mock" />
+            <interceptor-ref name="defaultStack"/>
+        </action>
+
+        <action name="WildCardError" 
class="com.opensymphony.xwork2.SimpleAction">
+            <result name="success" type="void" />
+            <result name="*" type="mock" />
+            <interceptor-ref name="defaultStack"/>
+        </action>
+               
+               <action name="WildCard/*/*" 
class="com.opensymphony.xwork2.{1}Action" 
+                       method="{2}">
+            <param name="foo">{1}</param>
+            <param name="bar">{2}</param>
+            <result name="success" type="void" />
+            <interceptor-ref name="defaultStack"/>
+        </action>
+
+        <action name="aliasTest" class="com.opensymphony.xwork2.SimpleAction">
+               <param name="aliases">#{ "aliasSource" : "aliasDest", 
"bar":"baz" }</param>
+                       <interceptor-ref name="params"/>
+               <interceptor-ref name="alias"/>
+               <result name="success" type="mock" />
+        </action>
+      
+        <action name="packagelessAction" class="PackagelessAction">
+        </action>
+
+        <action name="Bar" class="com.opensymphony.xwork2.SimpleAction">
+               <param name="foo">17</param>
+            <param name="bar">23</param>
+            <result name="error" type="mock" />
+        </action>
+
+        <action name="MyBean" 
class="com.opensymphony.xwork2.util.MyBeanAction">
+            <interceptor-ref name="debugStack"/>
+            <interceptor-ref name="defaultStack"/>
+            <result name="success" type="mock" />
+        </action>
+
+        <action name="TestInterceptorParam" 
class="com.opensymphony.xwork2.SimpleAction">
+            <interceptor-ref name="test">
+                <param name="expectedFoo">expectedFoo</param>
+            </interceptor-ref>
+            <result name="error" type="mock" />
+        </action>
+
+        <action name="TestInterceptorParamOverride" 
class="com.opensymphony.xwork2.SimpleAction">
+            <interceptor-ref name="test">
+                <param name="foo">foo123</param>
+                <param name="expectedFoo">foo123</param>
+            </interceptor-ref>
+            <result name="error" type="mock" />
+        </action>
+       
+        <action name="TestModelDrivenValidation" 
class="com.opensymphony.xwork2.ModelDrivenAction">
+            <interceptor-ref name="defaultStack"/>
+            <interceptor-ref name="validation"/>
+            <result name="success" type="mock" />
+        </action>
+
+        <!-- chain resursion detection -->
+        <action name="InfiniteRecursionChain" 
class="com.opensymphony.xwork2.ActionSupport">
+                <result name="success" 
type="chain">InfiniteRecursionChain</result>
+        </action>
+
+   </package>
+
+   <package name="bar" extends="default" namespace="/foo/bar">
+        <interceptors>
+            <interceptor-stack name="barDefaultStack">
+                <interceptor-ref name="debugStack"/>
+                <interceptor-ref name="defaultStack"/>
+            </interceptor-stack>
+        </interceptors>
+
+        <global-exception-mappings>
+            <exception-mapping name="foo" 
exception="com.opensymphony.TestException" result="foo"/>
+        </global-exception-mappings>
+
+        <action name="Bar" class="com.opensymphony.xwork2.SimpleAction">
+            <interceptor-ref name="barDefaultStack"/>
+            <result name="error" type="mock" />
+        </action>
+
+        <action name="TestInterceptorParamInheritance" 
class="com.opensymphony.xwork2.SimpleAction">
+            <interceptor-ref name="test">
+                <param name="expectedFoo">expectedFoo</param>
+            </interceptor-ref>
+            <result name="error" type="mock" />
+        </action>
+
+        <action name="TestInterceptorParamInehritanceOverride" 
class="com.opensymphony.xwork2.SimpleAction">
+            <interceptor-ref name="test">
+                <param name="foo">foo123</param>
+                <param name="expectedFoo">foo123</param>
+            </interceptor-ref>
+            <result name="error" type="mock" />
+        </action>
+    </package>
+
+    <package name="abstractPackage" namespace="/abstract" abstract="true">
+        <action name="test" class="com.opensymphony.xwork2.SimpleAction"/>
+    </package>
+
+    <package name="nonAbstractPackage" extends="abstractPackage" 
namespace="/nonAbstract"/>
+
+    <package name="baz" extends="default" namespace="baz">
+        <action name="commandTest" 
class="com.opensymphony.xwork2.SimpleAction">
+            <param name="foo">123</param>
+            <result name="error" type="chain">
+                <param name="actionName">bar</param>
+            </result>
+            <result name="success" type="mock" />
+            <interceptor-ref name="staticParams"/>
+        </action>
+        <action name="myCommand" class="com.opensymphony.xwork2.SimpleAction" 
method="commandMethod">
+            <param name="bar">456</param>
+            <result name="success" type="chain">
+                <param name="actionName">foo</param>
+            </result>
+            <result name="com.opensymphony.xwork2.SimpleAction.CommandInvoked" 
type="mock"/>
+            <interceptor-ref name="logger"/>
+        </action>
+        <action name="doMethodTest" 
class="com.opensymphony.xwork2.SimpleAction" method="input">
+            <result name="input" type="mock" />
+        </action>
+        <action name="unknownMethodTest" 
class="com.opensymphony.xwork2.SimpleAction">
+            <result name="found" type="mock" />
+        </action>
+        <action name="resultAction" 
class="com.opensymphony.xwork2.SimpleAction" method="resultAction">
+            <param name="bar">456</param>
+            <result name="success" type="chain">
+                <param name="actionName">foo</param>
+            </result>
+            <interceptor-ref name="logger"/>
+        </action>
+    </package>
+
+    <package name="wildcardNamespaces" extends="default" 
namespace="/animals/*">
+        <action name="commandTest" 
class="com.opensymphony.xwork2.SimpleAction">
+            <result name="success" type="mock" />
+            <interceptor-ref name="staticParams"/>
+        </action>
+    </package>
+
+    <package name="multipleInheritance" extends="default,abstractPackage,bar" 
namespace="multipleInheritance">
+        <action name="testMultipleInheritance" 
class="com.opensymphony.xwork2.SimpleAction">
+            <result name="success" type="chain">
+                <param name="actionName">foo</param>
+            </result>
+            <interceptor-ref name="barDefaultStack"/>
+        </action>
+    </package>
+
+
+       <package name="Abstract-crud" extends="default">
+       <!--  edit is often used as the create/view -->
+                          <default-class-ref 
class="com.opensymphony.xwork2.SimpleAction"/>
+                <action name="edit" >
+                        <result name="input" type="mock">edit.vm</result>
+                        <result name="success" type="mock">edit.vm</result>
+                        <result name="error" type="mock">edit.vm</result>
+                </action>
+                <action name="save" >
+                        <result name="input" type="mock">edit.vm</result>
+                        <result name="success" type="chain">list</result>
+                        <result name="error" type="mock">edit.vm</result>
+                        <result name="cancel" type="mock">list.action</result>
+                </action>
+                <action name="list">
+                        <result name="success" type="mock">list</result>
+                </action>
+                <action name="delete">
+                        <result name="success" type="mock">list</result>
+                </action>
+
+        </package>
+       
+        <package name="Example" extends="Abstract-crud" namespace="/example">
+                 <default-class-ref 
class="com.opensymphony.xwork2.ModelDrivenAction" />
+        </package>
+
+        <package name="Example2" extends="Abstract-crud" namespace="/example2">
+                <default-class-ref 
class="com.opensymphony.xwork2.ModelDrivenAction" />
+                <action name="override">
+                        <result name="success" 
type="mock">somethingelse.vm</result>
+                </action>
+        </package>
+
+        <package name="SubItem" extends="Abstract-crud" 
namespace="/example2/subItem">
+                <default-class-ref 
class="com.opensymphony.xwork2.ModelDrivenAction" />
+        </package> 
+        
+        <package name="Example3" extends="Abstract-crud" namespace="/example3">
+                       <!--  default-class-ref is expected to be inherited -->
+        </package>
+
+    <include file="includeTest.xml"/>
+</xwork>

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/resources/xwork-test-beans.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/xwork-test-beans.xml 
b/core/src/test/resources/xwork-test-beans.xml
new file mode 100644
index 0000000..1606f1d
--- /dev/null
+++ b/core/src/test/resources/xwork-test-beans.xml
@@ -0,0 +1,9 @@
+<!DOCTYPE xwork PUBLIC
+        "-//Apache Struts//XWork 2.0//EN"
+        "http://struts.apache.org/dtds/xwork-2.0.dtd";>
+
+<xwork>
+
+    <constant name="ognlExcludedClasses" 
value="java.lang.Object,java.lang.Runtime,ognl.OgnlContext,ognl.MemberAccess,ognl.ClassResolver,ognl.TypeConverter,com.opensymphony.xwork2.ognl.SecurityMemberAccess"
 />
+
+</xwork>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/resources/xwork-test-default.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/xwork-test-default.xml 
b/core/src/test/resources/xwork-test-default.xml
new file mode 100644
index 0000000..bceeb32
--- /dev/null
+++ b/core/src/test/resources/xwork-test-default.xml
@@ -0,0 +1,39 @@
+<!DOCTYPE xwork PUBLIC
+    "-//Apache Struts//XWork 2.0//EN"
+    "http://struts.apache.org/dtds/xwork-2.0.dtd";
+ >
+
+<xwork>
+    <package name="xwork-test-default">
+        <result-types>
+            <result-type name="chain" 
class="com.opensymphony.xwork2.ActionChainResult" default="true"/>
+            <result-type name="void" 
class="com.opensymphony.xwork2.VoidResult"/>
+            <result-type name="mock" 
class="com.opensymphony.xwork2.mock.MockResult"/>
+        </result-types>
+
+        <interceptors>
+            <interceptor name="timer" 
class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>
+            <interceptor name="logger" 
class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/>
+            <interceptor name="chain" 
class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>
+            <interceptor name="params" 
class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
+            <interceptor name="staticParams" 
class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
+            <interceptor name="modelDriven" 
class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
+            <interceptor name="validation" 
class="com.opensymphony.xwork2.validator.ValidationInterceptor"/>
+                       <interceptor name="alias" 
class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
+            <interceptor name="test" 
class="com.opensymphony.xwork2.mock.MockInterceptor">
+                <param name="foo">expectedFoo</param>
+            </interceptor>
+
+            <interceptor-stack name="defaultStack">
+                <interceptor-ref name="staticParams"/>
+                <interceptor-ref name="modelDriven"/>
+                <interceptor-ref name="params"/>
+            </interceptor-stack>
+
+            <interceptor-stack name="debugStack">
+                <interceptor-ref name="timer"/>
+                <interceptor-ref name="logger"/>
+            </interceptor-stack>
+        </interceptors>
+    </package>
+</xwork>

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/resources/xwork-test-validation.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/xwork-test-validation.xml 
b/core/src/test/resources/xwork-test-validation.xml
new file mode 100644
index 0000000..65b3556
--- /dev/null
+++ b/core/src/test/resources/xwork-test-validation.xml
@@ -0,0 +1,64 @@
+<!DOCTYPE xwork PUBLIC
+    "-//Apache Struts//XWork 2.0//EN"
+    "http://struts.apache.org/dtds/xwork-2.0.dtd";
+ >
+
+<xwork>
+       <include file="xwork-test-beans.xml" />
+    <package name="xwork-test-default">
+        <result-types>
+            <result-type name="chain" 
class="com.opensymphony.xwork2.ActionChainResult" default="true"/>
+            <result-type name="void" 
class="com.opensymphony.xwork2.VoidResult"/>
+            <result-type name="mock" 
class="com.opensymphony.xwork2.mock.MockResult"/>
+        </result-types>
+
+        <interceptors>
+            <interceptor name="timer" 
class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>
+            <interceptor name="logger" 
class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/>
+            <interceptor name="chain" 
class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>
+            <interceptor name="params" 
class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
+            <interceptor name="staticParams" 
class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
+            <interceptor name="modelDriven" 
class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
+            <interceptor name="validation" 
class="com.opensymphony.xwork2.validator.ValidationInterceptor">
+                <param name="validateAnnotatedMethodOnly">true</param>
+            </interceptor>
+                       <interceptor name="alias" 
class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
+            <interceptor name="test" 
class="com.opensymphony.xwork2.mock.MockInterceptor">
+                <param name="foo">expectedFoo</param>
+            </interceptor>
+
+            <interceptor-stack name="defaultStack">
+                <interceptor-ref name="staticParams"/>
+                <interceptor-ref name="modelDriven"/>
+                <interceptor-ref name="params"/>
+            </interceptor-stack>
+
+            <interceptor-stack name="debugStack">
+                <interceptor-ref name="timer"/>
+                <interceptor-ref name="logger"/>
+            </interceptor-stack>
+
+            <interceptor-stack name="validationStack">
+                <interceptor-ref name="staticParams"/>
+                <interceptor-ref name="modelDriven"/>
+                <interceptor-ref name="params"/>
+                <interceptor-ref name="validation"/>
+            </interceptor-stack>
+        </interceptors>
+
+    </package>
+    <package name="default" extends="xwork-test-default">
+
+        <action name="annotatedMethod" 
class="com.opensymphony.xwork2.test.annotations.ValidateAnnotatedMethodOnlyAction"
 method="annotatedMethod">
+            <interceptor-ref name="validationStack"/>
+            <result name="success" type="mock"/>
+        </action>
+        
+        <action name="notAnnotatedMethod" 
class="com.opensymphony.xwork2.test.annotations.ValidateAnnotatedMethodOnlyAction"
 method="notAnnotatedMethod">
+            <interceptor-ref name="validationStack"/>
+            <result name="success" type="mock"/>
+        </action>
+
+    </package>
+
+</xwork>

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/resources/xwork-zip.zip
----------------------------------------------------------------------
diff --git a/core/src/test/resources/xwork-zip.zip 
b/core/src/test/resources/xwork-zip.zip
new file mode 100644
index 0000000..596606b
Binary files /dev/null and b/core/src/test/resources/xwork-zip.zip differ

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/plugins/java8-support/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/java8-support/pom.xml b/plugins/java8-support/pom.xml
index 1bd614e..49dee3f 100644
--- a/plugins/java8-support/pom.xml
+++ b/plugins/java8-support/pom.xml
@@ -31,8 +31,8 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.apache.struts.xwork</groupId>
-            <artifactId>xwork-core</artifactId>
+            <groupId>org.apache.struts</groupId>
+            <artifactId>struts2-core</artifactId>
             <exclusions>
                 <exclusion>
                     <groupId>asm</groupId>

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 73d9599..1b8474e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -61,7 +61,6 @@
 
     <modules>
         <module>bom</module>
-        <module>xwork-core</module>
         <module>core</module>
         <module>apps</module>
         <module>plugins</module>
@@ -357,11 +356,6 @@
             </dependency>
 
             <dependency>
-                <groupId>org.apache.struts.xwork</groupId>
-                <artifactId>xwork-core</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
                 <groupId>org.apache.struts</groupId>
                 <artifactId>struts2-core</artifactId>
                 <version>${project.version}</version>

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/xwork-core/pom.xml
----------------------------------------------------------------------
diff --git a/xwork-core/pom.xml b/xwork-core/pom.xml
deleted file mode 100644
index 3ba6461..0000000
--- a/xwork-core/pom.xml
+++ /dev/null
@@ -1,239 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
-
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>org.apache.struts</groupId>
-        <artifactId>struts2-parent</artifactId>
-        <version>2.5-SNAPSHOT</version>
-    </parent>
-
-    <groupId>org.apache.struts.xwork</groupId>
-    <artifactId>xwork-core</artifactId>
-    <packaging>jar</packaging>
-    <name>XWork: Core</name>
-
-    <properties>
-        <currentVersion>${project.version}</currentVersion>
-        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    </properties>
-
-    <build>
-        <sourceDirectory>${basedir}/src/main/java</sourceDirectory>
-        <testSourceDirectory>${basedir}/src/test/java</testSourceDirectory>
-        <resources>
-            <resource>
-                <directory>${basedir}/src/main/resources</directory>
-            </resource>
-        </resources>
-        <testResources>
-            <testResource>
-                <directory>${basedir}/src/test/resources</directory>
-            </testResource>
-        </testResources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-surefire-plugin</artifactId>
-                <version>2.6</version>
-                <configuration>
-                    <argLine>-Duser.language=en -Duser.region=US</argLine>
-                    <properties>
-                        <property>
-                            <name>maven.testng.output.dir</name>
-                            
<value>${project.basedir}/target/surefire-reports</value>
-                        </property>
-                    </properties>
-                    <useSystemClassLoader>false</useSystemClassLoader>
-                    <additionalClasspathElements>
-                        
<element>${project.build.testOutputDirectory}/xwork-jar.jar</element>
-                        
<element>${project.build.testOutputDirectory}/xwork-zip.zip</element>
-                        <element>${project.build.testOutputDirectory}/xwork - 
jar.jar</element>
-                        <element>${project.build.testOutputDirectory}/xwork - 
zip.zip</element>
-                    </additionalClasspathElements>
-                    <includes>
-                        <include>**/*Test.java</include>
-                    </includes>
-                    <excludes>
-                        <exclude>**/XWorkTestCase.java</exclude>
-                        <exclude>**/TestBean.java</exclude>
-                        <exclude>**/TestBean2.java</exclude>
-                        <exclude>**/TestInterceptor.java</exclude>
-                        <exclude>**/AnnotatedTestBean.java</exclude>
-                        <exclude>**/ContainerImplTest.java</exclude>
-                        <exclude>**/URLUtilTest.java</exclude>
-                    </excludes>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>cobertura-maven-plugin</artifactId>
-                <version>2.4</version>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>clean</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <artifactId>maven-jar-plugin</artifactId>
-                <configuration>
-                    <archive>
-                        
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
-                    </archive>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        
<Export-Package>com.opensymphony.xwork2.*</Export-Package>
-                    </instructions>
-                </configuration>
-                <executions>
-                    <execution>
-                        <id>bundle-manifest</id>
-                        <phase>process-classes</phase>
-                        <goals>
-                            <goal>manifest</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-        <defaultGoal>install</defaultGoal>
-    </build>
-
-    <dependencies>
-        <dependency>
-            <groupId>commons-logging</groupId>
-            <artifactId>commons-logging</artifactId>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-lang3</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>commons-io</groupId>
-            <artifactId>commons-io</artifactId>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>ognl</groupId>
-            <artifactId>ognl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>asm</groupId>
-            <artifactId>asm</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>asm</groupId>
-            <artifactId>asm-commons</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-core</artifactId>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-aop</artifactId>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-aspects</artifactId>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-beans</artifactId>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-context</artifactId>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-context-support</artifactId>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-web</artifactId>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-test</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>cglib</groupId>
-            <artifactId>cglib-nodep</artifactId>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <optional>true</optional>
-        </dependency>
-
-        <dependency>
-            <groupId>org.testng</groupId>
-            <artifactId>testng</artifactId>
-            <optional>true</optional>
-            <classifier>jdk15</classifier>
-        </dependency>
-
-        <dependency>
-            <groupId>mockobjects</groupId>
-            <artifactId>mockobjects-core</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.easymock</groupId>
-            <artifactId>easymock</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>log4j</groupId>
-            <artifactId>log4j</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.logging.log4j</groupId>
-            <artifactId>log4j-core</artifactId>
-            <version>${log4j2.version}</version>
-            <scope>test</scope>
-        </dependency>
-
-        <!-- SLF4J support -->
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-simple</artifactId>
-            <optional>true</optional>
-        </dependency>
-
-        <!-- Log4J2 support -->
-        <dependency>
-            <groupId>org.apache.logging.log4j</groupId>
-            <artifactId>log4j-api</artifactId>
-            <optional>true</optional>
-        </dependency>
-    </dependencies>
-
-</project>

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/xwork-core/src/main/java/com/opensymphony/xwork2/Action.java
----------------------------------------------------------------------
diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/Action.java 
b/xwork-core/src/main/java/com/opensymphony/xwork2/Action.java
deleted file mode 100644
index f10a431..0000000
--- a/xwork-core/src/main/java/com/opensymphony/xwork2/Action.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2002-2007,2009 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 com.opensymphony.xwork2;
-
-/**
- * All actions <b>may</b> implement this interface, which exposes the 
<code>execute()</code> method.
- * <p/>
- * However, as of XWork 1.1, this is <b>not</b> required and is only here to 
assist users. You are free to create POJOs
- * that honor the same contract defined by this interface without actually 
implementing the interface.
- */
-public interface Action {
-
-    /**
-     * The action execution was successful. Show result
-     * view to the end user.
-     */
-    public static final String SUCCESS = "success";
-
-    /**
-     * The action execution was successful but do not
-     * show a view. This is useful for actions that are
-     * handling the view in another fashion like redirect.
-     */
-    public static final String NONE = "none";
-
-    /**
-     * The action execution was a failure.
-     * Show an error view, possibly asking the
-     * user to retry entering data.
-     */
-    public static final String ERROR = "error";
-
-    /**
-     * The action execution require more input
-     * in order to succeed.
-     * This result is typically used if a form
-     * handling action has been executed so as
-     * to provide defaults for a form. The
-     * form associated with the handler should be
-     * shown to the end user.
-     * <p/>
-     * This result is also used if the given input
-     * params are invalid, meaning the user
-     * should try providing input again.
-     */
-    public static final String INPUT = "input";
-
-    /**
-     * The action could not execute, since the
-     * user most was not logged in. The login view
-     * should be shown.
-     */
-    public static final String LOGIN = "login";
-
-
-    /**
-     * Where the logic of the action is executed.
-     *
-     * @return a string representing the logical result of the execution.
-     *         See constants in this interface for a list of standard result 
values.
-     * @throws Exception thrown if a system level exception occurs.
-     *                   <b>Note:</b> Application level exceptions should be 
handled by returning
-     *                   an error value, such as <code>Action.ERROR</code>.
-     */
-    public String execute() throws Exception;
-
-}

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/xwork-core/src/main/java/com/opensymphony/xwork2/ActionChainResult.java
----------------------------------------------------------------------
diff --git 
a/xwork-core/src/main/java/com/opensymphony/xwork2/ActionChainResult.java 
b/xwork-core/src/main/java/com/opensymphony/xwork2/ActionChainResult.java
deleted file mode 100644
index 859ccfd..0000000
--- a/xwork-core/src/main/java/com/opensymphony/xwork2/ActionChainResult.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright 2002-2006,2009 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 com.opensymphony.xwork2;
-
-import com.opensymphony.xwork2.inject.Inject;
-import com.opensymphony.xwork2.util.TextParseUtil;
-import com.opensymphony.xwork2.util.ValueStack;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
-import java.util.*;
-
-
-/**
-* <!-- START SNIPPET: description -->
-*
-* This result invokes an entire other action, complete with it's own 
interceptor stack and result.
-*
-* <!-- END SNIPPET: description -->
-*
-* <b>This result type takes the following parameters:</b>
-*
-* <!-- START SNIPPET: params -->
-*
-* <ul>
-*
-* <li><b>actionName (default)</b> - the name of the action that will be 
chained to</li>
-*
-* <li><b>namespace</b> - used to determine which namespace the Action is in 
that we're chaining. If namespace is null,
-* this defaults to the current namespace</li>
-*
-* <li><b>method</b> - used to specify another method on target action to be 
invoked.
-* If null, this defaults to execute method</li>
-*
-* <li><b>skipActions</b> - (optional) the list of comma separated action names 
for the
-* actions that could be chained to</li>
-*
-* </ul>
-*
-* <!-- END SNIPPET: params -->
-*
-* <b>Example:</b>
-*
-* <pre><!-- START SNIPPET: example -->
-* &lt;package name="public" extends="struts-default"&gt;
-*     &lt;!-- Chain creatAccount to login, using the default parameter --&gt;
-*     &lt;action name="createAccount" class="..."&gt;
-*         &lt;result type="chain"&gt;login&lt;/result&gt;
-*     &lt;/action&gt;
-*
-*     &lt;action name="login" class="..."&gt;
-*         &lt;!-- Chain to another namespace --&gt;
-*         &lt;result type="chain"&gt;
-*             &lt;param name="actionName"&gt;dashboard&lt;/param&gt;
-*             &lt;param name="namespace"&gt;/secure&lt;/param&gt;
-*         &lt;/result&gt;
-*     &lt;/action&gt;
-* &lt;/package&gt;
-*
-* &lt;package name="secure" extends="struts-default" namespace="/secure"&gt;
-*     &lt;action name="dashboard" class="..."&gt;
-*         &lt;result&gt;dashboard.jsp&lt;/result&gt;
-*     &lt;/action&gt;
-* &lt;/package&gt;
-* <!-- END SNIPPET: example --></pre>
-*
-* @author <a href='mailto:the_mindstorm[at]evolva[dot]ro'>Alexandru Popescu</a>
-*/
-public class ActionChainResult implements Result {
-
-    private static final Logger LOG = 
LogManager.getLogger(ActionChainResult.class);
-
-    /**
-     * The result parameter name to set the name of the action to chain to.
-     */
-    public static final String DEFAULT_PARAM = "actionName";
-
-    /**
-     * The action context key to save the chain history.
-     */
-    private static final String CHAIN_HISTORY = "CHAIN_HISTORY";
-
-    /**
-     * The result parameter name to set the name of the action to chain to.
-     */
-    public static final String SKIP_ACTIONS_PARAM = "skipActions";
-
-
-    private ActionProxy proxy;
-    private String actionName;
-    
-    private String namespace;
-
-    private String methodName;
-
-    /**
-     * The list of actions to skip.
-     */
-    private String skipActions;
-
-    private ActionProxyFactory actionProxyFactory;
-
-    public ActionChainResult() {
-        super();
-    }
-
-    public ActionChainResult(String namespace, String actionName, String 
methodName) {
-        this.namespace = namespace;
-        this.actionName = actionName;
-        this.methodName = methodName;
-    }
-
-    public ActionChainResult(String namespace, String actionName, String 
methodName, String skipActions) {
-        this.namespace = namespace;
-        this.actionName = actionName;
-        this.methodName = methodName;
-        this.skipActions = skipActions;
-    }
-
-
-    /**
-     * @param actionProxyFactory the actionProxyFactory to set
-     */
-    @Inject
-    public void setActionProxyFactory(ActionProxyFactory actionProxyFactory) {
-        this.actionProxyFactory = actionProxyFactory;
-    }
-
-    /**
-     * Set the action name.
-     *
-     * @param actionName The action name.
-     */
-    public void setActionName(String actionName) {
-        this.actionName = actionName;
-    }
-
-    /**
-     * sets the namespace of the Action that we're chaining to.  if namespace
-     * is null, this defaults to the current namespace.
-     *
-     * @param namespace the name of the namespace we're chaining to
-     */
-    public void setNamespace(String namespace) {
-        this.namespace = namespace;
-    }
-
-    /**
-     * Set the list of actions to skip.
-     * To test if an action should not throe an infinite recursion,
-     * only the action name is used, not the namespace.
-     *
-     * @param actions The list of action name separated by a white space.
-     */
-    public void setSkipActions(String actions) {
-        this.skipActions = actions;
-    }
-
-
-    public void setMethod(String method) {
-        this.methodName = method;
-    }
-
-    public ActionProxy getProxy() {
-        return proxy;
-    }
-
-    /**
-     * Get the XWork chain history.
-     * The stack is a list of <code>namespace/action!method</code> keys.
-     */
-    public static LinkedList<String> getChainHistory() {
-        LinkedList<String> chainHistory = (LinkedList<String>) 
ActionContext.getContext().get(CHAIN_HISTORY);
-        //  Add if not exists
-        if (chainHistory == null) {
-            chainHistory = new LinkedList<>();
-            ActionContext.getContext().put(CHAIN_HISTORY, chainHistory);
-        }
-
-        return chainHistory;
-    }
-
-    /**
-     * @param invocation the DefaultActionInvocation calling the action call 
stack
-     */
-    public void execute(ActionInvocation invocation) throws Exception {
-        // if the finalNamespace wasn't explicitly defined, assume the current 
one
-        if (this.namespace == null) {
-            this.namespace = invocation.getProxy().getNamespace();
-        }
-
-        ValueStack stack = ActionContext.getContext().getValueStack();
-        String finalNamespace = TextParseUtil.translateVariables(namespace, 
stack);
-        String finalActionName = TextParseUtil.translateVariables(actionName, 
stack);
-        String finalMethodName = this.methodName != null
-                ? TextParseUtil.translateVariables(this.methodName, stack)
-                : null;
-
-        if (isInChainHistory(finalNamespace, finalActionName, 
finalMethodName)) {
-            addToHistory(finalNamespace, finalActionName, finalMethodName);
-            throw new XWorkException("Infinite recursion detected: " + 
ActionChainResult.getChainHistory().toString());
-        }
-
-        if (ActionChainResult.getChainHistory().isEmpty() && invocation != 
null && invocation.getProxy() != null) {
-            addToHistory(finalNamespace, 
invocation.getProxy().getActionName(), invocation.getProxy().getMethod());
-        }
-        addToHistory(finalNamespace, finalActionName, finalMethodName);
-
-        HashMap<String, Object> extraContext = new HashMap<>();
-        extraContext.put(ActionContext.VALUE_STACK, 
ActionContext.getContext().getValueStack());
-        extraContext.put(ActionContext.PARAMETERS, 
ActionContext.getContext().getParameters());
-        extraContext.put(CHAIN_HISTORY, ActionChainResult.getChainHistory());
-
-        LOG.debug("Chaining to action {}", finalActionName);
-
-        proxy = actionProxyFactory.createActionProxy(finalNamespace, 
finalActionName, finalMethodName, extraContext);
-        proxy.execute();
-    }
-
-    @Override public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        final ActionChainResult that = (ActionChainResult) o;
-
-        if (actionName != null ? !actionName.equals(that.actionName) : 
that.actionName != null) return false;
-        if (methodName != null ? !methodName.equals(that.methodName) : 
that.methodName != null) return false;
-        if (namespace != null ? !namespace.equals(that.namespace) : 
that.namespace != null) return false;
-
-        return true;
-    }
-
-    @Override public int hashCode() {
-        int result;
-        result = (actionName != null ? actionName.hashCode() : 0);
-        result = 31 * result + (namespace != null ? namespace.hashCode() : 0);
-        result = 31 * result + (methodName != null ? methodName.hashCode() : 
0);
-        return result;
-    }
-
-    private boolean isInChainHistory(String namespace, String actionName, 
String methodName) {
-        LinkedList<? extends String> chainHistory = 
ActionChainResult.getChainHistory();
-
-        if (chainHistory == null) {
-            return false;
-        } else {
-            //  Actions to skip
-            Set<String> skipActionsList = new HashSet<>();
-            if (skipActions != null && skipActions.length() > 0) {
-                ValueStack stack = ActionContext.getContext().getValueStack();
-                String finalSkipActions = 
TextParseUtil.translateVariables(this.skipActions, stack);
-                
skipActionsList.addAll(TextParseUtil.commaDelimitedStringToSet(finalSkipActions));
-            }
-            if (!skipActionsList.contains(actionName)) {
-                //  Get if key is in the chain history
-                return chainHistory.contains(makeKey(namespace, actionName, 
methodName));
-            }
-
-            return false;
-        }
-    }
-
-    private void addToHistory(String namespace, String actionName, String 
methodName) {
-        List<String> chainHistory = ActionChainResult.getChainHistory();
-        chainHistory.add(makeKey(namespace, actionName, methodName));
-    }
-
-    private String makeKey(String namespace, String actionName, String 
methodName) {
-        if (null == methodName) {
-            return namespace + "/" + actionName;
-        }
-
-        return namespace + "/" + actionName + "!" + methodName;
-    }
-}

Reply via email to