WW-5326 refactor(ognl): replace Ognl.createDefaultContext with direct StrutsContext construction

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Lukasz Lenart
2026-04-06 18:41:27 +02:00
parent f7923fc704
commit fbb904e9c6
5 changed files with 45 additions and 42 deletions
@@ -29,6 +29,7 @@ import ognl.Ognl;
public class OgnlReflectionContextFactory implements ReflectionContextFactory {
@Override
@SuppressWarnings({"rawtypes", "unchecked"})
public OgnlContext createDefaultContext(Object root) {
return Ognl.createDefaultContext(root);
}
@@ -61,7 +61,7 @@ public class OgnlUtil {
private final OgnlCache<String, Object> expressionCache;
private final OgnlCache<Class<?>, BeanInfo> beanInfoCache;
private TypeConverter defaultConverter;
private TypeConverter<StrutsContext> defaultConverter;
private final OgnlGuard ognlGuard;
private boolean devMode;
@@ -211,14 +211,14 @@ public class OgnlUtil {
* @return an OgnlContext instance
* @since 7.2.0
*/
private OgnlContext ensureOgnlContext(Map<String, Object> context) {
if (context instanceof OgnlContext ognlContext) {
return ognlContext;
private StrutsContext ensureOgnlContext(Map<String, Object> context) {
if (context instanceof StrutsContext strutsContext) {
return strutsContext;
}
// Create a new OgnlContext and copy the Map contents
OgnlContext ognlContext = createDefaultContext(null);
ognlContext.putAll(context);
return ognlContext;
// Create a new StrutsContext and copy the Map contents
StrutsContext strutsContext = createDefaultContext(null);
strutsContext.putAll(context);
return strutsContext;
}
/**
@@ -247,9 +247,9 @@ public class OgnlUtil {
return;
}
OgnlContext ognlContext = ensureOgnlContext(context);
StrutsContext strutsContext = ensureOgnlContext(context);
try {
withRoot(ognlContext, o, () -> {
withRoot(strutsContext, o, () -> {
for (Map.Entry<String, ?> entry : props.entrySet()) {
String expression = entry.getKey();
internalSetProperty(expression, entry.getValue(), o, context, throwPropertyExceptions);
@@ -309,9 +309,9 @@ public class OgnlUtil {
* problems setting the property
*/
public void setProperty(String name, Object value, Object o, Map<String, Object> context, boolean throwPropertyExceptions) {
OgnlContext ognlContext = ensureOgnlContext(context);
StrutsContext strutsContext = ensureOgnlContext(context);
try {
withRoot(ognlContext, o, () -> internalSetProperty(name, value, o, context, throwPropertyExceptions));
withRoot(strutsContext, o, () -> internalSetProperty(name, value, o, context, throwPropertyExceptions));
} catch (OgnlException e) {
// Should never happen as internalSetProperty catches OgnlException
throw new IllegalStateException("Unexpected OgnlException in setProperty", e);
@@ -424,7 +424,7 @@ public class OgnlUtil {
for (TreeValidator validator : treeValidators) {
validator.validate(tree, checkContext);
}
OgnlContext ognlContext = (OgnlContext) context;
StrutsContext ognlContext = (StrutsContext) context;
withRoot(ognlContext, root, () -> Ognl.setValue(tree, ognlContext, root, value));
}
@@ -434,7 +434,7 @@ public class OgnlUtil {
for (TreeValidator validator : treeValidators) {
validator.validate(tree, checkContext);
}
OgnlContext ognlContext = (OgnlContext) context;
StrutsContext ognlContext = (StrutsContext) context;
return withRoot(ognlContext, root, () -> (T) Ognl.getValue(tree, ognlContext, root, resultType));
}
@@ -548,8 +548,8 @@ public class OgnlUtil {
return;
}
final Map<String, Object> contextFrom = createDefaultContext(from);
final Map<String, Object> contextTo = createDefaultContext(to);
final StrutsContext contextFrom = createDefaultContext(from);
final StrutsContext contextTo = createDefaultContext(to);
PropertyDescriptor[] fromPds;
PropertyDescriptor[] toPds;
@@ -654,7 +654,7 @@ public class OgnlUtil {
*/
public Map<String, Object> getBeanMap(final Object source) throws IntrospectionException, OgnlException {
Map<String, Object> beanMap = new HashMap<>();
final Map<String, Object> sourceMap = createDefaultContext(source);
final StrutsContext sourceMap = createDefaultContext(source);
PropertyDescriptor[] propertyDescriptors = getPropertyDescriptors(source);
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
final String propertyName = propertyDescriptor.getDisplayName();
@@ -724,18 +724,21 @@ public class OgnlUtil {
}
}
protected OgnlContext createDefaultContext(Object root) {
protected StrutsContext createDefaultContext(Object root) {
return createDefaultContext(root, null);
}
protected OgnlContext createDefaultContext(Object root, ClassResolver resolver) {
protected StrutsContext createDefaultContext(Object root, ClassResolver<StrutsContext> resolver) {
if (resolver == null) {
resolver = container.getInstance(RootAccessor.class);
if (resolver == null) {
throw new IllegalStateException("Cannot find ClassResolver");
}
}
return Ognl.createDefaultContext(root, container.getInstance(SecurityMemberAccess.class), resolver, defaultConverter);
StrutsContext context = new StrutsContext(
container.getInstance(SecurityMemberAccess.class), resolver, defaultConverter);
context.withRoot(root);
return context;
}
@FunctionalInterface
@@ -762,13 +765,13 @@ public class OgnlUtil {
* @param action the action to execute
* @throws OgnlException if the action throws an OgnlException
*/
private void withRoot(OgnlContext context, Object root, OgnlAction action) throws OgnlException {
Object oldRoot = Ognl.getRoot(context);
private void withRoot(StrutsContext context, Object root, OgnlAction action) throws OgnlException {
Object oldRoot = context.getRoot();
try {
Ognl.setRoot(context, root);
context.withRoot(root);
action.run();
} finally {
Ognl.setRoot(context, oldRoot);
context.withRoot(oldRoot);
}
}
@@ -783,13 +786,13 @@ public class OgnlUtil {
* @return the result of the supplier
* @throws OgnlException if the supplier throws an OgnlException
*/
private <T> T withRoot(OgnlContext context, Object root, OgnlSupplier<T> supplier) throws OgnlException {
Object oldRoot = Ognl.getRoot(context);
private <T> T withRoot(StrutsContext context, Object root, OgnlSupplier<T> supplier) throws OgnlException {
Object oldRoot = context.getRoot();
try {
Ognl.setRoot(context, root);
context.withRoot(root);
return supplier.get();
} finally {
Ognl.setRoot(context, oldRoot);
context.withRoot(oldRoot);
}
}
}
@@ -31,8 +31,6 @@ import org.apache.struts2.util.ValueStack;
import org.apache.struts2.util.reflection.ReflectionContextState;
import ognl.MethodFailedException;
import ognl.NoSuchPropertyException;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.logging.log4j.LogManager;
@@ -68,7 +66,7 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
private static final String MAP_IDENTIFIER_KEY = "org.apache.struts2.util.OgnlValueStack.MAP_IDENTIFIER_KEY";
protected CompoundRoot root;
protected transient Map<String, Object> context;
protected transient StrutsContext context;
protected Class defaultType;
protected Map<Object, Object> overrides;
protected transient OgnlUtil ognlUtil;
@@ -121,12 +119,12 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
protected void setRoot(XWorkConverter xworkConverter, RootAccessor accessor, CompoundRoot compoundRoot, SecurityMemberAccess securityMemberAccess) {
this.root = compoundRoot;
this.securityMemberAccess = securityMemberAccess;
OgnlContext ognlContext = Ognl.createDefaultContext(this.root, securityMemberAccess, accessor, new OgnlTypeConverterWrapper(xworkConverter));
this.context = ognlContext;
this.context = new StrutsContext(securityMemberAccess, accessor, new OgnlTypeConverterWrapper(xworkConverter));
this.context.withRoot(this.root);
this.converter = xworkConverter;
context.put(VALUE_STACK, this);
ognlContext.setTraceEvaluations(false);
ognlContext.setKeepLastEvaluation(false);
context.setTraceEvaluations(false);
context.setKeepLastEvaluation(false);
}
@Inject(StrutsConstants.STRUTS_DEVMODE)
@@ -508,9 +506,7 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
@Override
public void clearContextValues() {
//this is an OGNL ValueStack so the context will be an OgnlContext
//it would be better to make context of type OgnlContext
((OgnlContext) context).getValues().clear();
context.getValues().clear();
}
@Override
@@ -54,6 +54,7 @@ public class OgnlValueStackFactory implements ValueStackFactory {
}
@Inject
@SuppressWarnings({"rawtypes", "unchecked"})
protected void setCompoundRootAccessor(RootAccessor compoundRootAccessor) {
this.compoundRootAccessor = compoundRootAccessor;
OgnlRuntime.setPropertyAccessor(CompoundRoot.class, compoundRootAccessor);
@@ -110,6 +111,7 @@ public class OgnlValueStackFactory implements ValueStackFactory {
* {@link #setMethodAccessor} and can be configured using the extension point
* {@link StrutsConstants#STRUTS_METHOD_ACCESSOR}.
*/
@SuppressWarnings({"rawtypes", "unchecked"})
protected void registerAdditionalMethodAccessors() {
Set<String> names = container.getInstanceNames(MethodAccessor.class);
for (String name : names) {
@@ -145,6 +147,7 @@ public class OgnlValueStackFactory implements ValueStackFactory {
}
}
@SuppressWarnings({"rawtypes", "unchecked"})
protected void registerPropertyAccessors() throws ClassNotFoundException {
Set<String> names = container.getInstanceNames(PropertyAccessor.class);
for (String name : names) {
@@ -52,22 +52,22 @@ public class ObjectProxyPropertyAccessor implements PropertyAccessor<StrutsConte
}
@Override
@SuppressWarnings("unchecked")
@SuppressWarnings({"unchecked", "rawtypes"})
public Object getProperty(StrutsContext context, Object target, Object name) throws OgnlException {
ObjectProxy proxy = (ObjectProxy) target;
setupContext(context, proxy);
return OgnlRuntime.getPropertyAccessor(proxy.getValue().getClass()).getProperty(context, target, name);
return ((PropertyAccessor) OgnlRuntime.getPropertyAccessor(proxy.getValue().getClass())).getProperty(context, target, name);
}
@Override
@SuppressWarnings("unchecked")
@SuppressWarnings({"unchecked", "rawtypes"})
public void setProperty(StrutsContext context, Object target, Object name, Object value) throws OgnlException {
ObjectProxy proxy = (ObjectProxy) target;
setupContext(context, proxy);
OgnlRuntime.getPropertyAccessor(proxy.getValue().getClass()).setProperty(context, target, name, value);
((PropertyAccessor) OgnlRuntime.getPropertyAccessor(proxy.getValue().getClass())).setProperty(context, target, name, value);
}
/**