Backport applicable OgnlValueStackTest test fix and unit test additions from 2.6:

- This backport resulted from a review inspired/suggested by Y. Zamani in discussions for PR#334.
- Backports fix of error in testNullMethod().
- Backports applicable static access tests (static method access only), cleanup of unused imports.
- As with 2.6, it uses Y. Zamani's improved/enhanced reload mechanism.
This commit is contained in:
JCgH4164838Gh792C124B5
2019-03-16 17:50:18 -04:00
parent aff4d46835
commit 53f64cdecf
@@ -19,15 +19,16 @@
package com.opensymphony.xwork2.ognl;
import com.opensymphony.xwork2.*;
import com.opensymphony.xwork2.config.ConfigurationManager;
import com.opensymphony.xwork2.config.ConfigurationProvider;
import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider;
import com.opensymphony.xwork2.config.ConfigurationException;
import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.inject.ContainerBuilder;
import com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor;
import com.opensymphony.xwork2.test.StubConfigurationProvider;
import com.opensymphony.xwork2.test.TestBean2;
import com.opensymphony.xwork2.util.*;
import com.opensymphony.xwork2.util.Foo;
import com.opensymphony.xwork2.util.location.LocatableProperties;
import com.opensymphony.xwork2.util.reflection.ReflectionContextState;
import ognl.PropertyAccessor;
@@ -36,6 +37,7 @@ import java.math.BigDecimal;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import org.apache.struts2.StrutsConstants;
/**
@@ -43,10 +45,25 @@ import java.util.Map;
*/
public class OgnlValueStackTest 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";
public static Integer staticNullMethod() {
return null;
}
public static Integer staticInteger100Method() {
return 100;
}
private OgnlUtil ognlUtil;
@Override
@@ -69,6 +86,33 @@ public class OgnlValueStackTest extends XWorkTestCase {
return stack;
}
/**
* @return current OgnlValueStackFactory instance from current container
*/
private OgnlValueStackFactory getValueStackFactory() {
return (OgnlValueStackFactory) container.getInstance(ValueStackFactory.class);
}
/**
* Reloads container and gets a new OgnlValueStackFactory with specified new configuration.
* Intended for testing OgnlValueStack instance(s) that are minimally configured.
* This should help ensure no underlying configuration/injection side-effects are responsible
* for the behaviour of fundamental access control flags).
*
* @param allowStaticMethod new allowStaticMethod configuration
* @return a new OgnlValueStackFactory with specified new configuration
*/
private OgnlValueStackFactory reloadValueStackFactory(Boolean allowStaticMethod) {
try {
reloadTestContainerConfiguration(allowStaticMethod);
}
catch (Exception ex) {
fail("Unable to reload container configuration and configure ognlValueStackFactory - exception: " + ex);
}
return getValueStackFactory();
}
public void testExpOverridesCanStackExpUp() throws Exception {
Map expr1 = new LinkedHashMap();
expr1.put("expr1", "'expr1value'");
@@ -580,7 +624,7 @@ public class OgnlValueStackTest extends XWorkTestCase {
OgnlValueStack stack = createValueStack();
stack.push(dog);
assertNull(stack.findValue("nullMethod()"));
assertNull(stack.findValue("@com.opensymphony.xwork2.util.OgnlValueStackTest@staticNullMethod()"));
assertNull(stack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@staticNullMethod()"));
}
public void testPetSoarBug() {
@@ -972,6 +1016,173 @@ public class OgnlValueStackTest extends XWorkTestCase {
assertEquals(null, stack.findValue("address.country.name", String.class));
}
/**
* Test a default OgnlValueStackFactory and OgnlValueStack generated by it
* when a default configuration is used.
*/
public void testOgnlValueStackFromOgnlValueStackFactoryDefaultConfig() {
OgnlValueStackFactory ognlValueStackFactory = getValueStackFactory();
OgnlValueStack ognlValueStack = (OgnlValueStack) ognlValueStackFactory.createValueStack();
Object accessedValue;
// An OgnlValueStackFactory using a container config with default (from XWorkConfigurationProvider)
// static method access flag value present should prevent staticMethodAccess but allow staticFieldAccess.
assertFalse("OgnlValueStackFactory staticMethodAccess (default flag) not false?", containerAllowsStaticMethodAccess(ognlValueStackFactory.container));
// An OgnlValueStack created from the above OgnlValueStackFactory should allow public field access,
// but prevent non-public field access. It should also deny static method access.
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@staticInteger100Method()");
assertNull("able to access static method (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PUBLIC_ATTRIBUTE");
assertEquals("accessed static final public field value not equal to actual?", accessedValue, STATIC_FINAL_PUBLIC_ATTRIBUTE);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PUBLIC_ATTRIBUTE");
assertEquals("accessed static public field value not equal to actual?", accessedValue, STATIC_PUBLIC_ATTRIBUTE);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PACKAGE_ATTRIBUTE");
assertNull("accessed final package field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PACKAGE_ATTRIBUTE");
assertNull("accessed package field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PROTECTED_ATTRIBUTE");
assertNull("accessed final protected field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PROTECTED_ATTRIBUTE");
assertNull("accessed protected field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PRIVATE_ATTRIBUTE");
assertNull("accessed final private field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PRIVATE_ATTRIBUTE");
assertNull("accessed private field (result not null) ?", accessedValue);
}
/**
* Test a raw OgnlValueStackFactory and OgnlValueStack generated by it
* when no static method access flag is set (not present in configuration).
*/
public void testOgnlValueStackFromOgnlValueStackFactoryNoFlagsSet() {
OgnlValueStackFactory ognlValueStackFactory = reloadValueStackFactory(null);
OgnlValueStack ognlValueStack = (OgnlValueStack) ognlValueStackFactory.createValueStack();
Object accessedValue;
// An OgnlValueStackFactory using a container config with no static method access flag value present
// (such as from a DefaultConfiguration vs. XWorkConfigurationProvider) should
// prevent staticMethodAccess and allow staticFieldAccess.
// Note: Under normal circumstances, explicit static method access configuration flag should be present,
// but this specific check verifies what happens if that configuration flags is not present.
assertFalse("OgnlValueStackFactory staticMethodAccess (no flag present) not false?", containerAllowsStaticMethodAccess(ognlValueStackFactory.container));
// An OgnlValueStack created from the above OgnlValueStackFactory should allow public field access,
// and prevent non-public field access. It should also deny static method access.
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@staticInteger100Method()");
assertNull("able to access static method (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PUBLIC_ATTRIBUTE");
assertEquals("accessed static final public field value not equal to actual?", accessedValue, STATIC_FINAL_PUBLIC_ATTRIBUTE);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PUBLIC_ATTRIBUTE");
assertEquals("accessed static public field value not equal to actual?", accessedValue, STATIC_PUBLIC_ATTRIBUTE);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PACKAGE_ATTRIBUTE");
assertNull("accessed final package field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PACKAGE_ATTRIBUTE");
assertNull("accessed package field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PROTECTED_ATTRIBUTE");
assertNull("accessed final protected field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PROTECTED_ATTRIBUTE");
assertNull("accessed protected field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PRIVATE_ATTRIBUTE");
assertNull("accessed final private field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PRIVATE_ATTRIBUTE");
assertNull("accessed private field (result not null) ?", accessedValue);
}
/**
* Test a raw OgnlValueStackFactory and OgnlValueStack generated by it
* when static method access flag is set to false.
*/
public void testOgnlValueStackFromOgnlValueStackFactoryNoStaticMethodAccess() {
OgnlValueStackFactory ognlValueStackFactory = reloadValueStackFactory(false);
OgnlValueStack ognlValueStack = (OgnlValueStack) ognlValueStackFactory.createValueStack();
Object accessedValue;
// An OgnlValueStackFactory using a container config with static method access flag set false should
// prevent staticMethodAccess and allow staticFieldAccess.
assertFalse("OgnlValueStackFactory staticMethodAccess (set false) not false?", containerAllowsStaticMethodAccess(ognlValueStackFactory.container));
// An OgnlValueStack created from the above OgnlValueStackFactory should allow public field access,
// and prevent non-public field access. It should also deny static method access.
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@staticInteger100Method()");
assertNull("able to access static method (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PUBLIC_ATTRIBUTE");
assertEquals("accessed static final public field value not equal to actual?", accessedValue, STATIC_FINAL_PUBLIC_ATTRIBUTE);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PUBLIC_ATTRIBUTE");
assertEquals("accessed static public field value not equal to actual?", accessedValue, STATIC_PUBLIC_ATTRIBUTE);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PACKAGE_ATTRIBUTE");
assertNull("accessed final package field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PACKAGE_ATTRIBUTE");
assertNull("accessed package field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PROTECTED_ATTRIBUTE");
assertNull("accessed final protected field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PROTECTED_ATTRIBUTE");
assertNull("accessed protected field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PRIVATE_ATTRIBUTE");
assertNull("accessed final private field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PRIVATE_ATTRIBUTE");
assertNull("accessed private field (result not null) ?", accessedValue);
}
/**
* Test a raw OgnlValueStackFactory and OgnlValueStack generated by it
* when static method access flag set to true.
*/
public void testOgnlValueStackFromOgnlValueStackFactoryStaticMethodAccess() {
OgnlValueStackFactory ognlValueStackFactory = reloadValueStackFactory(true);
OgnlValueStack ognlValueStack = (OgnlValueStack) ognlValueStackFactory.createValueStack();
Object accessedValue;
// An OgnlValueStackFactory using a container config with static method access flag set true should
// allow both staticMethodAccess and staticFieldAccess.
assertTrue("OgnlValueStackFactory staticMethodAccess (set true) not true?", containerAllowsStaticMethodAccess(ognlValueStackFactory.container));
// An OgnlValueStack created from the above OgnlValueStackFactory should allow public field access,
// but prevent non-public field access. It should also allow static method access.
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@staticInteger100Method()");
assertNotNull("unable to access static method (result null) ?", accessedValue);
assertEquals("accessed static method result not equal to expected?", accessedValue, staticInteger100Method());
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PUBLIC_ATTRIBUTE");
assertEquals("accessed static final public field value not equal to actual?", accessedValue, STATIC_FINAL_PUBLIC_ATTRIBUTE);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PUBLIC_ATTRIBUTE");
assertEquals("accessed static public field value not equal to actual?", accessedValue, STATIC_PUBLIC_ATTRIBUTE);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PACKAGE_ATTRIBUTE");
assertNull("accessed final package field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PACKAGE_ATTRIBUTE");
assertNull("accessed package field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PROTECTED_ATTRIBUTE");
assertNull("accessed final protected field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PROTECTED_ATTRIBUTE");
assertNull("accessed protected field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PRIVATE_ATTRIBUTE");
assertNull("accessed final private field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PRIVATE_ATTRIBUTE");
assertNull("accessed private field (result not null) ?", accessedValue);
}
protected boolean containerAllowsStaticMethodAccess(Container checkContainer) {
return Boolean.parseBoolean(checkContainer.getInstance(String.class, XWorkConstants.ALLOW_STATIC_METHOD_ACCESS));
}
private void reloadTestContainerConfiguration(final Boolean allowStaticMethod) throws Exception {
loadConfigurationProviders(new StubConfigurationProvider() {
@Override
public void register(ContainerBuilder builder,
LocatableProperties props) throws ConfigurationException {
// null values simulate undefined (by removing).
// undefined values then should be evaluated to false
if (props.containsKey(StrutsConstants.STRUTS_ALLOW_STATIC_METHOD_ACCESS)) {
props.remove(StrutsConstants.STRUTS_ALLOW_STATIC_METHOD_ACCESS);
}
if (props.containsKey(XWorkConstants.ALLOW_STATIC_METHOD_ACCESS)) {
props.remove(XWorkConstants.ALLOW_STATIC_METHOD_ACCESS);
}
if (allowStaticMethod != null) {
props.setProperty(StrutsConstants.STRUTS_ALLOW_STATIC_METHOD_ACCESS, "" + allowStaticMethod);
props.setProperty(XWorkConstants.ALLOW_STATIC_METHOD_ACCESS, "" + allowStaticMethod);
}
}
});
ognlUtil = container.getInstance(OgnlUtil.class);
}
class BadJavaBean {
private int count;
private int count2;