WW-5326 feat(ognl): introduce StrutsContext extending OgnlContext<StrutsContext>

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Lukasz Lenart
2026-04-06 18:14:29 +02:00
parent 71c204f04b
commit e2e8fa1f33
2 changed files with 107 additions and 0 deletions
@@ -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);
}
}
@@ -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");
}
}