Merge pull request #320 from JCgH4164838Gh792C124B5/localS2_26x_B2

Fix for access issue for 2.6 discovered in WW-5004:
This commit is contained in:
Aleksandr Mashchenko
2019-01-31 17:39:35 +02:00
committed by GitHub
16 changed files with 576 additions and 76 deletions
@@ -224,6 +224,7 @@ public class XWorkConfigurationProvider implements ConfigurationProvider {
props.setProperty(StrutsConstants.STRUTS_ENABLE_OGNL_EVAL_EXPRESSION, Boolean.FALSE.toString());
props.setProperty(StrutsConstants.STRUTS_CONFIGURATION_XML_RELOAD, Boolean.FALSE.toString());
props.setProperty(StrutsConstants.STRUTS_ALLOW_STATIC_METHOD_ACCESS, Boolean.FALSE.toString());
props.setProperty(StrutsConstants.STRUTS_ALLOW_STATIC_FIELD_ACCESS, Boolean.TRUE.toString());
}
}
@@ -66,6 +66,7 @@ public class OgnlUtil {
private Set<String> excludedPackageNames;
private Container container;
private boolean allowStaticFieldAccess = true;
private boolean allowStaticMethodAccess;
private boolean disallowProxyMemberAccess;
@@ -173,6 +174,11 @@ public class OgnlUtil {
this.container = container;
}
@Inject(value = StrutsConstants.STRUTS_ALLOW_STATIC_FIELD_ACCESS, required = false)
protected void setAllowStaticFieldAccess(String allowStaticFieldAccess) {
this.allowStaticFieldAccess = BooleanUtils.toBoolean(allowStaticFieldAccess);
}
@Inject(value = StrutsConstants.STRUTS_ALLOW_STATIC_METHOD_ACCESS, required = false)
protected void setAllowStaticMethodAccess(String allowStaticMethodAccess) {
this.allowStaticMethodAccess = BooleanUtils.toBoolean(allowStaticMethodAccess);
@@ -180,7 +186,7 @@ public class OgnlUtil {
@Inject(value = StrutsConstants.STRUTS_DISALLOW_PROXY_MEMBER_ACCESS, required = false)
protected void setDisallowProxyMemberAccess(String disallowProxyMemberAccess) {
this.disallowProxyMemberAccess = Boolean.parseBoolean(disallowProxyMemberAccess);
this.disallowProxyMemberAccess = BooleanUtils.toBoolean(disallowProxyMemberAccess);
}
public boolean isDisallowProxyMemberAccess() {
@@ -699,7 +705,7 @@ public class OgnlUtil {
resolver = container.getInstance(CompoundRootAccessor.class);
}
SecurityMemberAccess memberAccess = new SecurityMemberAccess(allowStaticMethodAccess);
SecurityMemberAccess memberAccess = new SecurityMemberAccess(allowStaticMethodAccess, allowStaticFieldAccess);
memberAccess.setExcludedClasses(excludedClasses);
memberAccess.setExcludedPackageNamePatterns(excludedPackageNamePatterns);
memberAccess.setExcludedPackageNames(excludedPackageNames);
@@ -72,13 +72,13 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
private boolean devMode;
private boolean logMissingProperties;
protected OgnlValueStack(XWorkConverter xworkConverter, CompoundRootAccessor accessor, TextProvider prov, boolean allowStaticAccess) {
setRoot(xworkConverter, accessor, new CompoundRoot(), allowStaticAccess);
protected OgnlValueStack(XWorkConverter xworkConverter, CompoundRootAccessor accessor, TextProvider prov, boolean allowStaticMethodAccess, boolean allowStaticFieldAccess) {
setRoot(xworkConverter, accessor, new CompoundRoot(), allowStaticMethodAccess, allowStaticFieldAccess);
push(prov);
}
protected OgnlValueStack(ValueStack vs, XWorkConverter xworkConverter, CompoundRootAccessor accessor, boolean allowStaticAccess) {
setRoot(xworkConverter, accessor, new CompoundRoot(vs.getRoot()), allowStaticAccess);
protected OgnlValueStack(ValueStack vs, XWorkConverter xworkConverter, CompoundRootAccessor accessor, boolean allowStaticMethodAccess, boolean allowStaticFieldAccess) {
setRoot(xworkConverter, accessor, new CompoundRoot(vs.getRoot()), allowStaticMethodAccess, allowStaticFieldAccess);
}
@Inject
@@ -91,9 +91,9 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
}
protected void setRoot(XWorkConverter xworkConverter, CompoundRootAccessor accessor, CompoundRoot compoundRoot,
boolean allowStaticMethodAccess) {
boolean allowStaticMethodAccess, boolean allowStaticFieldAccess) {
this.root = compoundRoot;
this.securityMemberAccess = new SecurityMemberAccess(allowStaticMethodAccess);
this.securityMemberAccess = new SecurityMemberAccess(allowStaticMethodAccess, allowStaticFieldAccess);
this.context = Ognl.createDefaultContext(this.root, securityMemberAccess, accessor, new OgnlTypeConverterWrapper(xworkConverter));
context.put(VALUE_STACK, this);
((OgnlContext) context).setTraceEvaluations(false);
@@ -448,10 +448,11 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
XWorkConverter xworkConverter = cont.getInstance(XWorkConverter.class);
CompoundRootAccessor accessor = (CompoundRootAccessor) cont.getInstance(PropertyAccessor.class, CompoundRoot.class.getName());
TextProvider prov = cont.getInstance(TextProvider.class, "system");
boolean allow = BooleanUtils.toBoolean(cont.getInstance(String.class, StrutsConstants.STRUTS_ALLOW_STATIC_METHOD_ACCESS));
OgnlValueStack aStack = new OgnlValueStack(xworkConverter, accessor, prov, allow);
final boolean allowStaticMethod = BooleanUtils.toBoolean(cont.getInstance(String.class, StrutsConstants.STRUTS_ALLOW_STATIC_METHOD_ACCESS));
final boolean allowStaticField = BooleanUtils.toBoolean(cont.getInstance(String.class, StrutsConstants.STRUTS_ALLOW_STATIC_FIELD_ACCESS));
OgnlValueStack aStack = new OgnlValueStack(xworkConverter, accessor, prov, allowStaticMethod, allowStaticField);
aStack.setOgnlUtil(cont.getInstance(OgnlUtil.class));
aStack.setRoot(xworkConverter, accessor, this.root, allow);
aStack.setRoot(xworkConverter, accessor, this.root, allowStaticMethod, allowStaticField);
return aStack;
}
@@ -37,6 +37,7 @@ import org.apache.logging.log4j.Logger;
import java.util.Map;
import java.util.Set;
import org.apache.struts2.StrutsConstants;
/**
* Creates an Ognl value stack
@@ -49,7 +50,6 @@ public class OgnlValueStackFactory implements ValueStackFactory {
protected CompoundRootAccessor compoundRootAccessor;
protected TextProvider textProvider;
protected Container container;
private boolean allowStaticMethodAccess;
@Inject
protected void setXWorkConverter(XWorkConverter converter) {
@@ -60,21 +60,18 @@ public class OgnlValueStackFactory implements ValueStackFactory {
protected void setTextProvider(TextProvider textProvider) {
this.textProvider = textProvider;
}
@Inject(value="allowStaticMethodAccess", required=false)
protected void setAllowStaticMethodAccess(String allowStaticMethodAccess) {
this.allowStaticMethodAccess = BooleanUtils.toBoolean(allowStaticMethodAccess);
}
public ValueStack createValueStack() {
ValueStack stack = new OgnlValueStack(xworkConverter, compoundRootAccessor, textProvider, allowStaticMethodAccess);
ValueStack stack = new OgnlValueStack(xworkConverter, compoundRootAccessor, textProvider,
containerAllowsStaticMethodAccess(), containerAllowsStaticFieldAccess());
container.inject(stack);
stack.getContext().put(ActionContext.CONTAINER, container);
return stack;
}
public ValueStack createValueStack(ValueStack stack) {
ValueStack result = new OgnlValueStack(stack, xworkConverter, compoundRootAccessor, allowStaticMethodAccess);
ValueStack result = new OgnlValueStack(stack, xworkConverter, compoundRootAccessor,
containerAllowsStaticMethodAccess(), containerAllowsStaticFieldAccess());
container.inject(result);
stack.getContext().put(ActionContext.CONTAINER, container);
return result;
@@ -116,4 +113,23 @@ public class OgnlValueStackFactory implements ValueStackFactory {
}
this.container = container;
}
/**
* Retrieve allowsStaticMethodAccess state from the container (allows for lazy fetching)
*
* @return
*/
protected boolean containerAllowsStaticMethodAccess() {
return BooleanUtils.toBoolean(container.getInstance(String.class, StrutsConstants.STRUTS_ALLOW_STATIC_METHOD_ACCESS));
}
/**
* Retrieve allowStaticFieldAccess state from the container (allows for lazy fetching)
*
* @return
*/
protected boolean containerAllowsStaticFieldAccess() {
return BooleanUtils.toBoolean(container.getInstance(String.class, StrutsConstants.STRUTS_ALLOW_STATIC_FIELD_ACCESS));
}
}
@@ -24,6 +24,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Modifier;
import java.util.Collections;
@@ -40,6 +41,7 @@ public class SecurityMemberAccess implements MemberAccess {
private static final Logger LOG = LogManager.getLogger(SecurityMemberAccess.class);
private final boolean allowStaticFieldAccess;
private final boolean allowStaticMethodAccess;
private Set<Pattern> excludeProperties = Collections.emptySet();
private Set<Pattern> acceptProperties = Collections.emptySet();
@@ -51,18 +53,24 @@ public class SecurityMemberAccess implements MemberAccess {
/**
* SecurityMemberAccess
* - access decisions based on whether member is static (or not)
* - block or allow access to properties (configureable-after-construction)
* - block or allow access to properties (configurable-after-construction)
*
* @param allowStaticMethodAccess
* @param allowStaticFieldAccess
*/
public SecurityMemberAccess(boolean allowStaticMethodAccess) {
public SecurityMemberAccess(boolean allowStaticMethodAccess, boolean allowStaticFieldAccess) {
this.allowStaticMethodAccess = allowStaticMethodAccess;
this.allowStaticFieldAccess = allowStaticFieldAccess;
}
public boolean getAllowStaticMethodAccess() {
public final boolean getAllowStaticMethodAccess() {
return allowStaticMethodAccess;
}
public final boolean getAllowStaticFieldAccess() {
return allowStaticFieldAccess;
}
@Override
public Object setup(Map context, Object target, Member member, String propertyName) {
Object result = null;
@@ -102,11 +110,17 @@ public class SecurityMemberAccess implements MemberAccess {
return true;
}
if (!checkStaticMethodAccess(member)) {
final int memberModifiers = member.getModifiers();
if (!checkStaticMemberAccess(member, memberModifiers)) {
LOG.warn("Access to static [{}] is blocked!", member);
return false;
}
if (!checkPublicMemberAccess(memberModifiers)) {
LOG.trace("Access to non-public [{}] is blocked!", member);
return false;
}
final Class memberClass = member.getDeclaringClass();
if (isClassExcluded(memberClass)) {
@@ -115,7 +129,7 @@ public class SecurityMemberAccess implements MemberAccess {
}
// target can be null in case of accessing static fields, since OGNL 3.2.8
final Class targetClass = Modifier.isStatic(member.getModifiers()) ? memberClass : target.getClass();
final Class targetClass = Modifier.isStatic(memberModifiers) ? memberClass : target.getClass();
if (isPackageExcluded(targetClass.getPackage(), memberClass.getPackage())) {
LOG.warn("Package [{}] of target class [{}] of target [{}] or package [{}] of member [{}] are excluded!", targetClass.getPackage(), targetClass,
@@ -133,22 +147,51 @@ public class SecurityMemberAccess implements MemberAccess {
return false;
}
return Modifier.isPublic(member.getModifiers()) && isAcceptableProperty(propertyName);
return isAcceptableProperty(propertyName);
}
protected boolean checkStaticMethodAccess(Member member) {
final int modifiers = member.getModifiers();
if (Modifier.isStatic(modifiers)) {
if (allowStaticMethodAccess) {
LOG.debug("Support for accessing static methods [member: {}] is deprecated!", member);
/**
* Check access for static members (via modifiers)
*
* Static non-field access result is allowStaticMethodAccess.
* Static field access result is allowStaticFieldAccess.
*
* Note: For non-static members, the result is always true.
*
* @param member
* @param memberModifiers (minor optimization)
*
* @return
*/
protected final boolean checkStaticMemberAccess(Member member, int memberModifiers) {
if (Modifier.isStatic(memberModifiers)) {
if (member instanceof Field) {
return allowStaticFieldAccess;
} else {
if (allowStaticMethodAccess) {
LOG.debug("Support for accessing static methods [member: {}] is deprecated!", member);
}
return allowStaticMethodAccess;
}
return allowStaticMethodAccess;
} else {
return true;
}
}
protected boolean checkEnumAccess(Object target, Member member) {
/**
* Check access for public members (via modifiers)
*
* Returns true if-and-only-if the member is public.
*
* @param memberModifiers
*
* @return
*/
protected final boolean checkPublicMemberAccess(int memberModifiers) {
return Modifier.isPublic(memberModifiers);
}
protected final boolean checkEnumAccess(Object target, Member member) {
if (target instanceof Class) {
final Class clazz = (Class) target;
if (Enum.class.isAssignableFrom(clazz) && member.getName().equals("values")) {
@@ -225,6 +225,9 @@ public final class StrutsConstants {
/** The name of the parameter to create when mapping an id (used by some action mappers) */
public static final String STRUTS_ID_PARAMETER_NAME = "struts.mapper.idParameterName";
/** The name of the parameter to determine whether static field access will be allowed in OGNL expressions or not */
public static final String STRUTS_ALLOW_STATIC_FIELD_ACCESS = "struts.ognl.allowStaticFieldAccess";
/** The name of the parameter to determine whether static method access will be allowed in OGNL expressions or not */
public static final String STRUTS_ALLOW_STATIC_METHOD_ACCESS = "struts.ognl.allowStaticMethodAccess";
@@ -764,7 +764,7 @@ public class ParametersInterceptorTest extends XWorkTestCase {
ValueStack stack = new OgnlValueStack(
container.getInstance(XWorkConverter.class),
(CompoundRootAccessor) container.getInstance(PropertyAccessor.class, CompoundRoot.class.getName()),
container.getInstance(TextProvider.class, "system"), true) {
container.getInstance(TextProvider.class, "system"), true, true) {
@Override
public void setValue(String expr, Object value) {
actual.put(expr, value);
@@ -39,7 +39,16 @@ import java.util.*;
import java.util.regex.Pattern;
public class OgnlUtilTest extends XWorkTestCase {
// Fields for static field access test
public static final String STATIC_FINAL_PUBLIC_ATTRIBUTE = "Static_Final_Public_Attribute";
static final String STATIC_FINAL_PACKAGE_ATTRIBUTE = "Static_Final_Package_Attribute";
protected static final String STATIC_FINAL_PROTECTED_ATTRIBUTE = "Static_Final_Protected_Attribute";
private static final String STATIC_FINAL_PRIVATE_ATTRIBUTE = "Static_Final_Private_Attribute";
public static String STATIC_PUBLIC_ATTRIBUTE = "Static_Public_Attribute";
static String STATIC_PACKAGE_ATTRIBUTE = "Static_Package_Attribute";
protected static String STATIC_PROTECTED_ATTRIBUTE = "Static_Protected_Attribute";
private static String STATIC_PRIVATE_ATTRIBUTE = "Static_Private_Attribute";
private OgnlUtil ognlUtil;
@Override
@@ -1038,6 +1047,127 @@ public class OgnlUtilTest extends XWorkTestCase {
assertTrue("fakepackage4.package not in exclusions?", excludedPackageNames.contains("fakepackage4.package"));
}
/**
* Ensure getValue:
* 1) When allowStaticFieldAccess true - Permits public static field access,
* prevents non-public static field access.
* 2) When allowStaticFieldAccess false - blocks all static field access,
*/
public void testStaticFieldGetValue() {
OgnlContext context = null;
Object accessedValue;
try {
reloadTestContainerConfiguration(true); // Test with allowStaticFieldAccess true
context = (OgnlContext) ognlUtil.createDefaultContext(null);
} catch (Exception ex) {
fail("unable to reload test configuration? Exception: " + ex);
}
try {
accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PUBLIC_ATTRIBUTE", context, null);
assertEquals("accessed field value not equal to actual?", accessedValue, STATIC_FINAL_PUBLIC_ATTRIBUTE);
} catch (Exception ex) {
fail("static final public field access failed ? Exception: " + ex);
}
try {
accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PUBLIC_ATTRIBUTE", context, null);
assertEquals("accessed field value not equal to actual?", accessedValue, STATIC_PUBLIC_ATTRIBUTE);
} catch (Exception ex) {
fail("static public field access failed ? Exception: " + ex);
}
try {
accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PACKAGE_ATTRIBUTE", context, null);
fail("static final package field access succeeded?");
} catch (Exception ex) {
assertTrue("Exception not an OgnlException?", ex instanceof OgnlException);
}
try {
accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PACKAGE_ATTRIBUTE", context, null);
fail("static package field access succeeded?");
} catch (Exception ex) {
assertTrue("Exception not an OgnlException?", ex instanceof OgnlException);
}
try {
accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PROTECTED_ATTRIBUTE", context, null);
fail("static final protected field access succeeded?");
} catch (Exception ex) {
assertTrue("Exception not an OgnlException?", ex instanceof OgnlException);
}
try {
accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PROTECTED_ATTRIBUTE", context, null);
fail("static protected field access succeeded?");
} catch (Exception ex) {
assertTrue("Exception not an OgnlException?", ex instanceof OgnlException);
}
try {
accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PRIVATE_ATTRIBUTE", context, null);
fail("static final private field access succeeded?");
} catch (Exception ex) {
assertTrue("Exception not an OgnlException?", ex instanceof OgnlException);
}
try {
accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PRIVATE_ATTRIBUTE", context, null);
fail("static private field access succeeded?");
} catch (Exception ex) {
assertTrue("Exception not an OgnlException?", ex instanceof OgnlException);
}
try {
reloadTestContainerConfiguration(false); // Re-test with allowStaticFieldAccess false
context = (OgnlContext) ognlUtil.createDefaultContext(null);
} catch (Exception ex) {
fail("unable to reload test configuration? Exception: " + ex);
}
try {
accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PUBLIC_ATTRIBUTE", context, null);
fail("static final public field access succeded ?");
} catch (Exception ex) {
assertTrue("Exception not an OgnlException?", ex instanceof OgnlException);
}
try {
accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PUBLIC_ATTRIBUTE", context, null);
fail("static public field access succeded ?");
} catch (Exception ex) {
assertTrue("Exception not an OgnlException?", ex instanceof OgnlException);
}
try {
accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PACKAGE_ATTRIBUTE", context, null);
fail("static final package field access succeeded?");
} catch (Exception ex) {
assertTrue("Exception not an OgnlException?", ex instanceof OgnlException);
}
try {
accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PACKAGE_ATTRIBUTE", context, null);
fail("static package field access succeeded?");
} catch (Exception ex) {
assertTrue("Exception not an OgnlException?", ex instanceof OgnlException);
}
try {
accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PROTECTED_ATTRIBUTE", context, null);
fail("static final protected field access succeeded?");
} catch (Exception ex) {
assertTrue("Exception not an OgnlException?", ex instanceof OgnlException);
}
try {
accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PROTECTED_ATTRIBUTE", context, null);
fail("static protected field access succeeded?");
} catch (Exception ex) {
assertTrue("Exception not an OgnlException?", ex instanceof OgnlException);
}
try {
accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PRIVATE_ATTRIBUTE", context, null);
fail("static final private field access succeeded?");
} catch (Exception ex) {
assertTrue("Exception not an OgnlException?", ex instanceof OgnlException);
}
try {
accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PRIVATE_ATTRIBUTE", context, null);
fail("static private field access succeeded?");
} catch (Exception ex) {
assertTrue("Exception not an OgnlException?", ex instanceof OgnlException);
}
}
private void internalTestInitialEmptyOgnlUtilExclusions(OgnlUtil ognlUtilParam) throws Exception {
Set<Class<?>> excludedClasses = ognlUtilParam.getExcludedClasses();
assertNotNull("parameter (default) exluded classes null?", excludedClasses);
@@ -1181,17 +1311,17 @@ public class OgnlUtilTest extends XWorkTestCase {
}
}
private void reloadTestContainerConfiguration(boolean devMode, boolean allowStatic) throws Exception {
private void reloadTestContainerConfiguration(boolean devMode, boolean allowStaticMethod) throws Exception {
super.tearDown();
ConfigurationProvider configurationProvider;
if (devMode == true && allowStatic == true) {
if (devMode == true && allowStaticMethod == true) {
configurationProvider = new XmlConfigurationProvider("com/opensymphony/xwork2/config/providers/xwork-test-allowstatic-devmode-true.xml", true);
}
else if (devMode == true && allowStatic == false) {
else if (devMode == true && allowStaticMethod == false) {
configurationProvider = new XmlConfigurationProvider("com/opensymphony/xwork2/config/providers/xwork-test-devmode-true.xml", true);
}
else if (devMode == false && allowStatic == true) {
else if (devMode == false && allowStaticMethod == true) {
configurationProvider = new XmlConfigurationProvider("com/opensymphony/xwork2/config/providers/xwork-test-allowstatic-true.xml", true);
}
else { // devMode, allowStatic both false
@@ -1214,6 +1344,32 @@ public class OgnlUtilTest extends XWorkTestCase {
ognlUtil = container.getInstance(OgnlUtil.class);
}
private void reloadTestContainerConfiguration(boolean allowStaticField) throws Exception {
super.tearDown();
ConfigurationProvider configurationProvider;
if (allowStaticField) {
configurationProvider = new XmlConfigurationProvider("com/opensymphony/xwork2/config/providers/xwork-test-staticfield-true.xml", true);
} else {
configurationProvider = new XmlConfigurationProvider("com/opensymphony/xwork2/config/providers/xwork-test-staticfield-false.xml", true);
}
configurationManager = new ConfigurationManager(Container.DEFAULT_NAME);
configurationManager.addContainerProvider(configurationProvider);
configuration = configurationManager.getConfiguration();
container = configuration.getContainer();
container.inject(configurationProvider);
configurationProvider.init(configuration);
actionProxyFactory = container.getInstance(ActionProxyFactory.class);
// Reset the value stack
ValueStack stack = container.getInstance(ValueStackFactory.class).createValueStack();
stack.getContext().put(ActionContext.CONTAINER, container);
ActionContext.setContext(new ActionContext(stack.getContext()));
ognlUtil = container.getInstance(OgnlUtil.class);
}
public static class Email {
String address;
@@ -56,14 +56,14 @@ public class OgnlValueStackTest extends XWorkTestCase {
}
private OgnlValueStack createValueStack() {
return createValueStack(true);
return createValueStack(true, true);
}
private OgnlValueStack createValueStack(boolean allowStaticMethodAccess) {
private OgnlValueStack createValueStack(boolean allowStaticMethodAccess, boolean allowStaticFieldAccess) {
OgnlValueStack stack = new OgnlValueStack(
container.getInstance(XWorkConverter.class),
(CompoundRootAccessor) container.getInstance(PropertyAccessor.class, CompoundRoot.class.getName()),
container.getInstance(TextProvider.class, "system"), allowStaticMethodAccess);
container.getInstance(TextProvider.class, "system"), allowStaticMethodAccess, allowStaticFieldAccess);
container.inject(stack);
ognlUtil.setAllowStaticMethodAccess(Boolean.toString(allowStaticMethodAccess));
return stack;
@@ -280,7 +280,7 @@ public class OgnlValueStackTest extends XWorkTestCase {
}
public void testStaticMethodDisallow() {
OgnlValueStack vs = createValueStack(false);
OgnlValueStack vs = createValueStack(false, true);
Dog dog = new Dog();
dog.setDeity("fido");
@@ -908,7 +908,7 @@ public class OgnlValueStackTest extends XWorkTestCase {
OgnlValueStack stack2 = new OgnlValueStack(stack,
container.getInstance(XWorkConverter.class),
(CompoundRootAccessor) container.getInstance(PropertyAccessor.class, CompoundRoot.class.getName()), true);
(CompoundRootAccessor) container.getInstance(PropertyAccessor.class, CompoundRoot.class.getName()), true, true);
container.inject(stack2);
assertEquals(stack.getRoot(), stack2.getRoot());
@@ -44,7 +44,7 @@ public class SecurityMemberAccessProxyTest extends XWorkTestCase {
ActionProxy proxy = actionProxyFactory.createActionProxy(null,
"chaintoAOPedTestSubBeanAction", null, context);
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
sma.setDisallowProxyMemberAccess(true);
Member member = proxy.getAction().getClass().getMethod("isExposeProxy");
@@ -57,7 +57,7 @@ public class SecurityMemberAccessProxyTest extends XWorkTestCase {
ActionProxy proxy = actionProxyFactory.createActionProxy(null,
"chaintoAOPedTestSubBeanAction", null, context);
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
Member member = proxy.getAction().getClass().getMethod("isExposeProxy");
@@ -21,7 +21,9 @@ package com.opensymphony.xwork2.ognl;
import com.opensymphony.xwork2.util.TextParseUtil;
import junit.framework.TestCase;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
@@ -43,7 +45,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testWithoutClassExclusion() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
String propertyName = "stringField";
Member member = FooBar.class.getMethod("get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1));
@@ -57,7 +59,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testClassExclusion() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
String propertyName = "stringField";
Member member = FooBar.class.getDeclaredMethod("get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1));
@@ -75,7 +77,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testObjectClassExclusion() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
String propertyName = "toString";
Member member = FooBar.class.getMethod(propertyName);
@@ -89,7 +91,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testObjectOverwrittenMethodsExclusion() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
String propertyName = "hashCode";
Member member = FooBar.class.getMethod(propertyName);
@@ -103,7 +105,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testInterfaceInheritanceExclusion() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
String propertyName = "barLogic";
Member member = BarInterface.class.getMethod(propertyName);
@@ -121,7 +123,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testMiddleOfInheritanceExclusion1() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
String propertyName = "fooLogic";
Member member = FooBar.class.getMethod(propertyName);
@@ -139,7 +141,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testMiddleOfInheritanceExclusion3() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
String propertyName = "barLogic";
Member member = BarInterface.class.getMethod(propertyName);
@@ -153,7 +155,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testMiddleOfInheritanceExclusion4() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
String propertyName = "barLogic";
Member member = BarInterface.class.getMethod(propertyName);
@@ -171,7 +173,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testPackageExclusion() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
Set<Pattern> excluded = new HashSet<>();
excluded.add(Pattern.compile("^" + FooBar.class.getPackage().getName().replaceAll("\\.", "\\\\.") + ".*"));
@@ -189,7 +191,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testPackageNameExclusion() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
Set<String> excluded = new HashSet<>();
excluded.add(FooBar.class.getPackage().getName());
@@ -207,7 +209,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testDefaultPackageExclusion() {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
Set<Pattern> excluded = new HashSet<>();
excluded.add(Pattern.compile("^" + FooBar.class.getPackage().getName().replaceAll("\\.", "\\\\.") + ".*"));
@@ -222,7 +224,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testDefaultPackageExclusion2() {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
Set<Pattern> excluded = new HashSet<>();
excluded.add(Pattern.compile("^$"));
@@ -237,7 +239,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testAccessEnum() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
// when
Member values = MyValues.class.getMethod("values");
@@ -249,7 +251,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testAccessStatic() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
SecurityMemberAccess sma = new SecurityMemberAccess(true, true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class)));
// when
@@ -262,7 +264,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testAccessStaticField() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
SecurityMemberAccess sma = new SecurityMemberAccess(true, true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class)));
// when
@@ -275,7 +277,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testBlockedStaticFieldWhenFlagIsFalse() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class)));
// when
@@ -283,12 +285,96 @@ public class SecurityMemberAccessTest extends TestCase {
boolean actual = sma.isAccessible(context, null, method, null);
// then
assertFalse("Access to static field isn't blocked!", actual);
assertTrue("Access to public static field is blocked?", actual);
// public static final test
// given
sma = new SecurityMemberAccess(false, true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class)));
// when
method = StaticTester.class.getField("MIN_VALUE");
actual = sma.isAccessible(context, null, method, null);
// then
assertTrue("Access to public final static field is blocked?", actual);
// package static test
// given
sma = new SecurityMemberAccess(false, true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class)));
// when
method = StaticTester.getFieldByName("PACKAGE_STRING");
actual = sma.isAccessible(context, null, method, null);
// then
assertFalse("Access to package static field is allowed?", actual);
// package final static test
// given
sma = new SecurityMemberAccess(false, true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class)));
// when
method = StaticTester.getFieldByName("FINAL_PACKAGE_STRING");
actual = sma.isAccessible(context, null, method, null);
// then
assertFalse("Access to package final static field is allowed?", actual);
// protected static test
// given
sma = new SecurityMemberAccess(false, true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class)));
// when
method = StaticTester.getFieldByName("PROTECTED_STRING");
actual = sma.isAccessible(context, null, method, null);
// then
assertFalse("Access to protected static field is allowed?", actual);
// protected final static test
// given
sma = new SecurityMemberAccess(false, true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class)));
// when
method = StaticTester.getFieldByName("FINAL_PROTECTED_STRING");
actual = sma.isAccessible(context, null, method, null);
// then
assertFalse("Access to protected final static field is allowed?", actual);
// private static test
// given
sma = new SecurityMemberAccess(false, true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class)));
// when
method = StaticTester.getFieldByName("PRIVATE_STRING");
actual = sma.isAccessible(context, null, method, null);
// then
assertFalse("Access to private static field is allowed?", actual);
// private final static test
// given
sma = new SecurityMemberAccess(false, true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class)));
// when
method = StaticTester.getFieldByName("FINAL_PRIVATE_STRING");
actual = sma.isAccessible(context, null, method, null);
// then
assertFalse("Access to private final static field is allowed?", actual);
}
public void testBlockedStaticFieldWhenClassIsExcluded() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
SecurityMemberAccess sma = new SecurityMemberAccess(true, true);
sma.setExcludedClasses(new HashSet<>(Arrays.asList(Class.class, StaticTester.class)));
// when
@@ -301,7 +387,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testBlockStaticAccess() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class)));
// when
@@ -314,7 +400,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testBlockStaticAccessIfClassIsExcluded() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class)));
// when
@@ -327,7 +413,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testAllowStaticAccessIfClassIsNotExcluded() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
SecurityMemberAccess sma = new SecurityMemberAccess(true, true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(ClassLoader.class)));
// when
@@ -340,7 +426,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testAccessPrimitiveInt() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
sma.setExcludedPackageNames(TextParseUtil.commaDelimitedStringToSet("java.lang.,ognl,javax"));
String propertyName = "intField";
@@ -355,7 +441,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testAccessPrimitiveDoubleWithNames() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
sma.setExcludedPackageNames(TextParseUtil.commaDelimitedStringToSet("ognl.,javax."));
@@ -407,7 +493,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testAccessPrimitiveDoubleWithPackageRegExs() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
Set<Pattern> patterns = new HashSet<>();
patterns.add(Pattern.compile("^java\\.lang\\..*"));
sma.setExcludedPackageNamePatterns(patterns);
@@ -424,7 +510,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testAccessMemberAccessIsAccessible() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
Set<Class<?>> excluded = new HashSet<>();
excluded.add(ognl.MemberAccess.class);
sma.setExcludedClasses(excluded);
@@ -442,7 +528,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testAccessMemberAccessIsBlocked() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
Set<Class<?>> excluded = new HashSet<>();
excluded.add(SecurityMemberAccess.class);
sma.setExcludedClasses(excluded);
@@ -460,7 +546,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testPackageNameExclusionAsCommaDelimited() {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
sma.setExcludedPackageNames(TextParseUtil.commaDelimitedStringToSet("java.lang."));
@@ -544,9 +630,23 @@ enum MyValues {
class StaticTester {
public static int MAX_VALUE = 0;
public static final int MIN_VALUE = 0;
static String PACKAGE_STRING = "package_string";
static final String FINAL_PACKAGE_STRING = "final_package_string";
static String PROTECTED_STRING = "protected_string";
static final String FINAL_PROTECTED_STRING = "final_protected_string";
static String PRIVATE_STRING = "private_string";
static final String FINAL_PRIVATE_STRING = "final_private_string";
public static String sayHello() {
return "Hello";
}
protected static Field getFieldByName(String fieldName) throws NoSuchFieldException {
if (fieldName != null && fieldName.length() > 0) {
return StaticTester.class.getDeclaredField(fieldName);
} else {
throw new NoSuchFieldException("field: " + fieldName + " does not exist");
}
}
}
@@ -57,7 +57,7 @@ public class SetPropertiesTest extends XWorkTestCase {
}
public void testOgnlUtilEmptyStringAsLong() {
Bar bar = new Bar();
Map context = Ognl.createDefaultContext(bar, new SecurityMemberAccess(false));
Map context = Ognl.createDefaultContext(bar, new SecurityMemberAccess(false, true));
context.put(XWorkConverter.REPORT_CONVERSION_ERRORS, Boolean.TRUE);
bar.setId(null);
@@ -343,7 +343,7 @@ public class ServletRedirectResultTest extends StrutsInternalTestCase implements
ActionConfig actionConfig = new ActionConfig.Builder("", "", "")
.addResultConfigs(results).build();
ActionContext ac = new ActionContext(Ognl.createDefaultContext(null, new SecurityMemberAccess(false)));
ActionContext ac = new ActionContext(Ognl.createDefaultContext(null, new SecurityMemberAccess(false, true)));
ac.put(ServletActionContext.HTTP_REQUEST, requestMock.proxy());
ac.put(ServletActionContext.HTTP_RESPONSE, responseMock.proxy());
MockActionInvocation ai = new MockActionInvocation();
@@ -41,7 +41,7 @@ public class SecurityMemberAccessInServletsTest extends StrutsInternalTestCase {
public void testJavaxServletPackageAccess() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
Set<Pattern> excluded = new HashSet<Pattern>();
excluded.add(Pattern.compile("^(?!javax\\.servlet\\..+)(javax\\..+)"));
@@ -59,7 +59,7 @@ public class SecurityMemberAccessInServletsTest extends StrutsInternalTestCase {
public void testJavaxServletPackageExclusion() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
Set<Pattern> excluded = new HashSet<Pattern>();
excluded.add(Pattern.compile("^javax\\..+"));
@@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
/*
* 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 xwork PUBLIC
"-//Apache Struts//XWork 2.5//EN"
"http://struts.apache.org/dtds/xwork-2.5.dtd"
>
<xwork>
<constant name="struts.devMode" value="false" />
<constant name="struts.i18n.reload" value="false" />
<constant name="struts.ognl.logMissingProperties" value="false" />
<constant name="struts.ognl.enableExpressionCache" value="true" />
<constant name="struts.ognl.enableOGNLEvalExpression" value="false" />
<constant name="struts.configuration.xml.reload" value="false" />
<constant name="struts.ognl.allowStaticFieldAccess" value="false" />
<constant name="struts.ognl.allowStaticMethodAccess" value="false" />
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.dispatcher.errorHandler" value="struts" />
<bean class="com.opensymphony.xwork2.ObjectFactory" name="default" />
<bean class="org.apache.struts2.views.freemarker.FreemarkerThemeTemplateLoader" />
<bean class="org.apache.struts2.views.freemarker.FreemarkerManager" name="default" />
<bean class="org.apache.struts2.views.velocity.VelocityManager" name="default" optional="true" />
<bean class="org.apache.struts2.components.template.TemplateEngineManager" />
<bean class="com.opensymphony.xwork2.conversion.impl.XWorkBasicConverter" />
<bean class="com.opensymphony.xwork2.ognl.OgnlUtil" />
<bean class="org.apache.struts2.views.jsp.ui.OgnlTool" />
<bean type="com.opensymphony.xwork2.ActionProxyFactory" name="default" class="org.apache.struts2.factory.StrutsActionProxyFactory"/>
<bean type="com.opensymphony.xwork2.FileManager" name="system" class="com.opensymphony.xwork2.util.fs.DefaultFileManager" scope="singleton"/>
<bean type="com.opensymphony.xwork2.FileManagerFactory" name="default" class="com.opensymphony.xwork2.util.fs.DefaultFileManagerFactory" scope="singleton"/>
<bean type="com.opensymphony.xwork2.LocalizedTextProvider" name="global-only" class="com.opensymphony.xwork2.util.GlobalLocalizedTextProvider" scope="singleton" />
<bean type="com.opensymphony.xwork2.LocalizedTextProvider" name="default" class="com.opensymphony.xwork2.util.StrutsLocalizedTextProvider" scope="singleton" />
<bean type="com.opensymphony.xwork2.TextProvider" name="system" class="com.opensymphony.xwork2.DefaultTextProvider" scope="singleton" />
<bean type="com.opensymphony.xwork2.conversion.ConversionAnnotationProcessor" name="default" class="com.opensymphony.xwork2.conversion.impl.DefaultConversionAnnotationProcessor" />
<bean type="com.opensymphony.xwork2.conversion.ConversionFileProcessor" name="default" class="com.opensymphony.xwork2.conversion.impl.DefaultConversionFileProcessor" />
<bean type="com.opensymphony.xwork2.conversion.ObjectTypeDeterminer" name="default" class="com.opensymphony.xwork2.conversion.impl.DefaultObjectTypeDeterminer"/>
<bean type="com.opensymphony.xwork2.conversion.TypeConverterCreator" name="default" class="org.apache.struts2.conversion.StrutsTypeConverterCreator" />
<bean type="com.opensymphony.xwork2.conversion.TypeConverterHolder" name="default" class="org.apache.struts2.conversion.StrutsTypeConverterHolder" />
<bean type="com.opensymphony.xwork2.conversion.impl.XWorkConverter" name="default" class="com.opensymphony.xwork2.conversion.impl.XWorkConverter" />
<bean type="com.opensymphony.xwork2.factory.ActionFactory" name="default" class="com.opensymphony.xwork2.factory.DefaultActionFactory" />
<bean type="com.opensymphony.xwork2.factory.ConverterFactory" name="default" class="com.opensymphony.xwork2.factory.StrutsConverterFactory" />
<bean type="com.opensymphony.xwork2.factory.ResultFactory" name="default" class="org.apache.struts2.factory.StrutsResultFactory" />
<bean type="com.opensymphony.xwork2.factory.UnknownHandlerFactory" name="default" class="com.opensymphony.xwork2.factory.DefaultUnknownHandlerFactory" />
<bean type="com.opensymphony.xwork2.factory.ValidatorFactory" name="default" class="com.opensymphony.xwork2.factory.DefaultValidatorFactory" />
<bean type="com.opensymphony.xwork2.factory.InterceptorFactory" name="default" class="com.opensymphony.xwork2.factory.DefaultInterceptorFactory" />
<bean type="com.opensymphony.xwork2.util.ValueStackFactory" name="default" class="com.opensymphony.xwork2.ognl.OgnlValueStackFactory" />
<bean type="com.opensymphony.xwork2.util.reflection.ReflectionProvider" name="default" class="com.opensymphony.xwork2.ognl.OgnlReflectionProvider" />
<bean type="ognl.MethodAccessor" name="java.lang.Object" class="com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor" />
<bean type="ognl.MethodAccessor" name="com.opensymphony.xwork2.util.CompoundRoot" class="com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor" />
<bean type="ognl.PropertyAccessor" name="com.opensymphony.xwork2.util.CompoundRoot" class="com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor" />
<bean type="ognl.PropertyAccessor" name="org.apache.struts2.dispatcher.HttpParameters" class="com.opensymphony.xwork2.ognl.accessor.HttpParametersPropertyAccessor" />
<bean type="ognl.PropertyAccessor" name="com.opensymphony.xwork2.ognl.ObjectProxy" class="com.opensymphony.xwork2.ognl.accessor.ObjectProxyPropertyAccessor" />
<bean type="ognl.PropertyAccessor" name="org.apache.struts2.dispatcher.Parameter" class="com.opensymphony.xwork2.ognl.accessor.ParameterPropertyAccessor" />
<bean type="ognl.PropertyAccessor" name="java.util.ArrayList" class="com.opensymphony.xwork2.ognl.accessor.XWorkListPropertyAccessor" />
<bean type="ognl.PropertyAccessor" name="java.util.Collection" class="com.opensymphony.xwork2.ognl.accessor.XWorkCollectionPropertyAccessor" />
<bean type="ognl.PropertyAccessor" name="java.util.Enumeration" class="com.opensymphony.xwork2.ognl.accessor.XWorkEnumerationAccessor" />
<bean type="ognl.PropertyAccessor" name="java.util.HashMap" class="com.opensymphony.xwork2.ognl.accessor.XWorkMapPropertyAccessor" />
<bean type="ognl.PropertyAccessor" name="java.util.HashSet" class="com.opensymphony.xwork2.ognl.accessor.XWorkCollectionPropertyAccessor" />
<bean type="ognl.PropertyAccessor" name="java.util.Iterator" class="com.opensymphony.xwork2.ognl.accessor.XWorkIteratorPropertyAccessor" />
<bean type="ognl.PropertyAccessor" name="java.util.List" class="com.opensymphony.xwork2.ognl.accessor.XWorkListPropertyAccessor" />
<bean type="ognl.PropertyAccessor" name="java.util.Map" class="com.opensymphony.xwork2.ognl.accessor.XWorkMapPropertyAccessor" />
<bean type="ognl.PropertyAccessor" name="java.lang.Object" class="com.opensymphony.xwork2.ognl.accessor.ObjectAccessor" />
<bean type="ognl.PropertyAccessor" name="java.util.Set" class="com.opensymphony.xwork2.ognl.accessor.XWorkCollectionPropertyAccessor" />
</xwork>
@@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
/*
* 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 xwork PUBLIC
"-//Apache Struts//XWork 2.5//EN"
"http://struts.apache.org/dtds/xwork-2.5.dtd"
>
<xwork>
<constant name="struts.devMode" value="false" />
<constant name="struts.i18n.reload" value="false" />
<constant name="struts.ognl.logMissingProperties" value="false" />
<constant name="struts.ognl.enableExpressionCache" value="true" />
<constant name="struts.ognl.enableOGNLEvalExpression" value="false" />
<constant name="struts.configuration.xml.reload" value="false" />
<constant name="struts.ognl.allowStaticFieldAccess" value="true" />
<constant name="struts.ognl.allowStaticMethodAccess" value="false" />
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.dispatcher.errorHandler" value="struts" />
<bean class="com.opensymphony.xwork2.ObjectFactory" name="default" />
<bean class="org.apache.struts2.views.freemarker.FreemarkerThemeTemplateLoader" />
<bean class="org.apache.struts2.views.freemarker.FreemarkerManager" name="default" />
<bean class="org.apache.struts2.views.velocity.VelocityManager" name="default" optional="true" />
<bean class="org.apache.struts2.components.template.TemplateEngineManager" />
<bean class="com.opensymphony.xwork2.conversion.impl.XWorkBasicConverter" />
<bean class="com.opensymphony.xwork2.ognl.OgnlUtil" />
<bean class="org.apache.struts2.views.jsp.ui.OgnlTool" />
<bean type="com.opensymphony.xwork2.ActionProxyFactory" name="default" class="org.apache.struts2.factory.StrutsActionProxyFactory"/>
<bean type="com.opensymphony.xwork2.FileManager" name="system" class="com.opensymphony.xwork2.util.fs.DefaultFileManager" scope="singleton"/>
<bean type="com.opensymphony.xwork2.FileManagerFactory" name="default" class="com.opensymphony.xwork2.util.fs.DefaultFileManagerFactory" scope="singleton"/>
<bean type="com.opensymphony.xwork2.LocalizedTextProvider" name="global-only" class="com.opensymphony.xwork2.util.GlobalLocalizedTextProvider" scope="singleton" />
<bean type="com.opensymphony.xwork2.LocalizedTextProvider" name="default" class="com.opensymphony.xwork2.util.StrutsLocalizedTextProvider" scope="singleton" />
<bean type="com.opensymphony.xwork2.TextProvider" name="system" class="com.opensymphony.xwork2.DefaultTextProvider" scope="singleton" />
<bean type="com.opensymphony.xwork2.conversion.ConversionAnnotationProcessor" name="default" class="com.opensymphony.xwork2.conversion.impl.DefaultConversionAnnotationProcessor" />
<bean type="com.opensymphony.xwork2.conversion.ConversionFileProcessor" name="default" class="com.opensymphony.xwork2.conversion.impl.DefaultConversionFileProcessor" />
<bean type="com.opensymphony.xwork2.conversion.ObjectTypeDeterminer" name="default" class="com.opensymphony.xwork2.conversion.impl.DefaultObjectTypeDeterminer"/>
<bean type="com.opensymphony.xwork2.conversion.TypeConverterCreator" name="default" class="org.apache.struts2.conversion.StrutsTypeConverterCreator" />
<bean type="com.opensymphony.xwork2.conversion.TypeConverterHolder" name="default" class="org.apache.struts2.conversion.StrutsTypeConverterHolder" />
<bean type="com.opensymphony.xwork2.conversion.impl.XWorkConverter" name="default" class="com.opensymphony.xwork2.conversion.impl.XWorkConverter" />
<bean type="com.opensymphony.xwork2.factory.ActionFactory" name="default" class="com.opensymphony.xwork2.factory.DefaultActionFactory" />
<bean type="com.opensymphony.xwork2.factory.ConverterFactory" name="default" class="com.opensymphony.xwork2.factory.StrutsConverterFactory" />
<bean type="com.opensymphony.xwork2.factory.ResultFactory" name="default" class="org.apache.struts2.factory.StrutsResultFactory" />
<bean type="com.opensymphony.xwork2.factory.UnknownHandlerFactory" name="default" class="com.opensymphony.xwork2.factory.DefaultUnknownHandlerFactory" />
<bean type="com.opensymphony.xwork2.factory.ValidatorFactory" name="default" class="com.opensymphony.xwork2.factory.DefaultValidatorFactory" />
<bean type="com.opensymphony.xwork2.factory.InterceptorFactory" name="default" class="com.opensymphony.xwork2.factory.DefaultInterceptorFactory" />
<bean type="com.opensymphony.xwork2.util.ValueStackFactory" name="default" class="com.opensymphony.xwork2.ognl.OgnlValueStackFactory" />
<bean type="com.opensymphony.xwork2.util.reflection.ReflectionProvider" name="default" class="com.opensymphony.xwork2.ognl.OgnlReflectionProvider" />
<bean type="ognl.MethodAccessor" name="java.lang.Object" class="com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor" />
<bean type="ognl.MethodAccessor" name="com.opensymphony.xwork2.util.CompoundRoot" class="com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor" />
<bean type="ognl.PropertyAccessor" name="com.opensymphony.xwork2.util.CompoundRoot" class="com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor" />
<bean type="ognl.PropertyAccessor" name="org.apache.struts2.dispatcher.HttpParameters" class="com.opensymphony.xwork2.ognl.accessor.HttpParametersPropertyAccessor" />
<bean type="ognl.PropertyAccessor" name="com.opensymphony.xwork2.ognl.ObjectProxy" class="com.opensymphony.xwork2.ognl.accessor.ObjectProxyPropertyAccessor" />
<bean type="ognl.PropertyAccessor" name="org.apache.struts2.dispatcher.Parameter" class="com.opensymphony.xwork2.ognl.accessor.ParameterPropertyAccessor" />
<bean type="ognl.PropertyAccessor" name="java.util.ArrayList" class="com.opensymphony.xwork2.ognl.accessor.XWorkListPropertyAccessor" />
<bean type="ognl.PropertyAccessor" name="java.util.Collection" class="com.opensymphony.xwork2.ognl.accessor.XWorkCollectionPropertyAccessor" />
<bean type="ognl.PropertyAccessor" name="java.util.Enumeration" class="com.opensymphony.xwork2.ognl.accessor.XWorkEnumerationAccessor" />
<bean type="ognl.PropertyAccessor" name="java.util.HashMap" class="com.opensymphony.xwork2.ognl.accessor.XWorkMapPropertyAccessor" />
<bean type="ognl.PropertyAccessor" name="java.util.HashSet" class="com.opensymphony.xwork2.ognl.accessor.XWorkCollectionPropertyAccessor" />
<bean type="ognl.PropertyAccessor" name="java.util.Iterator" class="com.opensymphony.xwork2.ognl.accessor.XWorkIteratorPropertyAccessor" />
<bean type="ognl.PropertyAccessor" name="java.util.List" class="com.opensymphony.xwork2.ognl.accessor.XWorkListPropertyAccessor" />
<bean type="ognl.PropertyAccessor" name="java.util.Map" class="com.opensymphony.xwork2.ognl.accessor.XWorkMapPropertyAccessor" />
<bean type="ognl.PropertyAccessor" name="java.lang.Object" class="com.opensymphony.xwork2.ognl.accessor.ObjectAccessor" />
<bean type="ognl.PropertyAccessor" name="java.util.Set" class="com.opensymphony.xwork2.ognl.accessor.XWorkCollectionPropertyAccessor" />
</xwork>