This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch feat/ognl-3.5-upgrade
in repository https://gitbox.apache.org/repos/asf/struts.git

commit fbb904e9c656cc71beaca17e04d8d325f5ef30ed
Author: Lukasz Lenart <[email protected]>
AuthorDate: Mon Apr 6 18:41:27 2026 +0200

    WW-5326 refactor(ognl): replace Ognl.createDefaultContext with direct 
StrutsContext construction
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
---
 .../struts2/ognl/OgnlReflectionContextFactory.java |  1 +
 .../java/org/apache/struts2/ognl/OgnlUtil.java     | 59 ++++++++++++----------
 .../org/apache/struts2/ognl/OgnlValueStack.java    | 16 +++---
 .../apache/struts2/ognl/OgnlValueStackFactory.java |  3 ++
 .../ognl/accessor/ObjectProxyPropertyAccessor.java |  8 +--
 5 files changed, 45 insertions(+), 42 deletions(-)

diff --git 
a/core/src/main/java/org/apache/struts2/ognl/OgnlReflectionContextFactory.java 
b/core/src/main/java/org/apache/struts2/ognl/OgnlReflectionContextFactory.java
index 62dab60a3..ed79b2fbf 100644
--- 
a/core/src/main/java/org/apache/struts2/ognl/OgnlReflectionContextFactory.java
+++ 
b/core/src/main/java/org/apache/struts2/ognl/OgnlReflectionContextFactory.java
@@ -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);
     }
diff --git a/core/src/main/java/org/apache/struts2/ognl/OgnlUtil.java 
b/core/src/main/java/org/apache/struts2/ognl/OgnlUtil.java
index f9e484202..cec398f0b 100644
--- a/core/src/main/java/org/apache/struts2/ognl/OgnlUtil.java
+++ b/core/src/main/java/org/apache/struts2/ognl/OgnlUtil.java
@@ -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);
         }
     }
 }
diff --git a/core/src/main/java/org/apache/struts2/ognl/OgnlValueStack.java 
b/core/src/main/java/org/apache/struts2/ognl/OgnlValueStack.java
index 2376a418f..fc8a9d33f 100644
--- a/core/src/main/java/org/apache/struts2/ognl/OgnlValueStack.java
+++ b/core/src/main/java/org/apache/struts2/ognl/OgnlValueStack.java
@@ -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
diff --git 
a/core/src/main/java/org/apache/struts2/ognl/OgnlValueStackFactory.java 
b/core/src/main/java/org/apache/struts2/ognl/OgnlValueStackFactory.java
index ac60de0dc..eb9f39749 100644
--- a/core/src/main/java/org/apache/struts2/ognl/OgnlValueStackFactory.java
+++ b/core/src/main/java/org/apache/struts2/ognl/OgnlValueStackFactory.java
@@ -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) {
diff --git 
a/core/src/main/java/org/apache/struts2/ognl/accessor/ObjectProxyPropertyAccessor.java
 
b/core/src/main/java/org/apache/struts2/ognl/accessor/ObjectProxyPropertyAccessor.java
index 4f0230426..3120588a6 100644
--- 
a/core/src/main/java/org/apache/struts2/ognl/accessor/ObjectProxyPropertyAccessor.java
+++ 
b/core/src/main/java/org/apache/struts2/ognl/accessor/ObjectProxyPropertyAccessor.java
@@ -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);
     }
 
     /**

Reply via email to