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 e2e8fa1f332c11ec4de357561c025cb771d8974e
Author: Lukasz Lenart <[email protected]>
AuthorDate: Mon Apr 6 18:14:29 2026 +0200

    WW-5326 feat(ognl): introduce StrutsContext extending 
OgnlContext<StrutsContext>
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
---
 .../org/apache/struts2/ognl/StrutsContext.java     | 53 +++++++++++++++++++++
 .../org/apache/struts2/ognl/StrutsContextTest.java | 54 ++++++++++++++++++++++
 2 files changed, 107 insertions(+)

diff --git a/core/src/main/java/org/apache/struts2/ognl/StrutsContext.java 
b/core/src/main/java/org/apache/struts2/ognl/StrutsContext.java
new file mode 100644
index 000000000..e2b7b4b93
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/ognl/StrutsContext.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+package org.apache.struts2.ognl;
+
+import ognl.ClassResolver;
+import ognl.MemberAccess;
+import ognl.OgnlContext;
+import ognl.TypeConverter;
+
+/**
+ * Struts-specific OGNL evaluation context. Extends {@link OgnlContext} with 
the
+ * self-bounded generic parameter to enable type-safe access in all OGNL 
interface
+ * implementations ({@link MemberAccess}, {@link ognl.PropertyAccessor}, etc.).
+ *
+ * <p>Phase 1: minimal subclass delegating to super constructors.
+ * Future phases will promote stringly-typed map entries (e.g. {@code 
DENY_METHOD_EXECUTION},
+ * {@code CREATE_NULL_OBJECTS}) to proper typed fields.</p>
+ *
+ * @since 7.2.0
+ */
+public class StrutsContext extends OgnlContext<StrutsContext> {
+
+    public StrutsContext(MemberAccess<StrutsContext> memberAccess) {
+        super(memberAccess);
+    }
+
+    public StrutsContext(MemberAccess<StrutsContext> memberAccess,
+                         ClassResolver<StrutsContext> classResolver) {
+        super(memberAccess, classResolver);
+    }
+
+    public StrutsContext(MemberAccess<StrutsContext> memberAccess,
+                         ClassResolver<StrutsContext> classResolver,
+                         TypeConverter<StrutsContext> typeConverter) {
+        super(memberAccess, classResolver, typeConverter);
+    }
+}
diff --git a/core/src/test/java/org/apache/struts2/ognl/StrutsContextTest.java 
b/core/src/test/java/org/apache/struts2/ognl/StrutsContextTest.java
new file mode 100644
index 000000000..be0a07305
--- /dev/null
+++ b/core/src/test/java/org/apache/struts2/ognl/StrutsContextTest.java
@@ -0,0 +1,54 @@
+package org.apache.struts2.ognl;
+
+import ognl.ClassResolver;
+import ognl.MemberAccess;
+import ognl.TypeConverter;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+@SuppressWarnings("unchecked")
+class StrutsContextTest {
+
+    @Test
+    void shouldCreateContextWithRequiredMemberAccess() {
+        MemberAccess<StrutsContext> memberAccess = mock(MemberAccess.class);
+        var context = new StrutsContext(memberAccess);
+
+        assertThat(context).isNotNull();
+        assertThat(context.getMemberAccess()).isSameAs(memberAccess);
+    }
+
+    @Test
+    void shouldCreateContextWithAllComponents() {
+        MemberAccess<StrutsContext> memberAccess = mock(MemberAccess.class);
+        ClassResolver<StrutsContext> classResolver = mock(ClassResolver.class);
+        TypeConverter<StrutsContext> typeConverter = mock(TypeConverter.class);
+
+        var context = new StrutsContext(memberAccess, classResolver, 
typeConverter);
+
+        assertThat(context.getMemberAccess()).isSameAs(memberAccess);
+        assertThat(context.getClassResolver()).isSameAs(classResolver);
+        assertThat(context.getTypeConverter()).isSameAs(typeConverter);
+    }
+
+    @Test
+    void shouldSupportRootObject() {
+        MemberAccess<StrutsContext> memberAccess = mock(MemberAccess.class);
+        var root = new Object();
+        var context = new StrutsContext(memberAccess);
+        context.withRoot(root);
+
+        assertThat(context.getRoot()).isSameAs(root);
+    }
+
+    @Test
+    void shouldImplementMapInterface() {
+        MemberAccess<StrutsContext> memberAccess = mock(MemberAccess.class);
+        var context = new StrutsContext(memberAccess);
+
+        context.put("testKey", "testValue");
+        assertThat(context.get("testKey")).isEqualTo("testValue");
+    }
+}

Reply via email to