http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/java/com/opensymphony/xwork2/validator/validators/VisitorFieldValidator.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/com/opensymphony/xwork2/validator/validators/VisitorFieldValidator.java
 
b/core/src/main/java/com/opensymphony/xwork2/validator/validators/VisitorFieldValidator.java
new file mode 100644
index 0000000..e0be5f0
--- /dev/null
+++ 
b/core/src/main/java/com/opensymphony/xwork2/validator/validators/VisitorFieldValidator.java
@@ -0,0 +1,219 @@
+/*
+ * 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.validator.validators;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.util.ValueStack;
+import com.opensymphony.xwork2.validator.ActionValidatorManager;
+import com.opensymphony.xwork2.validator.DelegatingValidatorContext;
+import com.opensymphony.xwork2.validator.ValidationException;
+import com.opensymphony.xwork2.validator.ValidatorContext;
+
+import java.util.Collection;
+
+
+/**
+ * <!-- START SNIPPET: javadoc -->
+ * The VisitorFieldValidator allows you to forward validation to object
+ * properties of your action using the object's own validation files.  This
+ * allows you to use the ModelDriven development pattern and manage your
+ * validations for your models in one place, where they belong, next to your
+ * model classes.  The VisitorFieldValidator can handle either simple Object
+ * properties, Collections of Objects, or Arrays.
+ * <!-- END SNIPPET: javadoc -->
+ * <p/>
+ *
+ * <!-- START SNIPPET: parameters -->
+ * <ul>
+ * <li>fieldName - field name if plain-validator syntax is used, not needed if 
field-validator syntax is used</li>
+ * <li>context - the context of which validation should take place. 
Optional</li>
+ * <li>appendPrefix - the prefix to be added to field. Optional </li>
+ * </ul>
+ * <!-- END SNIPPET: parameters -->
+ *
+ * <pre>
+ * <!-- START SNIPPET: example -->
+ *    &lt;validators&gt;
+ *        &lt;!-- Plain Validator Syntax --&gt;
+ *        &lt;validator type="visitor"&gt;
+ *            &lt;param name="fieldName"&gt;user&lt;/param&gt;
+ *            &lt;param name="context"&gt;myContext&lt;/param&gt;
+ *            &lt;param name="appendPrefix"&gt;true&lt;/param&gt;
+ *        &lt;/validator&gt;
+ *
+ *        &lt;!-- Field Validator Syntax --&gt;
+ *        &lt;field name="user"&gt;
+ *           &lt;field-validator type="visitor"&gt;
+ *              &lt;param name="context"&gt;myContext&lt;/param&gt;
+ *              &lt;param name="appendPrefix"&gt;true&lt;/param&gt;
+ *           &lt;/field-validator&gt;
+ *        &lt;/field&gt;
+ *    &lt;/validators&gt;
+ * <!-- END SNIPPET: example -->
+ * </pre>
+ *
+ * <!-- START SNIPPET: explanation -->
+ * <p>In the example above, if the acion's getUser() method return User 
object, XWork
+ * will look for User-myContext-validation.xml for the validators. Since 
appednPrefix is true,
+ * every field name will be prefixed with 'user' such that if the actual field 
name for 'name' is
+ * 'user.name' </p>
+ * <!-- END SNIPPET: explanation -->
+ *
+ * @author Jason Carreira
+ * @author Rainer Hermanns
+ * @version $Date$ $Id$
+ */
+public class VisitorFieldValidator extends FieldValidatorSupport {
+
+    private String context;
+    private boolean appendPrefix = true;
+    private ActionValidatorManager actionValidatorManager;
+
+
+    @Inject
+    public void setActionValidatorManager(ActionValidatorManager mgr) {
+        this.actionValidatorManager = mgr;
+    }
+
+    /**
+     * Sets whether the field name of this field validator should be prepended 
to the field name of
+     * the visited field to determine the full field name when an error 
occurs.  The default is
+     * true.
+     */
+    public void setAppendPrefix(boolean appendPrefix) {
+        this.appendPrefix = appendPrefix;
+    }
+
+    /**
+     * Flags whether the field name of this field validator should be 
prepended to the field name of
+     * the visited field to determine the full field name when an error 
occurs.  The default is
+     * true.
+     */
+    public boolean isAppendPrefix() {
+        return appendPrefix;
+    }
+
+    public void setContext(String context) {
+        this.context = context;
+    }
+
+    public String getContext() {
+        return context;
+    }
+
+    public void validate(Object object) throws ValidationException {
+        String fieldName = getFieldName();
+        Object value = this.getFieldValue(fieldName, object);
+        if (value == null) {
+            log.warn("The visited object is null, VisitorValidator will not be 
able to handle validation properly. Please make sure the visited object is not 
null for VisitorValidator to function properly");
+            return;
+        }
+        ValueStack stack = ActionContext.getContext().getValueStack();
+
+        stack.push(object);
+
+        String visitorContext = (context == null) ? 
ActionContext.getContext().getName() : context;
+
+        if (value instanceof Collection) {
+            Collection coll = (Collection) value;
+            Object[] array = coll.toArray();
+
+            validateArrayElements(array, fieldName, visitorContext);
+        } else if (value instanceof Object[]) {
+            Object[] array = (Object[]) value;
+
+            validateArrayElements(array, fieldName, visitorContext);
+        } else {
+            validateObject(fieldName, value, visitorContext);
+        }
+
+        stack.pop();
+    }
+
+    private void validateArrayElements(Object[] array, String fieldName, 
String visitorContext) throws ValidationException {
+        if (array == null) {
+            return;
+        }
+
+        for (int i = 0; i < array.length; i++) {
+            Object o = array[i];
+            if (o != null) {
+                validateObject(fieldName + "[" + i + "]", o, visitorContext);
+            }
+        }
+    }
+
+    private void validateObject(String fieldName, Object o, String 
visitorContext) throws ValidationException {
+        ValueStack stack = ActionContext.getContext().getValueStack();
+        stack.push(o);
+
+        ValidatorContext validatorContext;
+
+        if (appendPrefix) {
+            validatorContext = new 
AppendingValidatorContext(getValidatorContext(), o, fieldName, getMessage(o));
+        } else {
+            ValidatorContext parent = getValidatorContext();
+            validatorContext = new DelegatingValidatorContext(parent, 
DelegatingValidatorContext.makeTextProvider(o, parent), parent);
+        }
+
+        actionValidatorManager.validate(o, visitorContext, validatorContext);
+        stack.pop();
+    }
+
+
+    public static class AppendingValidatorContext extends 
DelegatingValidatorContext {
+        private String field;
+        private String message;
+        private ValidatorContext parent;
+
+        public AppendingValidatorContext(ValidatorContext parent, Object 
object, String field, String message) {
+            super(parent, makeTextProvider(object, parent), parent);
+
+            this.field = field;
+            this.message = message;
+            this.parent = parent;
+        }
+
+        /**
+         * Translates a simple field name into a full field name in Ognl syntax
+         *
+         * @param fieldName field name in OGNL syntax
+         * @return full field name in OGNL syntax
+         */
+        @Override
+        public String getFullFieldName(String fieldName) {
+            if (parent instanceof 
VisitorFieldValidator.AppendingValidatorContext) {
+                return parent.getFullFieldName(field + "." + fieldName);
+            }
+            return field + "." + fieldName;
+        }
+
+        public String getFieldNameWithField(String fieldName) {
+            return field + "." + fieldName;
+        }
+
+        @Override
+        public void addActionError(String anErrorMessage) {
+            super.addFieldError(getFieldNameWithField(field), message + 
anErrorMessage);
+        }
+
+        @Override
+        public void addFieldError(String fieldName, String errorMessage) {
+            super.addFieldError(getFieldNameWithField(fieldName), message + 
errorMessage);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/java/com/opensymphony/xwork2/validator/validators/package.html
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/com/opensymphony/xwork2/validator/validators/package.html 
b/core/src/main/java/com/opensymphony/xwork2/validator/validators/package.html
new file mode 100644
index 0000000..8b34399
--- /dev/null
+++ 
b/core/src/main/java/com/opensymphony/xwork2/validator/validators/package.html
@@ -0,0 +1 @@
+<body>XWork default validator classes.</body>

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/resources/com/opensymphony/xwork2/validator/validators/default.xml
----------------------------------------------------------------------
diff --git 
a/core/src/main/resources/com/opensymphony/xwork2/validator/validators/default.xml
 
b/core/src/main/resources/com/opensymphony/xwork2/validator/validators/default.xml
new file mode 100644
index 0000000..fa8e742
--- /dev/null
+++ 
b/core/src/main/resources/com/opensymphony/xwork2/validator/validators/default.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE validators PUBLIC
+        "-//Apache Struts//XWork Validator Definition 1.0//EN"
+        "http://struts.apache.org/dtds/xwork-validator-definition-1.0.dtd";>
+
+<!-- START SNIPPET: validators-default -->
+<validators>
+    <validator name="required" 
class="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"/>
+    <validator name="requiredstring" 
class="com.opensymphony.xwork2.validator.validators.RequiredStringValidator"/>
+    <validator name="int" 
class="com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator"/>
+    <validator name="long" 
class="com.opensymphony.xwork2.validator.validators.LongRangeFieldValidator"/>
+    <validator name="short" 
class="com.opensymphony.xwork2.validator.validators.ShortRangeFieldValidator"/>
+    <validator name="double" 
class="com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator"/>
+    <validator name="date" 
class="com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator"/>
+    <validator name="expression" 
class="com.opensymphony.xwork2.validator.validators.ExpressionValidator"/>
+    <validator name="fieldexpression" 
class="com.opensymphony.xwork2.validator.validators.FieldExpressionValidator"/>
+    <validator name="email" 
class="com.opensymphony.xwork2.validator.validators.EmailValidator"/>
+    <validator name="url" 
class="com.opensymphony.xwork2.validator.validators.URLValidator"/>
+    <validator name="visitor" 
class="com.opensymphony.xwork2.validator.validators.VisitorFieldValidator"/>
+    <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>
+<!--  END SNIPPET: validators-default -->

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/resources/com/opensymphony/xwork2/xwork-messages.properties
----------------------------------------------------------------------
diff --git 
a/core/src/main/resources/com/opensymphony/xwork2/xwork-messages.properties 
b/core/src/main/resources/com/opensymphony/xwork2/xwork-messages.properties
new file mode 100644
index 0000000..6068879
--- /dev/null
+++ b/core/src/main/resources/com/opensymphony/xwork2/xwork-messages.properties
@@ -0,0 +1,10 @@
+#
+# Copyright (c) 2002-2006 by OpenSymphony
+# All rights reserved.
+#
+
+xwork.error.action.execution=Error during Action invocation
+xwork.exception.missing-action=There is no Action mapped for action name {0}.
+xwork.exception.missing-package-action=There is no Action mapped for namespace 
{0} and action name {1}.
+xwork.default.invalid.fieldvalue=Invalid field value for field "{0}".
+

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/resources/xwork-1.0.dtd
----------------------------------------------------------------------
diff --git a/core/src/main/resources/xwork-1.0.dtd 
b/core/src/main/resources/xwork-1.0.dtd
new file mode 100644
index 0000000..0ab3cd5
--- /dev/null
+++ b/core/src/main/resources/xwork-1.0.dtd
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+   XWork Configuraion DTD.
+   Use the following DOCTYPE.
+   
+   <!DOCTYPE xwork PUBLIC 
+               "-//Apache Struts//XWork 1.0//EN"
+               "http://struts.apache.org/dtds/xwork-1.0.dtd";>
+-->
+
+<!ELEMENT xwork (package|include)*>
+
+<!ELEMENT package (result-types?, interceptors?, default-interceptor-ref?, 
global-results?, action*)>
+<!ATTLIST package
+    name CDATA #REQUIRED
+    extends CDATA #IMPLIED
+    namespace CDATA #IMPLIED
+    abstract CDATA #IMPLIED
+    externalReferenceResolver NMTOKEN #IMPLIED
+>
+
+<!ELEMENT result-types (result-type+)>
+
+<!ELEMENT result-type (param*)>
+<!ATTLIST result-type
+    name CDATA #REQUIRED
+    class CDATA #REQUIRED
+    default (true|false) "false"
+>
+
+<!ELEMENT interceptors (interceptor|interceptor-stack)+>
+
+<!ELEMENT interceptor (param*)>
+<!ATTLIST interceptor
+    name CDATA #REQUIRED
+    class CDATA #REQUIRED
+>
+
+<!ELEMENT interceptor-stack (interceptor-ref+)>
+<!ATTLIST interceptor-stack
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT interceptor-ref (param*)>
+<!ATTLIST interceptor-ref
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT default-interceptor-ref (param*)>
+<!ATTLIST default-interceptor-ref
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT external-ref (#PCDATA)>
+<!ATTLIST external-ref
+    name NMTOKEN #REQUIRED
+    required (true|false) "true"
+>
+
+<!ELEMENT global-results (result+)>
+
+<!ELEMENT action (param|result|interceptor-ref|external-ref)*>
+<!ATTLIST action
+name CDATA #REQUIRED
+    class CDATA #REQUIRED
+    method CDATA #IMPLIED
+    converter CDATA #IMPLIED
+>
+
+<!ELEMENT param (#PCDATA)>
+<!ATTLIST param
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT result (#PCDATA|param)*>
+<!ATTLIST result
+    name CDATA #REQUIRED
+    type CDATA #IMPLIED
+>
+
+<!ELEMENT include (#PCDATA)>
+<!ATTLIST include
+    file CDATA #REQUIRED
+>
+
+

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/resources/xwork-1.1.1.dtd
----------------------------------------------------------------------
diff --git a/core/src/main/resources/xwork-1.1.1.dtd 
b/core/src/main/resources/xwork-1.1.1.dtd
new file mode 100644
index 0000000..973719e
--- /dev/null
+++ b/core/src/main/resources/xwork-1.1.1.dtd
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- START SNIPPET: xworkDtd -->
+
+<!--
+   XWork configuration DTD.
+   Use the following DOCTYPE
+   
+   <!DOCTYPE xwork PUBLIC 
+               "-//Apache Struts//XWork 1.0//EN"
+               "http://struts.apache.org/dtds/xwork-1.1.1.dtd";>
+-->
+
+<!ELEMENT xwork (package|include)*>
+
+<!ELEMENT package (result-types?, interceptors?, default-interceptor-ref?, 
default-action-ref?, global-results?, global-exception-mappings?, action*)>
+<!ATTLIST package
+    name CDATA #REQUIRED
+    extends CDATA #IMPLIED
+    namespace CDATA #IMPLIED
+    abstract CDATA #IMPLIED
+    externalReferenceResolver NMTOKEN #IMPLIED
+>
+
+<!ELEMENT result-types (result-type+)>
+
+<!ELEMENT result-type (param*)>
+<!ATTLIST result-type
+    name CDATA #REQUIRED
+    class CDATA #REQUIRED
+    default (true|false) "false"
+>
+
+<!ELEMENT interceptors (interceptor|interceptor-stack)+>
+
+<!ELEMENT interceptor (param*)>
+<!ATTLIST interceptor
+    name CDATA #REQUIRED
+    class CDATA #REQUIRED
+>
+
+<!ELEMENT interceptor-stack (interceptor-ref+)>
+<!ATTLIST interceptor-stack
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT interceptor-ref (param*)>
+<!ATTLIST interceptor-ref
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT default-interceptor-ref (param*)>
+<!ATTLIST default-interceptor-ref
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT default-action-ref (param*)>
+<!ATTLIST default-action-ref
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT external-ref (#PCDATA)>
+<!ATTLIST external-ref
+    name NMTOKEN #REQUIRED
+    required (true|false) "true"
+>
+
+<!ELEMENT global-results (result+)>
+
+<!ELEMENT global-exception-mappings (exception-mapping+)>
+
+<!ELEMENT action 
(param|result|interceptor-ref|exception-mapping|external-ref)*>
+<!ATTLIST action
+    name CDATA #REQUIRED
+    class CDATA #IMPLIED
+    method CDATA #IMPLIED
+    converter CDATA #IMPLIED
+>
+
+<!ELEMENT param (#PCDATA)>
+<!ATTLIST param
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT result (#PCDATA|param)*>
+<!ATTLIST result
+    name CDATA #IMPLIED
+    type CDATA #IMPLIED
+>
+
+<!ELEMENT exception-mapping (#PCDATA|param)*>
+<!ATTLIST exception-mapping
+    name CDATA #IMPLIED
+    exception CDATA #REQUIRED
+    result CDATA #REQUIRED
+>
+
+<!ELEMENT include (#PCDATA)>
+<!ATTLIST include
+    file CDATA #REQUIRED
+>
+
+<!-- END SNIPPET: xworkDtd -->
+

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/resources/xwork-1.1.2.dtd
----------------------------------------------------------------------
diff --git a/core/src/main/resources/xwork-1.1.2.dtd 
b/core/src/main/resources/xwork-1.1.2.dtd
new file mode 100644
index 0000000..019f697
--- /dev/null
+++ b/core/src/main/resources/xwork-1.1.2.dtd
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- START SNIPPET: xworkDtd -->
+
+<!--
+   XWork configuration DTD.
+   Use the following DOCTYPE
+
+   <!DOCTYPE xwork PUBLIC
+               "-//Apache Struts//XWork 1.0//EN"
+               "http://struts.apache.org/dtds/xwork-1.1.2.dtd";>
+-->
+
+<!ELEMENT xwork (parameters?, (package|include)*)>
+
+<!ELEMENT parameters (parameter*)>
+
+<!ELEMENT parameter (#PCDATA)>
+<!ATTLIST parameter
+    name CDATA #REQUIRED
+    value CDATA #REQUIRED
+>
+
+<!ELEMENT package (result-types?, interceptors?, default-interceptor-ref?, 
default-action-ref?, global-results?, global-exception-mappings?, action*)>
+<!ATTLIST package
+    name CDATA #REQUIRED
+    extends CDATA #IMPLIED
+    namespace CDATA #IMPLIED
+    abstract CDATA #IMPLIED
+    externalReferenceResolver NMTOKEN #IMPLIED
+>
+
+<!ELEMENT result-types (result-type+)>
+
+<!ELEMENT result-type (param*)>
+<!ATTLIST result-type
+    name CDATA #REQUIRED
+    class CDATA #REQUIRED
+    default (true|false) "false"
+>
+
+<!ELEMENT interceptors (interceptor|interceptor-stack)+>
+
+<!ELEMENT interceptor (param*)>
+<!ATTLIST interceptor
+    name CDATA #REQUIRED
+    class CDATA #REQUIRED
+>
+
+<!ELEMENT interceptor-stack (interceptor-ref+)>
+<!ATTLIST interceptor-stack
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT interceptor-ref (param*)>
+<!ATTLIST interceptor-ref
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT default-interceptor-ref (param*)>
+<!ATTLIST default-interceptor-ref
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT default-action-ref (param*)>
+<!ATTLIST default-action-ref
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT external-ref (#PCDATA)>
+<!ATTLIST external-ref
+    name NMTOKEN #REQUIRED
+    required (true|false) "true"
+>
+
+<!ELEMENT global-results (result+)>
+
+<!ELEMENT global-exception-mappings (exception-mapping+)>
+
+<!ELEMENT action 
(param|result|interceptor-ref|exception-mapping|external-ref)*>
+<!ATTLIST action
+    name CDATA #REQUIRED
+    class CDATA #IMPLIED
+    method CDATA #IMPLIED
+    converter CDATA #IMPLIED
+>
+
+<!ELEMENT param (#PCDATA)>
+<!ATTLIST param
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT result (#PCDATA|param)*>
+<!ATTLIST result
+    name CDATA #IMPLIED
+    type CDATA #IMPLIED
+>
+
+<!ELEMENT exception-mapping (#PCDATA|param)*>
+<!ATTLIST exception-mapping
+    name CDATA #IMPLIED
+    exception CDATA #REQUIRED
+    result CDATA #REQUIRED
+>
+
+<!ELEMENT include (#PCDATA)>
+<!ATTLIST include
+    file CDATA #REQUIRED
+>
+
+<!-- END SNIPPET: xworkDtd -->
+

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/resources/xwork-1.1.dtd
----------------------------------------------------------------------
diff --git a/core/src/main/resources/xwork-1.1.dtd 
b/core/src/main/resources/xwork-1.1.dtd
new file mode 100644
index 0000000..039328d
--- /dev/null
+++ b/core/src/main/resources/xwork-1.1.dtd
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+   XWork configuration DTD.
+   Use the following DOCTYPE
+   
+   <!DOCTYPE xwork PUBLIC 
+               "-//Apache Struts//XWork 1.0//EN"
+               "http://struts.apache.org/dtds/xwork-1.1.dtd";>
+-->
+
+<!ELEMENT xwork (package|include)*>
+
+<!ELEMENT package (result-types?, interceptors?, default-interceptor-ref?, 
global-results?, global-exception-mappings?, action*)>
+<!ATTLIST package
+    name CDATA #REQUIRED
+    extends CDATA #IMPLIED
+    namespace CDATA #IMPLIED
+    abstract CDATA #IMPLIED
+    externalReferenceResolver NMTOKEN #IMPLIED
+>
+
+<!ELEMENT result-types (result-type+)>
+
+<!ELEMENT result-type (param*)>
+<!ATTLIST result-type
+    name CDATA #REQUIRED
+    class CDATA #REQUIRED
+    default (true|false) "false"
+>
+
+<!ELEMENT interceptors (interceptor|interceptor-stack)+>
+
+<!ELEMENT interceptor (param*)>
+<!ATTLIST interceptor
+    name CDATA #REQUIRED
+    class CDATA #REQUIRED
+>
+
+<!ELEMENT interceptor-stack (interceptor-ref+)>
+<!ATTLIST interceptor-stack
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT interceptor-ref (param*)>
+<!ATTLIST interceptor-ref
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT default-interceptor-ref (param*)>
+<!ATTLIST default-interceptor-ref
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT external-ref (#PCDATA)>
+<!ATTLIST external-ref
+    name NMTOKEN #REQUIRED
+    required (true|false) "true"
+>
+
+<!ELEMENT global-results (result+)>
+
+<!ELEMENT global-exception-mappings (exception-mapping+)>
+
+<!ELEMENT action 
(param|result|interceptor-ref|exception-mapping|external-ref)*>
+<!ATTLIST action
+    name CDATA #REQUIRED
+    class CDATA #IMPLIED
+    method CDATA #IMPLIED
+    converter CDATA #IMPLIED
+>
+
+<!ELEMENT param (#PCDATA)>
+<!ATTLIST param
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT result (#PCDATA|param)*>
+<!ATTLIST result
+    name CDATA #IMPLIED
+    type CDATA #IMPLIED
+>
+
+<!ELEMENT exception-mapping (#PCDATA|param)*>
+<!ATTLIST exception-mapping
+    name CDATA #IMPLIED
+    exception CDATA #REQUIRED
+    result CDATA #REQUIRED
+>
+
+<!ELEMENT include (#PCDATA)>
+<!ATTLIST include
+    file CDATA #REQUIRED
+>
+
+

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/resources/xwork-2.0.dtd
----------------------------------------------------------------------
diff --git a/core/src/main/resources/xwork-2.0.dtd 
b/core/src/main/resources/xwork-2.0.dtd
new file mode 100644
index 0000000..e095e26
--- /dev/null
+++ b/core/src/main/resources/xwork-2.0.dtd
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- START SNIPPET: xworkDtd -->
+
+<!--
+   XWork configuration DTD.
+   Use the following DOCTYPE
+   
+   <!DOCTYPE xwork PUBLIC 
+       "-//Apache Struts//XWork 2.0//EN"
+       "http://struts.apache.org/dtds/xwork-2.0.dtd";>
+-->
+
+<!ELEMENT xwork (package|include|bean|constant)*>
+
+<!ELEMENT package (result-types?, interceptors?, default-interceptor-ref?, 
default-action-ref?, default-class-ref?, global-results?, 
global-exception-mappings?, action*)>
+<!ATTLIST package
+    name CDATA #REQUIRED
+    extends CDATA #IMPLIED
+    namespace CDATA #IMPLIED
+    abstract CDATA #IMPLIED
+>
+
+<!ELEMENT result-types (result-type+)>
+
+<!ELEMENT result-type (param*)>
+<!ATTLIST result-type
+    name CDATA #REQUIRED
+    class CDATA #REQUIRED
+    default (true|false) "false"
+>
+
+<!ELEMENT interceptors (interceptor|interceptor-stack)+>
+
+<!ELEMENT interceptor (param*)>
+<!ATTLIST interceptor
+    name CDATA #REQUIRED
+    class CDATA #REQUIRED
+>
+
+<!ELEMENT interceptor-stack (interceptor-ref*)>
+<!ATTLIST interceptor-stack
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT interceptor-ref (param*)>
+<!ATTLIST interceptor-ref
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT default-interceptor-ref (#PCDATA)>
+<!ATTLIST default-interceptor-ref
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT default-action-ref (#PCDATA)>
+<!ATTLIST default-action-ref
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT default-class-ref (#PCDATA)>
+<!ATTLIST default-class-ref
+   class CDATA #REQUIRED
+>
+
+<!ELEMENT global-results (result+)>
+
+<!ELEMENT global-exception-mappings (exception-mapping+)>
+
+<!ELEMENT action (param|result|interceptor-ref|exception-mapping)*>
+<!ATTLIST action
+    name CDATA #REQUIRED
+    class CDATA #IMPLIED
+    method CDATA #IMPLIED
+    converter CDATA #IMPLIED
+>
+
+<!ELEMENT param (#PCDATA)>
+<!ATTLIST param
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT result (#PCDATA|param)*>
+<!ATTLIST result
+    name CDATA #IMPLIED
+    type CDATA #IMPLIED
+>
+
+<!ELEMENT exception-mapping (#PCDATA|param)*>
+<!ATTLIST exception-mapping
+    name CDATA #IMPLIED
+    exception CDATA #REQUIRED
+    result CDATA #REQUIRED
+>
+
+<!ELEMENT include (#PCDATA)>
+<!ATTLIST include
+    file CDATA #REQUIRED
+>
+
+<!ELEMENT bean (#PCDATA)>
+<!ATTLIST bean
+    type CDATA #IMPLIED
+    name CDATA #IMPLIED
+    class CDATA #REQUIRED
+    scope CDATA #IMPLIED
+    static CDATA #IMPLIED
+    optional CDATA #IMPLIED
+>
+
+<!ELEMENT constant (#PCDATA)>
+<!ATTLIST constant
+    name CDATA #REQUIRED
+    value CDATA #REQUIRED    
+>
+
+<!-- END SNIPPET: xworkDtd -->
+

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/resources/xwork-2.1.3.dtd
----------------------------------------------------------------------
diff --git a/core/src/main/resources/xwork-2.1.3.dtd 
b/core/src/main/resources/xwork-2.1.3.dtd
new file mode 100644
index 0000000..6893f97
--- /dev/null
+++ b/core/src/main/resources/xwork-2.1.3.dtd
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- START SNIPPET: xworkDtd -->
+
+<!--
+   XWork configuration DTD.
+   Use the following DOCTYPE
+
+   <!DOCTYPE xwork PUBLIC
+       "-//Apache Struts//XWork 2.1.3//EN"
+       "http://struts.apache.org/dtds/xwork-2.1.3.dtd";>
+-->
+
+<!ELEMENT xwork ((package|include|bean|constant)*, unknown-handler-stack?)>
+<!ATTLIST xwork
+    order CDATA #IMPLIED
+>
+
+<!ELEMENT package (result-types?, interceptors?, default-interceptor-ref?, 
default-action-ref?, default-class-ref?, global-results?, 
global-exception-mappings?, action*)>
+<!ATTLIST package
+    name CDATA #REQUIRED
+    extends CDATA #IMPLIED
+    namespace CDATA #IMPLIED
+    abstract CDATA #IMPLIED
+>
+
+<!ELEMENT result-types (result-type+)>
+
+<!ELEMENT result-type (param*)>
+<!ATTLIST result-type
+    name CDATA #REQUIRED
+    class CDATA #REQUIRED
+    default (true|false) "false"
+>
+
+<!ELEMENT interceptors (interceptor|interceptor-stack)+>
+
+<!ELEMENT interceptor (param*)>
+<!ATTLIST interceptor
+    name CDATA #REQUIRED
+    class CDATA #REQUIRED
+>
+
+<!ELEMENT interceptor-stack (interceptor-ref*)>
+<!ATTLIST interceptor-stack
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT interceptor-ref (param*)>
+<!ATTLIST interceptor-ref
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT default-interceptor-ref (#PCDATA)>
+<!ATTLIST default-interceptor-ref
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT default-action-ref (#PCDATA)>
+<!ATTLIST default-action-ref
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT default-class-ref (#PCDATA)>
+<!ATTLIST default-class-ref
+   class CDATA #REQUIRED
+>
+
+<!ELEMENT global-results (result+)>
+
+<!ELEMENT global-exception-mappings (exception-mapping+)>
+
+<!ELEMENT action (param|result|interceptor-ref|exception-mapping)*>
+<!ATTLIST action
+    name CDATA #REQUIRED
+    class CDATA #IMPLIED
+    method CDATA #IMPLIED
+    converter CDATA #IMPLIED
+>
+
+<!ELEMENT param (#PCDATA)>
+<!ATTLIST param
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT result (#PCDATA|param)*>
+<!ATTLIST result
+    name CDATA #IMPLIED
+    type CDATA #IMPLIED
+>
+
+<!ELEMENT exception-mapping (#PCDATA|param)*>
+<!ATTLIST exception-mapping
+    name CDATA #IMPLIED
+    exception CDATA #REQUIRED
+    result CDATA #REQUIRED
+>
+
+<!ELEMENT include (#PCDATA)>
+<!ATTLIST include
+    file CDATA #REQUIRED
+>
+
+<!ELEMENT bean (#PCDATA)>
+<!ATTLIST bean
+    type CDATA #IMPLIED
+    name CDATA #IMPLIED
+    class CDATA #REQUIRED
+    scope CDATA #IMPLIED
+    static CDATA #IMPLIED
+    optional CDATA #IMPLIED
+>
+
+<!ELEMENT constant (#PCDATA)>
+<!ATTLIST constant
+    name CDATA #REQUIRED
+    value CDATA #REQUIRED
+>
+
+<!ELEMENT unknown-handler-stack (unknown-handler-ref*)>
+<!ELEMENT unknown-handler-ref (#PCDATA)>
+<!ATTLIST unknown-handler-ref
+    name CDATA #REQUIRED
+>
+
+<!-- END SNIPPET: xworkDtd -->
+

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/resources/xwork-2.1.dtd
----------------------------------------------------------------------
diff --git a/core/src/main/resources/xwork-2.1.dtd 
b/core/src/main/resources/xwork-2.1.dtd
new file mode 100644
index 0000000..a003753
--- /dev/null
+++ b/core/src/main/resources/xwork-2.1.dtd
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- START SNIPPET: xworkDtd -->
+
+<!--
+   XWork configuration DTD.
+   Use the following DOCTYPE
+
+   <!DOCTYPE xwork PUBLIC
+       "-//Apache Struts//XWork 2.1//EN"
+       "http://struts.apache.org/dtds/xwork-2.1.dtd";>
+-->
+
+<!ELEMENT xwork ((package|include|bean|constant)*, unknown-handler-stack?)>
+
+<!ELEMENT package (result-types?, interceptors?, default-interceptor-ref?, 
default-action-ref?, default-class-ref?, global-results?, 
global-exception-mappings?, action*)>
+<!ATTLIST package
+    name CDATA #REQUIRED
+    extends CDATA #IMPLIED
+    namespace CDATA #IMPLIED
+    abstract CDATA #IMPLIED
+>
+
+<!ELEMENT result-types (result-type+)>
+
+<!ELEMENT result-type (param*)>
+<!ATTLIST result-type
+    name CDATA #REQUIRED
+    class CDATA #REQUIRED
+    default (true|false) "false"
+>
+
+<!ELEMENT interceptors (interceptor|interceptor-stack)+>
+
+<!ELEMENT interceptor (param*)>
+<!ATTLIST interceptor
+    name CDATA #REQUIRED
+    class CDATA #REQUIRED
+>
+
+<!ELEMENT interceptor-stack (interceptor-ref*)>
+<!ATTLIST interceptor-stack
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT interceptor-ref (param*)>
+<!ATTLIST interceptor-ref
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT default-interceptor-ref (#PCDATA)>
+<!ATTLIST default-interceptor-ref
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT default-action-ref (#PCDATA)>
+<!ATTLIST default-action-ref
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT default-class-ref (#PCDATA)>
+<!ATTLIST default-class-ref
+   class CDATA #REQUIRED
+>
+
+<!ELEMENT global-results (result+)>
+
+<!ELEMENT global-exception-mappings (exception-mapping+)>
+
+<!ELEMENT action (param|result|interceptor-ref|exception-mapping)*>
+<!ATTLIST action
+    name CDATA #REQUIRED
+    class CDATA #IMPLIED
+    method CDATA #IMPLIED
+    converter CDATA #IMPLIED
+>
+
+<!ELEMENT param (#PCDATA)>
+<!ATTLIST param
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT result (#PCDATA|param)*>
+<!ATTLIST result
+    name CDATA #IMPLIED
+    type CDATA #IMPLIED
+>
+
+<!ELEMENT exception-mapping (#PCDATA|param)*>
+<!ATTLIST exception-mapping
+    name CDATA #IMPLIED
+    exception CDATA #REQUIRED
+    result CDATA #REQUIRED
+>
+
+<!ELEMENT include (#PCDATA)>
+<!ATTLIST include
+    file CDATA #REQUIRED
+>
+
+<!ELEMENT bean (#PCDATA)>
+<!ATTLIST bean
+    type CDATA #IMPLIED
+    name CDATA #IMPLIED
+    class CDATA #REQUIRED
+    scope CDATA #IMPLIED
+    static CDATA #IMPLIED
+    optional CDATA #IMPLIED
+>
+
+<!ELEMENT constant (#PCDATA)>
+<!ATTLIST constant
+    name CDATA #REQUIRED
+    value CDATA #REQUIRED
+>
+
+<!ELEMENT unknown-handler-stack (unknown-handler-ref*)>
+<!ELEMENT unknown-handler-ref (#PCDATA)>
+<!ATTLIST unknown-handler-ref
+    name CDATA #REQUIRED
+>
+
+<!-- END SNIPPET: xworkDtd -->
+

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/resources/xwork-2.3.dtd
----------------------------------------------------------------------
diff --git a/core/src/main/resources/xwork-2.3.dtd 
b/core/src/main/resources/xwork-2.3.dtd
new file mode 100644
index 0000000..b983ff9
--- /dev/null
+++ b/core/src/main/resources/xwork-2.3.dtd
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- START SNIPPET: xworkDtd -->
+
+<!--
+   XWork configuration DTD.
+   Use the following DOCTYPE
+
+   <!DOCTYPE xwork PUBLIC
+       "-//Apache Struts//XWork 2.3//EN"
+       "http://struts.apache.org/dtds/xwork-2.3.dtd";>
+-->
+
+<!ELEMENT xwork ((package|include|bean|constant)*, unknown-handler-stack?)>
+<!ATTLIST xwork
+    order CDATA #IMPLIED
+>
+
+<!ELEMENT package (result-types?, interceptors?, default-interceptor-ref?, 
default-action-ref?, default-class-ref?, global-results?, 
global-exception-mappings?, action*)>
+<!ATTLIST package
+    name CDATA #REQUIRED
+    extends CDATA #IMPLIED
+    namespace CDATA #IMPLIED
+    abstract CDATA #IMPLIED
+    strict-method-invocation CDATA #IMPLIED
+>
+
+<!ELEMENT result-types (result-type+)>
+
+<!ELEMENT result-type (param*)>
+<!ATTLIST result-type
+    name CDATA #REQUIRED
+    class CDATA #REQUIRED
+    default (true|false) "false"
+>
+
+<!ELEMENT interceptors (interceptor|interceptor-stack)+>
+
+<!ELEMENT interceptor (param*)>
+<!ATTLIST interceptor
+    name CDATA #REQUIRED
+    class CDATA #REQUIRED
+>
+
+<!ELEMENT interceptor-stack (interceptor-ref*)>
+<!ATTLIST interceptor-stack
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT interceptor-ref (param*)>
+<!ATTLIST interceptor-ref
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT default-interceptor-ref (#PCDATA)>
+<!ATTLIST default-interceptor-ref
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT default-action-ref (#PCDATA)>
+<!ATTLIST default-action-ref
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT default-class-ref (#PCDATA)>
+<!ATTLIST default-class-ref
+   class CDATA #REQUIRED
+>
+
+<!ELEMENT global-results (result+)>
+
+<!ELEMENT global-exception-mappings (exception-mapping+)>
+
+<!ELEMENT action 
((param|result|interceptor-ref|exception-mapping)*,allowed-methods?)>
+<!ATTLIST action
+    name CDATA #REQUIRED
+    class CDATA #IMPLIED
+    method CDATA #IMPLIED
+    converter CDATA #IMPLIED
+>
+
+<!ELEMENT param (#PCDATA)>
+<!ATTLIST param
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT result (#PCDATA|param)*>
+<!ATTLIST result
+    name CDATA #IMPLIED
+    type CDATA #IMPLIED
+>
+
+<!ELEMENT exception-mapping (#PCDATA|param)*>
+<!ATTLIST exception-mapping
+    name CDATA #IMPLIED
+    exception CDATA #REQUIRED
+    result CDATA #REQUIRED
+>
+
+<!ELEMENT allowed-methods (#PCDATA)>
+
+<!ELEMENT include (#PCDATA)>
+<!ATTLIST include
+    file CDATA #REQUIRED
+>
+
+<!ELEMENT bean (#PCDATA)>
+<!ATTLIST bean
+    type CDATA #IMPLIED
+    name CDATA #IMPLIED
+    class CDATA #REQUIRED
+    scope CDATA #IMPLIED
+    static CDATA #IMPLIED
+    optional CDATA #IMPLIED
+>
+
+<!ELEMENT constant (#PCDATA)>
+<!ATTLIST constant
+    name CDATA #REQUIRED
+    value CDATA #REQUIRED
+>
+
+<!ELEMENT unknown-handler-stack (unknown-handler-ref*)>
+<!ELEMENT unknown-handler-ref (#PCDATA)>
+<!ATTLIST unknown-handler-ref
+    name CDATA #REQUIRED
+>
+
+<!-- END SNIPPET: xworkDtd -->
+

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/resources/xwork-default.xml
----------------------------------------------------------------------
diff --git a/core/src/main/resources/xwork-default.xml 
b/core/src/main/resources/xwork-default.xml
new file mode 100644
index 0000000..dba9d68
--- /dev/null
+++ b/core/src/main/resources/xwork-default.xml
@@ -0,0 +1,67 @@
+<!DOCTYPE xwork PUBLIC
+        "-//Apache Struts//XWork 2.0//EN"
+        "http://struts.apache.org/dtds/xwork-2.0.dtd";>
+
+<xwork>
+    <package name="xwork-default" abstract="true">
+
+        <!-- START SNIPPET: xwork2-default-result-types -->
+        <result-types>
+            <result-type name="chain" 
class="com.opensymphony.xwork2.ActionChainResult"/>
+        </result-types>
+
+        <!-- END SNIPPET: xwork2-default-result-types -->
+
+        <interceptors>
+            <!-- START SNIPPET: xwork2-default-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="staticParams" 
class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
+            <interceptor name="params" 
class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
+            <interceptor name="filterParams" 
class="com.opensymphony.xwork2.interceptor.ParameterFilterInterceptor"/>
+            <interceptor name="removeParams" 
class="com.opensymphony.xwork2.interceptor.ParameterRemoverInterceptor"/>
+            <interceptor name="modelDriven" 
class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
+            <interceptor name="scopedModelDriven"
+                         
class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/>
+            <interceptor name="validation" 
class="com.opensymphony.xwork2.validator.ValidationInterceptor"/>
+            <interceptor name="workflow" 
class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/>
+            <interceptor name="prepare" 
class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>
+            <interceptor name="conversionError" 
class="com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor"/>
+            <interceptor name="alias" 
class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
+            <interceptor name="exception" 
class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>
+            <interceptor name="i18n" 
class="com.opensymphony.xwork2.interceptor.I18nInterceptor"/>
+
+            <!-- END SNIPPET: xwork2-default-interceptors -->
+
+            <!--interceptor name="static-params" 
class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
+            <interceptor name="filter-params" 
class="com.opensymphony.xwork2.interceptor.ParameterFilterInterceptor"/>
+            <interceptor name="remove-params" 
class="com.opensymphony.xwork2.interceptor.ParameterRemoverInterceptor"/>
+            <interceptor name="model-driven" 
class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
+            <interceptor name="scoped-model-driven"
+                         
class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/-->
+
+            <!-- START SNIPPET: xwork2-default-interceptor-stack -->
+
+            <interceptor-stack name="emptyStack"/>
+
+            <interceptor-stack name="defaultStack">
+                <interceptor-ref name="staticParams"/>
+                <interceptor-ref name="params"/>
+                <interceptor-ref name="conversionError"/>
+            </interceptor-stack>
+            <interceptor-stack name="validationWorkflowStack">
+                <interceptor-ref name="defaultStack"/>
+                <interceptor-ref name="validation"/>
+                <interceptor-ref name="workflow"/>
+            </interceptor-stack>
+
+            <!-- END SNIPPET: xwork2-default-interceptor-stack -->
+
+        </interceptors>
+
+        <default-class-ref class="com.opensymphony.xwork2.ActionSupport"/>
+
+    </package>
+</xwork>

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/resources/xwork-validator-1.0.2.dtd
----------------------------------------------------------------------
diff --git a/core/src/main/resources/xwork-validator-1.0.2.dtd 
b/core/src/main/resources/xwork-validator-1.0.2.dtd
new file mode 100644
index 0000000..a697a13
--- /dev/null
+++ b/core/src/main/resources/xwork-validator-1.0.2.dtd
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  XWork Validators DTD.
+  Used the following DOCTYPE.
+  
+  <!DOCTYPE validators PUBLIC 
+               "-//Apache Struts//XWork Validator 1.0.2//EN"
+               "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd";>
+-->
+
+
+<!ELEMENT validators (field|validator)+>
+
+<!ELEMENT field (field-validator+)>
+<!ATTLIST field
+       name CDATA #REQUIRED
+>
+
+<!ELEMENT field-validator (param*, message)>
+<!ATTLIST field-validator
+       type CDATA #REQUIRED
+    short-circuit (true|false) "false"
+>
+
+<!ELEMENT validator (param*, message)>
+<!ATTLIST validator
+       type CDATA #REQUIRED
+    short-circuit (true|false) "false"
+>
+
+<!ELEMENT param (#PCDATA)>
+<!ATTLIST param
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT message (#PCDATA)>
+<!ATTLIST message
+    key CDATA #IMPLIED
+>
+
+

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/resources/xwork-validator-1.0.3.dtd
----------------------------------------------------------------------
diff --git a/core/src/main/resources/xwork-validator-1.0.3.dtd 
b/core/src/main/resources/xwork-validator-1.0.3.dtd
new file mode 100644
index 0000000..e474b65
--- /dev/null
+++ b/core/src/main/resources/xwork-validator-1.0.3.dtd
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  XWork Validators DTD.
+  Used the following DOCTYPE.
+
+  <!DOCTYPE validators PUBLIC
+               "-//Apache Struts//XWork Validator 1.0.3//EN"
+               "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd";>
+-->
+
+
+<!ELEMENT validators (field|validator)+>
+
+<!ELEMENT field (field-validator+)>
+<!ATTLIST field
+       name CDATA #REQUIRED
+>
+
+<!ELEMENT field-validator (param*, message)>
+<!ATTLIST field-validator
+       type CDATA #REQUIRED
+    short-circuit (true|false) "false"
+>
+
+<!ELEMENT validator (param*, message)>
+<!ATTLIST validator
+       type CDATA #REQUIRED
+    short-circuit (true|false) "false"
+>
+
+<!ELEMENT param (#PCDATA)>
+<!ATTLIST param
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT message (#PCDATA|param)*>
+<!ATTLIST message
+    key CDATA #IMPLIED
+>
+
+

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/resources/xwork-validator-1.0.dtd
----------------------------------------------------------------------
diff --git a/core/src/main/resources/xwork-validator-1.0.dtd 
b/core/src/main/resources/xwork-validator-1.0.dtd
new file mode 100644
index 0000000..4f5600b
--- /dev/null
+++ b/core/src/main/resources/xwork-validator-1.0.dtd
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  XWork Validators DTD.
+  Used the following DOCTYPE.
+  
+  <!DOCTYPE validators PUBLIC 
+               "-//Apache Struts//XWork Validator 1.0//EN"
+               "http://struts.apache.org/dtds/xwork-validator-1.0.dtd";>
+-->
+
+
+<!ELEMENT validators (field*,validator*)>
+
+<!ELEMENT field (field-validator+)>
+<!ATTLIST field
+       name CDATA #REQUIRED
+>
+
+<!ELEMENT field-validator (param*, message)>
+<!ATTLIST field-validator
+       type CDATA #REQUIRED
+>
+
+<!ELEMENT validator (param*, message)>
+<!ATTLIST validator
+       type CDATA #REQUIRED
+>
+
+<!ELEMENT param (#PCDATA)>
+<!ATTLIST param
+    name CDATA #REQUIRED
+>
+
+<!ELEMENT message (#PCDATA)>
+<!ATTLIST message
+    key CDATA #IMPLIED
+>
+
+

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/resources/xwork-validator-config-1.0.dtd
----------------------------------------------------------------------
diff --git a/core/src/main/resources/xwork-validator-config-1.0.dtd 
b/core/src/main/resources/xwork-validator-config-1.0.dtd
new file mode 100644
index 0000000..d860269
--- /dev/null
+++ b/core/src/main/resources/xwork-validator-config-1.0.dtd
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  XWork Validator Config DTD.
+  Used the following DOCTYPE.
+
+  <!DOCTYPE validators PUBLIC
+               "-//Apache Struts//XWork Validator Config 1.0//EN"
+               "http://struts.apache.org/dtds/xwork-validator-config-1.0.dtd";>
+-->
+<!ELEMENT validators (validator)+>
+
+<!ELEMENT validator (#PCDATA)>
+<!ATTLIST validator
+       name CDATA #REQUIRED
+    class CDATA #REQUIRED
+>

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/resources/xwork-validator-definition-1.0.dtd
----------------------------------------------------------------------
diff --git a/core/src/main/resources/xwork-validator-definition-1.0.dtd 
b/core/src/main/resources/xwork-validator-definition-1.0.dtd
new file mode 100644
index 0000000..33b22fb
--- /dev/null
+++ b/core/src/main/resources/xwork-validator-definition-1.0.dtd
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  XWork Validators Definition DTD.
+  Used the following DOCTYPE.
+
+  <!DOCTYPE validators PUBLIC
+               "-//Apache Struts//XWork Validator Definition 1.0//EN"
+               
"http://struts.apache.org/dtds/xwork-validator-definition-1.0.dtd";>
+-->
+
+<!ELEMENT validators (validator*)>
+
+<!ELEMENT validator (#PCDATA)>
+<!ATTLIST validator
+    name CDATA #REQUIRED
+    class CDATA #REQUIRED
+>
+

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/java/PackagelessAction.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/PackagelessAction.java 
b/core/src/test/java/PackagelessAction.java
new file mode 100644
index 0000000..8c792c0
--- /dev/null
+++ b/core/src/test/java/PackagelessAction.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+import com.opensymphony.xwork2.ActionSupport;
+
+
+/**
+ * @author Mark Woon
+ */
+public class PackagelessAction extends ActionSupport {
+
+    /**
+     * Default constructor.
+     */
+    public PackagelessAction() {
+    }
+
+
+    @Override
+    public String execute() {
+        // from action's bundle
+        System.out.println(getText("actionProperty"));
+
+        // from default bundle
+        System.out.println(getText("foo.range"));
+
+        // nonexistant
+        System.out.println(getText("non.existant"));
+
+        return NONE;
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/java/com/opensymphony/xwork2/ActionContextTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/ActionContextTest.java 
b/core/src/test/java/com/opensymphony/xwork2/ActionContextTest.java
new file mode 100644
index 0000000..fb5a538
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/ActionContextTest.java
@@ -0,0 +1,115 @@
+/*
+ * 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.util.ValueStack;
+import com.opensymphony.xwork2.util.ValueStackFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * Unit test for {@link ActionContext}.
+ *
+ * @author Jason Carreira
+ */
+public class ActionContextTest extends XWorkTestCase {
+
+    private static final String APPLICATION_KEY = 
"com.opensymphony.xwork2.ActionContextTest.application";
+    private static final String SESSION_KEY = 
"com.opensymphony.xwork2.ActionContextTest.session";
+    private static final String PARAMETERS_KEY = 
"com.opensymphony.xwork2.ActionContextTest.params";
+    private static final String ACTION_NAME = 
"com.opensymphony.xwork2.ActionContextTest.actionName";
+
+    private ActionContext context;
+
+    @Override public void setUp() throws Exception {
+        super.setUp();
+        ValueStack valueStack = 
container.getInstance(ValueStackFactory.class).createValueStack();
+        Map<String, Object> extraContext = valueStack.getContext();
+        Map<String, Object> application = new HashMap<>();
+        application.put(APPLICATION_KEY, APPLICATION_KEY);
+
+        Map<String, Object> session = new HashMap<>();
+        session.put(SESSION_KEY, SESSION_KEY);
+
+        Map<String, Object> params = new HashMap<>();
+        params.put(PARAMETERS_KEY, PARAMETERS_KEY);
+        extraContext.put(ActionContext.APPLICATION, application);
+        extraContext.put(ActionContext.SESSION, session);
+        extraContext.put(ActionContext.PARAMETERS, params);
+        extraContext.put(ActionContext.ACTION_NAME, ACTION_NAME);
+        context = new ActionContext(extraContext);
+        ActionContext.setContext(context);
+    }
+
+    public void testContextParams() {
+        
assertTrue(ActionContext.getContext().getApplication().containsKey(APPLICATION_KEY));
+        
assertTrue(ActionContext.getContext().getSession().containsKey(SESSION_KEY));
+        
assertTrue(ActionContext.getContext().getParameters().containsKey(PARAMETERS_KEY));
+        assertEquals(ActionContext.getContext().getName(), ACTION_NAME);
+    }
+
+    public void testGetContext() {
+        ActionContext threadContext = ActionContext.getContext();
+        assertEquals(context, threadContext);
+    }
+
+    public void testNewActionContextCanFindDefaultTexts() {
+        ValueStack valueStack = context.getValueStack();
+        String actionErrorMessage = (String) 
valueStack.findValue("getText('xwork.error.action.execution')");
+        assertNotNull(actionErrorMessage);
+        assertEquals("Error during Action invocation", actionErrorMessage);
+    }
+
+    public void testApplication() {
+        Map<String, Object> app = new HashMap<>();
+        context.setApplication(app);
+        assertEquals(app, context.getApplication());
+    }
+
+    public void testContextMap() {
+        Map<String, Object> map = new HashMap<>();
+        context.setContextMap(map);
+        assertEquals(map, context.getContextMap());
+    }
+
+    public void testParameters() {
+        Map<String, Object> param = new HashMap<>();
+        context.setParameters(param);
+        assertEquals(param, context.getParameters());
+    }
+
+    public void testConversionErrors() {
+        Map<String, Object> errors = context.getConversionErrors();
+        assertNotNull(errors);
+        assertEquals(0, errors.size());
+
+        Map<String, Object> errors2 = new HashMap<>();
+        context.setConversionErrors(errors);
+        assertEquals(errors2, context.getConversionErrors());
+    }
+
+    public void testStaticMethods() {
+        assertEquals(context, ActionContext.getContext());
+
+        ActionContext context2 = new ActionContext(null);
+        ActionContext.setContext(context2);
+
+        assertEquals(context2, ActionContext.getContext());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/java/com/opensymphony/xwork2/ActionContextThreadLocalTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/com/opensymphony/xwork2/ActionContextThreadLocalTest.java 
b/core/src/test/java/com/opensymphony/xwork2/ActionContextThreadLocalTest.java
new file mode 100644
index 0000000..d29aa32
--- /dev/null
+++ 
b/core/src/test/java/com/opensymphony/xwork2/ActionContextThreadLocalTest.java
@@ -0,0 +1,42 @@
+/*
+ * 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 junit.framework.TestCase;
+
+import java.util.HashMap;
+
+
+/**
+ * Simple Test ActionContext's ThreadLocal
+ * 
+ * @author tm_jee
+ * @version $Date$ $Id$
+ */
+public class ActionContextThreadLocalTest extends TestCase {
+
+       
+       public void testGetContext() throws Exception {
+           ActionContext.setContext(null);
+               assertNull(ActionContext.getContext());
+       }
+       
+       public void testSetContext() throws Exception {
+               ActionContext context = new ActionContext(new HashMap<String, 
Object>());
+               ActionContext.setContext(context);
+               assertEquals(context, ActionContext.getContext());
+       }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/java/com/opensymphony/xwork2/ActionInvocationTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/com/opensymphony/xwork2/ActionInvocationTest.java 
b/core/src/test/java/com/opensymphony/xwork2/ActionInvocationTest.java
new file mode 100644
index 0000000..58d02dd
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/ActionInvocationTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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;
+
+import com.opensymphony.xwork2.config.entities.ActionConfig;
+import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider;
+
+import java.util.HashMap;
+
+
+/**
+ * @author $Author$
+ * @version $Revision$
+ */
+public class ActionInvocationTest extends XWorkTestCase {
+
+    public void testCommandInvocation() throws Exception {
+        ActionProxy baseActionProxy = actionProxyFactory.createActionProxy(
+                "baz", "commandTest", null, null);
+        assertEquals("success", baseActionProxy.execute());
+
+        ActionProxy commandActionProxy = actionProxyFactory.createActionProxy(
+                "baz", "myCommand", null, null);
+        assertEquals(SimpleAction.COMMAND_RETURN_CODE, 
commandActionProxy.execute());
+    }
+
+    public void testCommandInvocationDoMethod() throws Exception {
+        ActionProxy baseActionProxy = actionProxyFactory.createActionProxy(
+                "baz", "doMethodTest", null, null);
+        assertEquals("input", baseActionProxy.execute());
+    }
+
+    public void testCommandInvocationUnknownHandler() throws Exception {
+
+        DefaultActionProxy baseActionProxy = (DefaultActionProxy) 
actionProxyFactory.createActionProxy(
+                "baz", "unknownMethodTest", "unknownmethod", null);
+        UnknownHandler unknownHandler = new UnknownHandler() {
+                       public ActionConfig handleUnknownAction(String 
namespace, String actionName) throws XWorkException { return null;}
+                       public Result handleUnknownResult(ActionContext 
actionContext, String actionName, ActionConfig actionConfig, String resultCode) 
throws XWorkException {
+                               return null;
+                       }
+                       public Object handleUnknownActionMethod(Object action, 
String methodName) throws NoSuchMethodException {
+                               if (methodName.equals("unknownmethod")) {
+                                       return "found";
+                               } else {
+                                       return null;
+                               }
+                       }
+        };
+
+        UnknownHandlerManagerMock uhm = new UnknownHandlerManagerMock();
+        uhm.addUnknownHandler(unknownHandler);
+        
((DefaultActionInvocation)baseActionProxy.getInvocation()).setUnknownHandlerManager(uhm);
+
+        assertEquals("found", baseActionProxy.execute());
+    }
+
+    public void testResultReturnInvocationAndWired() throws Exception {
+        ActionProxy baseActionProxy = actionProxyFactory.createActionProxy(
+                "baz", "resultAction", null, null);
+        assertEquals(null, baseActionProxy.execute());
+        assertTrue(SimpleAction.resultCalled);
+    }
+
+    public void testSimple() {
+        HashMap<String, Object> params = new HashMap<>();
+        params.put("blah", "this is blah");
+
+        HashMap<String, Object> extraContext = new HashMap<>();
+        extraContext.put(ActionContext.PARAMETERS, params);
+
+        try {
+            ActionProxy proxy = actionProxyFactory.createActionProxy( "", 
"Foo", null, extraContext);
+            proxy.execute();
+            assertEquals("this is blah", 
proxy.getInvocation().getStack().findValue("[1].blah"));
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail();
+        }
+    }
+
+    @Override protected void setUp() throws Exception {
+        super.setUp();
+
+        // ensure we're using the default configuration, not simple config
+        XmlConfigurationProvider configurationProvider = new 
XmlConfigurationProvider("xwork-sample.xml");
+        container.inject(configurationProvider);
+        loadConfigurationProviders(configurationProvider);
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/java/com/opensymphony/xwork2/ActionNestingTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/ActionNestingTest.java 
b/core/src/test/java/com/opensymphony/xwork2/ActionNestingTest.java
new file mode 100644
index 0000000..ee996e5
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/ActionNestingTest.java
@@ -0,0 +1,143 @@
+/*
+ * 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;
+
+import com.opensymphony.xwork2.config.Configuration;
+import com.opensymphony.xwork2.config.ConfigurationProvider;
+import com.opensymphony.xwork2.config.entities.ActionConfig;
+import com.opensymphony.xwork2.config.entities.PackageConfig;
+import com.opensymphony.xwork2.config.entities.ResultConfig;
+import com.opensymphony.xwork2.inject.ContainerBuilder;
+import com.opensymphony.xwork2.mock.MockResult;
+import com.opensymphony.xwork2.util.ValueStack;
+import com.opensymphony.xwork2.util.location.LocatableProperties;
+
+import java.util.HashMap;
+
+
+/**
+ * ActionNestingTest
+ *
+ * @author Jason Carreira
+ *         Created Mar 5, 2003 2:02:01 PM
+ */
+public class ActionNestingTest extends XWorkTestCase {
+
+    public static final String VALUE = "myValue";
+    public static final String NESTED_VALUE = "myNestedValue";
+    public static final String KEY = "myProperty";
+    public static final String NESTED_KEY = "nestedProperty";
+    public static final String NAMESPACE = "NestedActionTest";
+    public static final String SIMPLE_ACTION_NAME = "SimpleAction";
+    public static final String NO_STACK_ACTION_NAME = "NoStackNestedAction";
+    public static final String STACK_ACTION_NAME = "StackNestedAction";
+
+
+    private ActionContext context;
+
+
+    public String getMyProperty() {
+        return VALUE;
+    }
+
+    @Override public void setUp() throws Exception {
+        super.setUp();
+        loadConfigurationProviders(new NestedTestConfigurationProvider());
+
+        context = ActionContext.getContext();
+        context.getValueStack().push(this);
+    }
+
+    @Override protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    public void testNestedContext() throws Exception {
+        assertEquals(context, ActionContext.getContext());
+        ActionProxy proxy = actionProxyFactory.createActionProxy(NAMESPACE, 
SIMPLE_ACTION_NAME, null);
+        proxy.execute();
+        assertEquals(context, ActionContext.getContext());
+    }
+
+    public void testNestedNoValueStack() throws Exception {
+        ValueStack stack = ActionContext.getContext().getValueStack();
+        assertEquals(VALUE, stack.findValue(KEY));
+
+        ActionProxy proxy = actionProxyFactory.createActionProxy(NAMESPACE, 
NO_STACK_ACTION_NAME, null);
+        proxy.execute();
+        stack = ActionContext.getContext().getValueStack();
+        assertEquals(stack.findValue(KEY), VALUE);
+        assertNull(stack.findValue(NESTED_KEY));
+    }
+
+    public void testNestedValueStack() throws Exception {
+        ValueStack stack = ActionContext.getContext().getValueStack();
+        assertEquals(VALUE, stack.findValue(KEY));
+
+        HashMap<String, Object> extraContext = new HashMap<>();
+        extraContext.put(ActionContext.VALUE_STACK, stack);
+
+        ActionProxy proxy = actionProxyFactory.createActionProxy(NAMESPACE, 
STACK_ACTION_NAME, extraContext);
+        proxy.execute();
+        assertEquals(context, ActionContext.getContext());
+        assertEquals(stack, ActionContext.getContext().getValueStack());
+        assertEquals(VALUE, stack.findValue(KEY));
+        assertEquals(NESTED_VALUE, stack.findValue(NESTED_KEY));
+        assertEquals(3, stack.size());
+    }
+
+
+    class NestedTestConfigurationProvider implements ConfigurationProvider {
+        private Configuration configuration;
+        public void destroy() {
+        }
+        public void init(Configuration configuration) {
+            this.configuration = configuration;
+        }
+
+        public void register(ContainerBuilder builder, LocatableProperties 
props) {
+        }
+        
+        public void loadPackages() {
+            
+            PackageConfig packageContext = new 
PackageConfig.Builder("nestedActionTest")
+                .addActionConfig(SIMPLE_ACTION_NAME, new 
ActionConfig.Builder("nestedActionTest", SIMPLE_ACTION_NAME, 
SimpleAction.class.getName())
+                        .addResultConfig(new 
ResultConfig.Builder(Action.SUCCESS, MockResult.class.getName()).build())
+                        .addResultConfig(new 
ResultConfig.Builder(Action.ERROR, MockResult.class.getName()).build())
+                        .build())
+                .addActionConfig(NO_STACK_ACTION_NAME, new 
ActionConfig.Builder("nestedActionTest", NO_STACK_ACTION_NAME, 
NestedAction.class.getName())
+                        .addResultConfig(new 
ResultConfig.Builder(Action.SUCCESS, MockResult.class.getName()).build())
+                        .methodName("noStack")
+                        .build())
+                .addActionConfig(STACK_ACTION_NAME, new 
ActionConfig.Builder("nestedActionTest", STACK_ACTION_NAME, 
NestedAction.class.getName())
+                        .addResultConfig(new 
ResultConfig.Builder(Action.SUCCESS, MockResult.class.getName()).build())
+                        .methodName("stack")
+                        .build())
+                .namespace(NAMESPACE)
+                .build();
+            configuration.addPackageConfig("nestedActionTest", packageContext);
+        }
+
+        /**
+         * Tells whether the ConfigurationProvider should reload its 
configuration
+         *
+         * @return
+         */
+        public boolean needsReload() {
+            return false;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/java/com/opensymphony/xwork2/ActionSupportTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/ActionSupportTest.java 
b/core/src/test/java/com/opensymphony/xwork2/ActionSupportTest.java
new file mode 100644
index 0000000..98a5dac
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/ActionSupportTest.java
@@ -0,0 +1,361 @@
+/*
+ * 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.util.ValueStack;
+
+import java.util.*;
+
+/**
+ * Unit test for {@link ActionSupport}.
+ *
+ * @author Claus Ibsen
+ */
+public class ActionSupportTest extends XWorkTestCase {
+
+    private ActionSupport as;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        as = new ActionSupport();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        as = null;
+    }
+
+    public void testNothingDoneOnActionSupport() throws Exception {
+        assertEquals(false, as.hasErrors());
+
+        assertNotNull(as.getActionErrors());
+        assertEquals(0, as.getActionErrors().size());
+        assertEquals(false, as.hasActionErrors());
+
+        assertNotNull(as.getActionMessages());
+        assertEquals(0, as.getActionMessages().size());
+        assertEquals(false, as.hasActionMessages());
+
+        assertNotNull(as.getFieldErrors());
+        assertEquals(0, as.getFieldErrors().size());
+        assertEquals(false, as.hasFieldErrors());
+
+        assertNull(as.getText(null));
+
+        try {
+            as.pause(null);
+        } catch (Exception e) {
+            fail("Should not fail");
+        }
+
+        assertEquals(Action.INPUT, as.input());
+        assertEquals(Action.SUCCESS, as.doDefault());
+        assertEquals(Action.SUCCESS, as.execute());
+        try {
+            as.clone();
+            fail("Failure expected for clone()");
+        } catch (CloneNotSupportedException e) {
+            // success!
+        }
+
+
+        assertNull(as.getText(null, (List) null));
+        assertNull(as.getText(null, (String) null));
+        assertNull(as.getText(null, (String[]) null));
+
+        assertNull(as.getText(null, (String) null, (List) null));
+        assertNull(as.getText(null, (String) null, (String) null));
+        assertNull(as.getText(null, (String) null, (String[]) null));
+
+        assertNull(as.getText(null, (String) null, (List) null, (ValueStack) 
null));
+        assertNull(as.getText(null, (String) null, (String[]) null, 
(ValueStack) null));
+
+        assertNotNull(as.getLocale());
+        assertEquals(ActionContext.getContext().getLocale(), as.getLocale());
+
+        assertNull(as.getTexts()); // can not find a bundle
+        assertEquals("not.in.bundle", as.getText("not.in.bundle"));
+    }
+
+    public void testActionErrors() {
+        assertEquals(false, as.hasActionErrors());
+        assertEquals(0, as.getActionErrors().size());
+        as.addActionError("Damm");
+        assertEquals(1, as.getActionErrors().size());
+        assertEquals("Damm", as.getActionErrors().iterator().next());
+        assertEquals(true, as.hasActionErrors());
+        assertEquals(true, as.hasErrors());
+
+        as.clearErrorsAndMessages();
+        assertEquals(false, as.hasActionErrors());
+        assertEquals(false, as.hasErrors());
+    }
+
+    public void testActionMessages() {
+        assertEquals(false, as.hasActionMessages());
+        assertEquals(0, as.getActionMessages().size());
+        as.addActionMessage("Killroy was here");
+        assertEquals(1, as.getActionMessages().size());
+        assertEquals("Killroy was here", 
as.getActionMessages().iterator().next());
+        assertEquals(true, as.hasActionMessages());
+
+        assertEquals(false, as.hasActionErrors()); // does not count as a error
+        assertEquals(false, as.hasErrors()); // does not count as a error
+
+        as.clearErrorsAndMessages();
+        assertEquals(false, as.hasActionMessages());
+        assertEquals(false, as.hasErrors());
+    }
+
+    public void testFieldErrors() {
+        assertEquals(false, as.hasFieldErrors());
+        assertEquals(0, as.getFieldErrors().size());
+        as.addFieldError("username", "Admin is not allowed as username");
+        List<String> errors = as.getFieldErrors().get("username");
+        assertEquals(1, errors.size());
+        assertEquals("Admin is not allowed as username", errors.get(0));
+
+        assertEquals(true, as.hasFieldErrors());
+        assertEquals(true, as.hasErrors());
+
+        as.clearErrorsAndMessages();
+        assertEquals(false, as.hasFieldErrors());
+        assertEquals(false, as.hasErrors());
+    }
+
+    public void testDeprecated() throws Exception {
+        assertNotNull(as.getErrorMessages());
+        assertEquals(0, as.getErrorMessages().size());
+
+        assertNotNull(as.getErrors());
+        assertEquals(0, as.getErrors().size());
+    }
+
+    public void testLocale() {
+        Locale defLocale = Locale.getDefault();
+        ActionContext.getContext().setLocale(null);
+
+        // will never return null, if no locale is set then default is returned
+        assertNotNull(as.getLocale());
+        assertEquals(defLocale, as.getLocale());
+
+        ActionContext.getContext().setLocale(Locale.ITALY);
+        assertEquals(Locale.ITALY, as.getLocale());
+
+        ActionContext.setContext(new ActionContext(new HashMap<String, 
Object>()));
+        assertEquals(defLocale, as.getLocale()); // ActionContext will create 
a new context, when it was set to null before
+    }
+
+    public void testMyActionSupport() throws Exception {
+        ActionContext.getContext().setLocale(new Locale("da"));
+        MyActionSupport mas = new MyActionSupport();
+
+        assertEquals("santa", mas.doDefault());
+        assertNotNull(mas.getTexts());
+
+        assertEquals(false, mas.hasActionMessages());
+        mas.validate();
+        assertEquals(true, mas.hasActionMessages());
+    }
+
+    public void testSimpleGetTexts() throws Exception {
+        ActionContext.getContext().setLocale(new Locale("da"));
+        MyActionSupport mas = new MyActionSupport();
+
+        checkGetTexts(mas);
+    }
+
+    public void testSimpleGetTextsWithInjectedTextProvider() throws Exception {
+        ActionContext.getContext().setLocale(new Locale("da"));
+        MyActionSupport mas = new MyActionSupport();
+
+        TextProvider textProvider = container.getInstance(TextProvider.class, 
"system");
+
+        assertNotNull(textProvider);
+
+        container.inject(mas);
+
+        checkGetTexts(mas);
+    }
+
+    private void checkGetTexts(MyActionSupport mas) {
+        assertEquals("Hello World", mas.getText("hello"));
+        assertEquals("not.in.bundle", mas.getText("not.in.bundle"));
+
+        assertEquals("Hello World", mas.getText("hello", "this is default"));
+        assertEquals("this is default", mas.getText("not.in.bundle", "this is 
default"));
+
+        List nullList = null;
+        assertEquals("Hello World", mas.getText("hello", nullList));
+
+        String[] nullStrings = null;
+        assertEquals("Hello World", mas.getText("hello", nullStrings));
+    }
+
+    public void testGetTextsWithArgs() throws Exception {
+        ActionContext.getContext().setLocale(new Locale("da"));
+        MyActionSupport mas = new MyActionSupport();
+
+        assertEquals("Hello World", mas.getText("hello", "this is default", 
"from me")); // no args in bundle
+        assertEquals("Hello World from me", mas.getText("hello.0", "this is 
default", "from me"));
+        assertEquals("this is default", mas.getText("not.in.bundle", "this is 
default", "from me"));
+        assertEquals("this is default from me", mas.getText("not.in.bundle", 
"this is default {0}", "from me"));
+
+        assertEquals("not.in.bundle", mas.getText("not.in.bundle"));
+    }
+
+    public void testGetTextsWithListArgs() throws Exception {
+        ActionContext.getContext().setLocale(new Locale("da"));
+        MyActionSupport mas = new MyActionSupport();
+
+        List<Object> args = new ArrayList<>();
+        args.add("Santa");
+        args.add("loud");
+        assertEquals("Hello World", mas.getText("hello", "this is default", 
args)); // no args in bundle
+        assertEquals("Hello World Santa", mas.getText("hello.0", "this is 
default", args)); // only 1 arg in bundle
+        assertEquals("Hello World. This is Santa speaking loud", 
mas.getText("hello.1", "this is default", args));
+
+        assertEquals("this is default", mas.getText("not.in.bundle", "this is 
default", args));
+        assertEquals("this is default Santa", mas.getText("not.in.bundle", 
"this is default {0}", args));
+        assertEquals("this is default Santa speaking loud", 
mas.getText("not.in.bundle", "this is default {0} speaking {1}", args));
+
+        assertEquals("Hello World", mas.getText("hello", args)); // no args in 
bundle
+        assertEquals("Hello World Santa", mas.getText("hello.0", args)); // 
only 1 arg in bundle
+        assertEquals("Hello World. This is Santa speaking loud", 
mas.getText("hello.1", args));
+
+        assertEquals("not.in.bundle", mas.getText("not.in.bundle", args));
+
+        assertEquals("Hello World", mas.getText("hello", "this is default", 
(List) null));
+        assertEquals("this is default", mas.getText("not.in.bundle", "this is 
default", (List) null));
+    }
+
+    public void testGetTextsWithArrayArgs() throws Exception {
+        ActionContext.getContext().setLocale(new Locale("da"));
+        MyActionSupport mas = new MyActionSupport();
+
+        String[] args = {"Santa", "loud"};
+        assertEquals("Hello World", mas.getText("hello", "this is default", 
args)); // no args in bundle
+        assertEquals("Hello World Santa", mas.getText("hello.0", "this is 
default", args)); // only 1 arg in bundle
+        assertEquals("Hello World. This is Santa speaking loud", 
mas.getText("hello.1", "this is default", args));
+
+        assertEquals("this is default", mas.getText("not.in.bundle", "this is 
default", args));
+        assertEquals("this is default Santa", mas.getText("not.in.bundle", 
"this is default {0}", args));
+        assertEquals("this is default Santa speaking loud", 
mas.getText("not.in.bundle", "this is default {0} speaking {1}", args));
+
+        assertEquals("Hello World", mas.getText("hello", args)); // no args in 
bundle
+        assertEquals("Hello World Santa", mas.getText("hello.0", args)); // 
only 1 arg in bundle
+        assertEquals("Hello World. This is Santa speaking loud", 
mas.getText("hello.1", args));
+
+        assertEquals("not.in.bundle", mas.getText("not.in.bundle", args));
+
+        assertEquals("Hello World", mas.getText("hello", "this is default", 
(String[]) null));
+        assertEquals("this is default", mas.getText("not.in.bundle", "this is 
default", (String[]) null));
+    }
+
+    public void testGetTextsWithListAndStack() throws Exception {
+        ActionContext.getContext().setLocale(new Locale("da"));
+        MyActionSupport mas = new MyActionSupport();
+
+        ValueStack stack = ActionContext.getContext().getValueStack();
+
+        List<Object> args = new ArrayList<>();
+        args.add("Santa");
+        args.add("loud");
+        assertEquals("Hello World", mas.getText("hello", "this is default", 
args, stack)); // no args in bundle
+        assertEquals("Hello World Santa", mas.getText("hello.0", "this is 
default", args, stack)); // only 1 arg in bundle
+        assertEquals("Hello World. This is Santa speaking loud", 
mas.getText("hello.1", "this is default", args, stack));
+
+        assertEquals("this is default", mas.getText("not.in.bundle", "this is 
default", args, stack));
+        assertEquals("this is default Santa", mas.getText("not.in.bundle", 
"this is default {0}", args, stack));
+        assertEquals("this is default Santa speaking loud", 
mas.getText("not.in.bundle", "this is default {0} speaking {1}", args, stack));
+    }
+
+    public void testGetTextsWithArrayAndStack() throws Exception {
+        ActionContext.getContext().setLocale(new Locale("da"));
+        MyActionSupport mas = new MyActionSupport();
+
+        ValueStack stack = ActionContext.getContext().getValueStack();
+
+        String[] args = {"Santa", "loud"};
+        assertEquals("Hello World", mas.getText("hello", "this is default", 
args, stack)); // no args in bundle
+        assertEquals("Hello World Santa", mas.getText("hello.0", "this is 
default", args, stack)); // only 1 arg in bundle
+        assertEquals("Hello World. This is Santa speaking loud", 
mas.getText("hello.1", "this is default", args, stack));
+
+        assertEquals("this is default", mas.getText("not.in.bundle", "this is 
default", args, stack));
+        assertEquals("this is default Santa", mas.getText("not.in.bundle", 
"this is default {0}", args, stack));
+        assertEquals("this is default Santa speaking loud", 
mas.getText("not.in.bundle", "this is default {0} speaking {1}", args, stack));
+    }
+
+    public void testGetBundle() throws Exception {
+        ActionContext.getContext().setLocale(new Locale("da"));
+        MyActionSupport mas = new MyActionSupport();
+
+        ResourceBundle rb = 
ResourceBundle.getBundle(MyActionSupport.class.getName(), new Locale("da"));
+        assertEquals(rb, mas.getTexts(MyActionSupport.class.getName()));
+    }
+
+    public void testFormattingSupport() throws Exception {
+        ActionContext.getContext().setLocale(new Locale("da"));
+        MyActionSupport mas = new MyActionSupport();
+        ActionContext.getContext().getValueStack().push(mas);
+
+        mas.setVal(234d);
+
+        String formatted = mas.getFormatted("format.number", "val");
+
+        assertEquals("234,0", formatted);
+    }
+
+    public void testFormattingSupportWithConversionError() throws Exception {
+        ActionContext.getContext().getConversionErrors().put("val", new 
String[]{"4567def"});
+        ActionContext.getContext().setLocale(new Locale("da"));
+        MyActionSupport mas = new MyActionSupport();
+        ActionContext.getContext().getValueStack().push(mas);
+
+        mas.setVal(234d);
+
+        String formatted = mas.getFormatted("format.number", "val");
+
+        assertEquals("4567def", formatted);
+    }
+
+    private class MyActionSupport extends ActionSupport {
+
+        private Double val;
+
+        @Override
+        public String doDefault() throws Exception {
+            return "santa";
+        }
+
+        @Override
+        public void validate() {
+            super.validate(); // to have code coverage
+            addActionMessage("validation was called");
+        }
+
+        public Double getVal() {
+            return val;
+        }
+
+        public void setVal(Double val) {
+            this.val = val;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/test/java/com/opensymphony/xwork2/AnnotatedTestBean.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/AnnotatedTestBean.java 
b/core/src/test/java/com/opensymphony/xwork2/AnnotatedTestBean.java
new file mode 100644
index 0000000..98a5d96
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/AnnotatedTestBean.java
@@ -0,0 +1,76 @@
+/*
+ * 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.validator.annotations.IntRangeFieldValidator;
+import com.opensymphony.xwork2.validator.annotations.RequiredStringValidator;
+import com.opensymphony.xwork2.validator.annotations.Validations;
+
+import java.util.Date;
+
+
+/**
+ * AnnotatedTestBean
+ * @author Jason Carreira
+ * @author Rainer Hermanns
+ * Created Aug 4, 2003 12:39:53 AM
+ */
+public class AnnotatedTestBean {
+    //~ Instance fields 
////////////////////////////////////////////////////////
+
+    private Date birth;
+    private String name;
+    private int count;
+
+    //~ Constructors 
///////////////////////////////////////////////////////////
+
+    public AnnotatedTestBean() {
+    }
+
+    //~ Methods 
////////////////////////////////////////////////////////////////
+
+    public void setBirth(Date birth) {
+        this.birth = birth;
+    }
+
+    public Date getBirth() {
+        return birth;
+    }
+
+    @Validations(
+            intRangeFields = {
+                @IntRangeFieldValidator(shortCircuit = true, min = "1", 
max="100", key="invalid.count", message = "Invalid Count!"),
+                @IntRangeFieldValidator(shortCircuit = true, min = "20", 
max="28", key="invalid.count.bad", message = "Smaller Invalid Count: ${count}")
+            }
+
+    )
+    public void setCount(int count) {
+        this.count = count;
+    }
+
+    public int getCount() {
+        return count;
+    }
+
+    @RequiredStringValidator(message = "You must enter a name.")
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+}

Reply via email to