Compare commits

...

10 Commits

Author SHA1 Message Date
Lukasz Lenart b039dc5079 WW-5326 fix(rat): adjust exclude patterns for RAT and adds missing header with license 2026-04-07 07:38:42 +02:00
Lukasz Lenart 6374e31384 WW-5326 fix(tiles): use raw OgnlContext in tiles accessors
Tiles accessors are called by OGNL internal machinery with raw OgnlContext,
not within a Struts evaluation context, so they cannot use StrutsContext.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 19:27:16 +02:00
Lukasz Lenart 803b5cbbd0 WW-5326 docs: add Jira reference to spec and plan
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 19:18:21 +02:00
Lukasz Lenart 1dda92ed23 WW-5326 test(ognl): update tests for StrutsContext migration
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 19:17:10 +02:00
Lukasz Lenart cda38c79db WW-5326 refactor(tiles): parameterize tiles OGNL accessors with StrutsContext
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 19:01:25 +02:00
Lukasz Lenart fbb904e9c6 WW-5326 refactor(ognl): replace Ognl.createDefaultContext with direct StrutsContext construction
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 18:41:27 +02:00
Lukasz Lenart f7923fc704 WW-5326 refactor(ognl): parameterize all accessor implementations with StrutsContext
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 18:31:58 +02:00
Lukasz Lenart 47718f5a8a WW-5326 refactor(ognl): parameterize core interfaces with StrutsContext
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 18:19:55 +02:00
Lukasz Lenart e2e8fa1f33 WW-5326 feat(ognl): introduce StrutsContext extending OgnlContext<StrutsContext>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 18:14:29 +02:00
Lukasz Lenart 71c204f04b WW-5326 build(deps): bump OGNL from 3.4.10 to 3.5.0-BETA4
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 18:10:50 +02:00
38 changed files with 1850 additions and 152 deletions
@@ -18,10 +18,9 @@
*/
package org.apache.struts2.ognl;
import ognl.OgnlContext;
import org.apache.struts2.conversion.NullHandler;
public class OgnlNullHandlerWrapper implements ognl.NullHandler {
public class OgnlNullHandlerWrapper implements ognl.NullHandler<StrutsContext> {
private final NullHandler wrapped;
@@ -30,13 +29,13 @@ public class OgnlNullHandlerWrapper implements ognl.NullHandler {
}
@Override
public Object nullMethodResult(OgnlContext context, Object target,
public Object nullMethodResult(StrutsContext context, Object target,
String methodName, Object[] args) {
return wrapped.nullMethodResult(context, target, methodName, args);
}
@Override
public Object nullPropertyValue(OgnlContext context, Object target, Object property) {
public Object nullPropertyValue(StrutsContext context, Object target, Object property) {
return wrapped.nullPropertyValue(context, target, property);
}
@@ -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);
}
@@ -18,7 +18,6 @@
*/
package org.apache.struts2.ognl;
import ognl.OgnlContext;
import org.apache.struts2.conversion.TypeConverter;
import java.lang.reflect.Member;
@@ -26,7 +25,7 @@ import java.lang.reflect.Member;
/**
* Wraps an XWork type conversion class for as an OGNL TypeConverter
*/
public class OgnlTypeConverterWrapper implements ognl.TypeConverter {
public class OgnlTypeConverterWrapper implements ognl.TypeConverter<StrutsContext> {
private final TypeConverter typeConverter;
@@ -38,7 +37,7 @@ public class OgnlTypeConverterWrapper implements ognl.TypeConverter {
}
@Override
public Object convertValue(OgnlContext context, Object target, Member member, String propertyName, Object value, Class<?> toType) {
public Object convertValue(StrutsContext context, Object target, Member member, String propertyName, Object value, Class<?> toType) {
return typeConverter.convertValue(context, target, member, propertyName, value, toType);
}
@@ -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) {
@@ -19,7 +19,6 @@
package org.apache.struts2.ognl;
import ognl.MemberAccess;
import ognl.OgnlContext;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -54,7 +53,7 @@ import static org.apache.struts2.util.DebugUtils.logWarningForFirstOccurrence;
* Allows access decisions to be made on the basis of whether a member is static or not.
* Also blocks or allows access to properties.
*/
public class SecurityMemberAccess implements MemberAccess {
public class SecurityMemberAccess implements MemberAccess<StrutsContext> {
private static final Logger LOG = LogManager.getLogger(SecurityMemberAccess.class);
@@ -115,7 +114,7 @@ public class SecurityMemberAccess implements MemberAccess {
}
@Override
public Object setup(OgnlContext context, Object target, Member member, String propertyName) {
public Object setup(StrutsContext context, Object target, Member member, String propertyName) {
Object result = null;
if (isAccessible(context, target, member, propertyName)) {
@@ -130,7 +129,7 @@ public class SecurityMemberAccess implements MemberAccess {
}
@Override
public void restore(OgnlContext context, Object target, Member member, String propertyName, Object state) {
public void restore(StrutsContext context, Object target, Member member, String propertyName, Object state) {
if (state == null) {
return;
}
@@ -145,7 +144,7 @@ public class SecurityMemberAccess implements MemberAccess {
}
@Override
public boolean isAccessible(OgnlContext context, Object target, Member member, String propertyName) {
public boolean isAccessible(StrutsContext context, Object target, Member member, String propertyName) {
LOG.debug("Checking access for [target: {}, member: {}, property: {}]", target, member, propertyName);
if (member == null) {
@@ -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);
}
}
@@ -18,7 +18,6 @@
*/
package org.apache.struts2.ognl;
import ognl.OgnlContext;
import org.apache.struts2.conversion.TypeConverter;
import java.lang.reflect.Member;
@@ -29,19 +28,19 @@ import java.util.Map;
*/
public class XWorkTypeConverterWrapper implements TypeConverter {
private final ognl.TypeConverter typeConverter;
private final ognl.TypeConverter<StrutsContext> typeConverter;
public XWorkTypeConverterWrapper(ognl.TypeConverter conv) {
public XWorkTypeConverterWrapper(ognl.TypeConverter<StrutsContext> conv) {
this.typeConverter = conv;
}
@Override
public Object convertValue(Map context, Object target, Member member, String propertyName, Object value, Class toType) {
// Cast context to OgnlContext for OGNL 3.4.8+ compatibility
OgnlContext ognlContext = (context instanceof OgnlContext oc) ? oc : null;
if (ognlContext == null) {
throw new IllegalArgumentException("Context must be an OgnlContext for OGNL 3.4.8+");
// Cast context to StrutsContext for OGNL 3.5.x compatibility
StrutsContext strutsContext = (context instanceof StrutsContext sc) ? sc : null;
if (strutsContext == null) {
throw new IllegalArgumentException("Context must be a StrutsContext for OGNL 3.5.x+");
}
return typeConverter.convertValue(ognlContext, target, member, propertyName, value, toType);
return typeConverter.convertValue(strutsContext, target, member, propertyName, value, toType);
}
}
@@ -26,7 +26,6 @@ import org.apache.struts2.util.ValueStack;
import ognl.MethodFailedException;
import ognl.NoSuchPropertyException;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
import ognl.OgnlRuntime;
import org.apache.commons.lang3.BooleanUtils;
@@ -34,6 +33,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.StrutsException;
import org.apache.struts2.ognl.StrutsContext;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
@@ -64,7 +64,7 @@ public class CompoundRootAccessor implements RootAccessor, InternalDestroyable {
* Used by OGNl to generate bytecode
*/
@Override
public String getSourceAccessor(OgnlContext context, Object target, Object index) {
public String getSourceAccessor(StrutsContext context, Object target, Object index) {
return null;
}
@@ -72,7 +72,7 @@ public class CompoundRootAccessor implements RootAccessor, InternalDestroyable {
* Used by OGNl to generate bytecode
*/
@Override
public String getSourceSetter(OgnlContext context, Object target, Object index) {
public String getSourceSetter(StrutsContext context, Object target, Object index) {
return null;
}
@@ -96,7 +96,7 @@ public class CompoundRootAccessor implements RootAccessor, InternalDestroyable {
}
@Override
public void setProperty(OgnlContext context, Object target, Object name, Object value) throws OgnlException {
public void setProperty(StrutsContext context, Object target, Object name, Object value) throws OgnlException {
CompoundRoot root = (CompoundRoot) target;
for (Object o : root) {
@@ -138,7 +138,7 @@ public class CompoundRootAccessor implements RootAccessor, InternalDestroyable {
}
@Override
public Object getProperty(OgnlContext context, Object target, Object name) throws OgnlException {
public Object getProperty(StrutsContext context, Object target, Object name) throws OgnlException {
CompoundRoot root = (CompoundRoot) target;
if (name instanceof Integer index) {
@@ -182,7 +182,7 @@ public class CompoundRootAccessor implements RootAccessor, InternalDestroyable {
}
@Override
public Object callMethod(OgnlContext context, Object target, String name, Object[] objects) throws MethodFailedException {
public Object callMethod(StrutsContext context, Object target, String name, Object[] objects) throws MethodFailedException {
CompoundRoot root = (CompoundRoot) target;
if ("describe".equals(name)) {
@@ -270,12 +270,12 @@ public class CompoundRootAccessor implements RootAccessor, InternalDestroyable {
}
@Override
public Object callStaticMethod(OgnlContext transientVars, Class aClass, String s, Object[] objects) throws MethodFailedException {
public Object callStaticMethod(StrutsContext transientVars, Class aClass, String s, Object[] objects) throws MethodFailedException {
return null;
}
@Override
public Class classForName(String className, OgnlContext context) throws ClassNotFoundException {
public Class classForName(String className, StrutsContext context) throws ClassNotFoundException {
Object root = Ognl.getRoot(context);
if (disallowCustomOgnlMap) {
@@ -19,20 +19,20 @@
package org.apache.struts2.ognl.accessor;
import ognl.ObjectPropertyAccessor;
import ognl.OgnlContext;
import ognl.OgnlException;
import org.apache.struts2.dispatcher.HttpParameters;
import org.apache.struts2.ognl.StrutsContext;
public class HttpParametersPropertyAccessor extends ObjectPropertyAccessor {
public class HttpParametersPropertyAccessor extends ObjectPropertyAccessor<StrutsContext> {
@Override
public Object getProperty(OgnlContext context, Object target, Object oname) throws OgnlException {
public Object getProperty(StrutsContext context, Object target, Object oname) throws OgnlException {
HttpParameters parameters = (HttpParameters) target;
return parameters.get(String.valueOf(oname)).getObject();
}
@Override
public void setProperty(OgnlContext context, Object target, Object oname, Object value) throws OgnlException {
public void setProperty(StrutsContext context, Object target, Object oname, Object value) throws OgnlException {
throw new OgnlException("Access to " + target.getClass().getName() + " is read-only!");
}
}
@@ -21,12 +21,12 @@ package org.apache.struts2.ognl.accessor;
import org.apache.struts2.conversion.impl.XWorkConverter;
import org.apache.struts2.util.reflection.ReflectionContextState;
import ognl.ObjectPropertyAccessor;
import ognl.OgnlContext;
import ognl.OgnlException;
import org.apache.struts2.ognl.StrutsContext;
public class ObjectAccessor extends ObjectPropertyAccessor {
public class ObjectAccessor extends ObjectPropertyAccessor<StrutsContext> {
@Override
public Object getProperty(OgnlContext map, Object o, Object o1) throws OgnlException {
public Object getProperty(StrutsContext map, Object o, Object o1) throws OgnlException {
Object obj = super.getProperty(map, o, o1);
map.put(XWorkConverter.LAST_BEAN_CLASS_ACCESSED, o.getClass());
@@ -20,10 +20,10 @@ package org.apache.struts2.ognl.accessor;
import org.apache.struts2.ognl.ObjectProxy;
import org.apache.struts2.util.reflection.ReflectionContextState;
import ognl.OgnlContext;
import ognl.OgnlException;
import ognl.OgnlRuntime;
import ognl.PropertyAccessor;
import org.apache.struts2.ognl.StrutsContext;
/**
* Is able to access (set/get) properties on a given object.
@@ -33,13 +33,13 @@ import ognl.PropertyAccessor;
*
* @author Gabe
*/
public class ObjectProxyPropertyAccessor implements PropertyAccessor {
public class ObjectProxyPropertyAccessor implements PropertyAccessor<StrutsContext> {
/**
* Used by OGNl to generate bytecode
*/
@Override
public String getSourceAccessor(OgnlContext context, Object target, Object index) {
public String getSourceAccessor(StrutsContext context, Object target, Object index) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@@ -47,25 +47,27 @@ public class ObjectProxyPropertyAccessor implements PropertyAccessor {
* Used by OGNl to generate bytecode
*/
@Override
public String getSourceSetter(OgnlContext context, Object target, Object index) {
public String getSourceSetter(StrutsContext context, Object target, Object index) {
return null;
}
@Override
public Object getProperty(OgnlContext context, Object target, Object name) throws OgnlException {
@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
public void setProperty(OgnlContext context, Object target, Object name, Object value) throws OgnlException {
@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);
}
/**
@@ -75,7 +77,7 @@ public class ObjectProxyPropertyAccessor implements PropertyAccessor {
* @param context
* @param proxy
*/
private void setupContext(OgnlContext context, ObjectProxy proxy) {
private void setupContext(StrutsContext context, ObjectProxy proxy) {
ReflectionContextState.setLastBeanClassAccessed(context, proxy.getLastClassAccessed());
ReflectionContextState.setLastBeanPropertyAccessed(context, proxy.getLastPropertyAccessed());
}
@@ -19,14 +19,14 @@
package org.apache.struts2.ognl.accessor;
import ognl.ObjectPropertyAccessor;
import ognl.OgnlContext;
import ognl.OgnlException;
import org.apache.struts2.dispatcher.Parameter;
import org.apache.struts2.ognl.StrutsContext;
public class ParameterPropertyAccessor extends ObjectPropertyAccessor {
public class ParameterPropertyAccessor extends ObjectPropertyAccessor<StrutsContext> {
@Override
public Object getProperty(OgnlContext context, Object target, Object oname) throws OgnlException {
public Object getProperty(StrutsContext context, Object target, Object oname) throws OgnlException {
if (target instanceof Parameter parameter) {
if ("value".equalsIgnoreCase(String.valueOf(oname))) {
throw new OgnlException("Access to " + oname + " is not allowed! Call parameter name directly!");
@@ -37,7 +37,7 @@ public class ParameterPropertyAccessor extends ObjectPropertyAccessor {
}
@Override
public void setProperty(OgnlContext context, Object target, Object oname, Object value) throws OgnlException {
public void setProperty(StrutsContext context, Object target, Object oname, Object value) throws OgnlException {
if (target instanceof Parameter) {
throw new OgnlException("Access to " + target.getClass().getName() + " is read-only!");
} else {
@@ -21,9 +21,10 @@ package org.apache.struts2.ognl.accessor;
import ognl.ClassResolver;
import ognl.MethodAccessor;
import ognl.PropertyAccessor;
import org.apache.struts2.ognl.StrutsContext;
/**
* @since 6.4.0
*/
public interface RootAccessor extends PropertyAccessor, MethodAccessor, ClassResolver {
public interface RootAccessor extends PropertyAccessor<StrutsContext>, MethodAccessor<StrutsContext>, ClassResolver<StrutsContext> {
}
@@ -25,10 +25,10 @@ import org.apache.struts2.inject.Inject;
import org.apache.struts2.ognl.OgnlUtil;
import org.apache.struts2.util.reflection.ReflectionContextState;
import ognl.ObjectPropertyAccessor;
import ognl.OgnlContext;
import ognl.OgnlException;
import ognl.OgnlRuntime;
import ognl.SetPropertyAccessor;
import org.apache.struts2.ognl.StrutsContext;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -40,7 +40,7 @@ import java.util.Map;
/**
* @author Gabe
*/
public class XWorkCollectionPropertyAccessor extends SetPropertyAccessor {
public class XWorkCollectionPropertyAccessor extends SetPropertyAccessor<StrutsContext> {
private static final Logger LOG = LogManager.getLogger(XWorkCollectionPropertyAccessor.class);
@@ -87,7 +87,7 @@ public class XWorkCollectionPropertyAccessor extends SetPropertyAccessor {
* @see ognl.PropertyAccessor#getProperty(java.util.Map, Object, Object)
*/
@Override
public Object getProperty(OgnlContext context, Object target, Object key) throws OgnlException {
public Object getProperty(StrutsContext context, Object target, Object key) throws OgnlException {
LOG.trace("Entering getProperty()");
//check if it is a generic type property.
@@ -186,7 +186,7 @@ public class XWorkCollectionPropertyAccessor extends SetPropertyAccessor {
* Gets an indexed Map by a given key property with the key being
* the value of the property and the value being the
*/
private Map getSetMap(OgnlContext context, Collection collection, String property) throws OgnlException {
private Map getSetMap(StrutsContext context, Collection collection, String property) throws OgnlException {
LOG.trace("getting set Map");
String path = ReflectionContextState.getCurrentPropertyPath(context);
@@ -211,7 +211,7 @@ public class XWorkCollectionPropertyAccessor extends SetPropertyAccessor {
/*
* gets a bean with the given
*/
public Object getPropertyThroughIteration(OgnlContext context, Collection collection, String property, Object key)
public Object getPropertyThroughIteration(StrutsContext context, Collection collection, String property, Object key)
throws OgnlException {
//TODO
for (Object currTest : collection) {
@@ -224,7 +224,7 @@ public class XWorkCollectionPropertyAccessor extends SetPropertyAccessor {
}
@Override
public void setProperty(OgnlContext context, Object target, Object name, Object value) throws OgnlException {
public void setProperty(StrutsContext context, Object target, Object name, Object value) throws OgnlException {
Class lastClass = (Class) context.get(XWorkConverter.LAST_BEAN_CLASS_ACCESSED);
String lastProperty = (String) context.get(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED);
Class convertToClass = objectTypeDeterminer.getElementClass(lastClass, lastProperty, name);
@@ -256,7 +256,7 @@ public class XWorkCollectionPropertyAccessor extends SetPropertyAccessor {
super.setProperty(context, target, name, realValue);
}
private Object getRealValue(OgnlContext context, Object value, Class convertToClass) {
private Object getRealValue(StrutsContext context, Object value, Class convertToClass) {
if (value == null || convertToClass == null) {
return value;
}
@@ -20,15 +20,15 @@ package org.apache.struts2.ognl.accessor;
import ognl.EnumerationPropertyAccessor;
import ognl.ObjectPropertyAccessor;
import ognl.OgnlContext;
import ognl.OgnlException;
import org.apache.struts2.ognl.StrutsContext;
public class XWorkEnumerationAccessor extends EnumerationPropertyAccessor {
public class XWorkEnumerationAccessor extends EnumerationPropertyAccessor<StrutsContext> {
private final ObjectPropertyAccessor opa = new ObjectPropertyAccessor();
private final ObjectPropertyAccessor<StrutsContext> opa = new ObjectPropertyAccessor<>();
@Override
public void setProperty(OgnlContext context, Object target, Object name, Object value) throws OgnlException {
public void setProperty(StrutsContext context, Object target, Object name, Object value) throws OgnlException {
opa.setProperty(context, target, name, value);
}
}
@@ -20,15 +20,15 @@ package org.apache.struts2.ognl.accessor;
import ognl.IteratorPropertyAccessor;
import ognl.ObjectPropertyAccessor;
import ognl.OgnlContext;
import ognl.OgnlException;
import org.apache.struts2.ognl.StrutsContext;
public class XWorkIteratorPropertyAccessor extends IteratorPropertyAccessor {
public class XWorkIteratorPropertyAccessor extends IteratorPropertyAccessor<StrutsContext> {
private final ObjectPropertyAccessor opa = new ObjectPropertyAccessor();
private final ObjectPropertyAccessor<StrutsContext> opa = new ObjectPropertyAccessor<>();
@Override
public void setProperty(OgnlContext context, Object target, Object name, Object value) throws OgnlException {
public void setProperty(StrutsContext context, Object target, Object name, Object value) throws OgnlException {
opa.setProperty(context, target, name, value);
}
}
@@ -25,9 +25,9 @@ import org.apache.struts2.inject.Inject;
import org.apache.struts2.ognl.OgnlUtil;
import org.apache.struts2.util.reflection.ReflectionContextState;
import ognl.ListPropertyAccessor;
import ognl.OgnlContext;
import ognl.OgnlException;
import ognl.PropertyAccessor;
import org.apache.struts2.ognl.StrutsContext;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.StrutsException;
@@ -41,7 +41,7 @@ import java.util.List;
*
* @author Gabriel Zimmerman
*/
public class XWorkListPropertyAccessor extends ListPropertyAccessor {
public class XWorkListPropertyAccessor extends ListPropertyAccessor<StrutsContext> {
private XWorkCollectionPropertyAccessor _sAcc = new XWorkCollectionPropertyAccessor();
@@ -57,7 +57,7 @@ public class XWorkListPropertyAccessor extends ListPropertyAccessor {
}
@Inject("java.util.Collection")
public void setXWorkCollectionPropertyAccessor(PropertyAccessor acc) {
public void setXWorkCollectionPropertyAccessor(PropertyAccessor<StrutsContext> acc) {
this._sAcc = (XWorkCollectionPropertyAccessor) acc;
}
@@ -82,7 +82,7 @@ public class XWorkListPropertyAccessor extends ListPropertyAccessor {
}
@Override
public Object getProperty(OgnlContext context, Object target, Object name) throws OgnlException {
public Object getProperty(StrutsContext context, Object target, Object name) throws OgnlException {
if (ReflectionContextState.isGettingByKeyProperty(context)
|| name.equals(XWorkCollectionPropertyAccessor.KEY_PROPERTY_FOR_CREATION)) {
@@ -137,7 +137,7 @@ public class XWorkListPropertyAccessor extends ListPropertyAccessor {
}
@Override
public void setProperty(OgnlContext context, Object target, Object name, Object value)
public void setProperty(StrutsContext context, Object target, Object name, Object value)
throws OgnlException {
Class lastClass = (Class) context.get(XWorkConverter.LAST_BEAN_CLASS_ACCESSED);
@@ -185,7 +185,7 @@ public class XWorkListPropertyAccessor extends ListPropertyAccessor {
super.setProperty(context, target, name, realValue);
}
private Object getRealValue(OgnlContext context, Object value, Class convertToClass) {
private Object getRealValue(StrutsContext context, Object value, Class convertToClass) {
if (value == null || convertToClass == null) {
return value;
}
@@ -24,8 +24,8 @@ import org.apache.struts2.conversion.impl.XWorkConverter;
import org.apache.struts2.inject.Inject;
import org.apache.struts2.util.reflection.ReflectionContextState;
import ognl.MapPropertyAccessor;
import ognl.OgnlContext;
import ognl.OgnlException;
import org.apache.struts2.ognl.StrutsContext;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -37,7 +37,7 @@ import java.util.Map;
*
* @author Gabriel Zimmerman
*/
public class XWorkMapPropertyAccessor extends MapPropertyAccessor {
public class XWorkMapPropertyAccessor extends MapPropertyAccessor<StrutsContext> {
private static final Logger LOG = LogManager.getLogger(XWorkMapPropertyAccessor.class);
@@ -63,7 +63,7 @@ public class XWorkMapPropertyAccessor extends MapPropertyAccessor {
}
@Override
public Object getProperty(OgnlContext context, Object target, Object name) throws OgnlException {
public Object getProperty(StrutsContext context, Object target, Object name) throws OgnlException {
LOG.trace("Entering getProperty ({},{},{})", context, target, name);
ReflectionContextState.updateCurrentPropertyPath(context, name);
@@ -123,7 +123,7 @@ public class XWorkMapPropertyAccessor extends MapPropertyAccessor {
}
@Override
public void setProperty(OgnlContext context, Object target, Object name, Object value) throws OgnlException {
public void setProperty(StrutsContext context, Object target, Object name, Object value) throws OgnlException {
LOG.trace("Entering setProperty({},{},{},{})", context, target, name, value);
Object key = getKey(context, name);
@@ -131,7 +131,7 @@ public class XWorkMapPropertyAccessor extends MapPropertyAccessor {
map.put(key, getValue(context, value));
}
private Object getValue(OgnlContext context, Object value) {
private Object getValue(StrutsContext context, Object value) {
Class lastClass = (Class) context.get(XWorkConverter.LAST_BEAN_CLASS_ACCESSED);
String lastProperty = (String) context.get(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED);
if (lastClass == null || lastProperty == null) {
@@ -144,7 +144,7 @@ public class XWorkMapPropertyAccessor extends MapPropertyAccessor {
return xworkConverter.convertValue(context, value, elementClass);
}
private Object getKey(OgnlContext context, Object name) {
private Object getKey(StrutsContext context, Object name) {
Class lastClass = (Class) context.get(XWorkConverter.LAST_BEAN_CLASS_ACCESSED);
String lastProperty = (String) context.get(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED);
if (lastClass == null || lastProperty == null) {
@@ -21,9 +21,9 @@ package org.apache.struts2.ognl.accessor;
import org.apache.struts2.util.reflection.ReflectionContextState;
import ognl.MethodFailedException;
import ognl.ObjectMethodAccessor;
import ognl.OgnlContext;
import ognl.OgnlRuntime;
import ognl.PropertyAccessor;
import org.apache.struts2.ognl.StrutsContext;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -38,12 +38,13 @@ import java.util.Collection;
* @author Patrick Lightbody
* @author tmjee
*/
public class XWorkMethodAccessor extends ObjectMethodAccessor {
public class XWorkMethodAccessor extends ObjectMethodAccessor<StrutsContext> {
private static final Logger LOG = LogManager.getLogger(XWorkMethodAccessor.class);
@Override
public Object callMethod(OgnlContext context, Object object, String string, Object[] objects) throws MethodFailedException {
@SuppressWarnings("unchecked")
public Object callMethod(StrutsContext context, Object object, String string, Object[] objects) throws MethodFailedException {
//Collection property accessing
//this if statement ensures that ognl
@@ -94,7 +95,7 @@ public class XWorkMethodAccessor extends ObjectMethodAccessor {
}
}
private Object callMethodWithDebugInfo(OgnlContext context, Object object, String methodName, Object[] objects) throws MethodFailedException {
private Object callMethodWithDebugInfo(StrutsContext context, Object object, String methodName, Object[] objects) throws MethodFailedException {
try {
return super.callMethod(context, object, methodName, objects);
} catch (MethodFailedException e) {
@@ -109,7 +110,7 @@ public class XWorkMethodAccessor extends ObjectMethodAccessor {
}
@Override
public Object callStaticMethod(OgnlContext context, Class aClass, String string, Object[] objects) throws MethodFailedException {
public Object callStaticMethod(StrutsContext context, Class aClass, String string, Object[] objects) throws MethodFailedException {
boolean e = ReflectionContextState.isDenyMethodExecution(context);
if (!e) {
@@ -119,7 +120,7 @@ public class XWorkMethodAccessor extends ObjectMethodAccessor {
}
}
private Object callStaticMethodWithDebugInfo(OgnlContext context, Class aClass, String methodName,
private Object callStaticMethodWithDebugInfo(StrutsContext context, Class aClass, String methodName,
Object[] objects) throws MethodFailedException {
try {
return super.callStaticMethod(context, aClass, methodName, objects);
@@ -21,15 +21,15 @@ package org.apache.struts2.ognl.accessor;
import org.apache.struts2.conversion.impl.XWorkConverter;
import org.apache.struts2.util.reflection.ReflectionContextState;
import ognl.ObjectPropertyAccessor;
import ognl.OgnlContext;
import ognl.OgnlException;
import org.apache.struts2.ognl.StrutsContext;
/**
* @author Gabe
*/
public class XWorkObjectPropertyAccessor extends ObjectPropertyAccessor {
public class XWorkObjectPropertyAccessor extends ObjectPropertyAccessor<StrutsContext> {
@Override
public Object getProperty(OgnlContext context, Object target, Object oname) throws OgnlException {
public Object getProperty(StrutsContext context, Object target, Object oname) throws OgnlException {
//set the last set objects in the context
//so if the next objects accessed are
//Maps or Collections they can use the information
@@ -42,7 +42,7 @@ import org.apache.struts2.ognl.accessor.RootAccessor;
import org.apache.struts2.util.ValueStack;
import org.apache.struts2.util.ValueStackFactory;
import org.apache.struts2.util.reflection.ReflectionContextState;
import ognl.OgnlContext;
import org.apache.struts2.ognl.StrutsContext;
import org.apache.struts2.action.NoParameters;
import org.apache.struts2.action.ParameterNameAware;
import org.apache.struts2.action.ParameterValueAware;
@@ -353,7 +353,7 @@ public class ParametersInterceptorTest extends XWorkTestCase {
//then
assertEquals("This is blah", ((SimpleAction) proxy.getAction()).getBlah());
Field field = ReflectionContextState.class.getField("DENY_METHOD_EXECUTION");
boolean allowStaticFieldAccess = ((OgnlContext) stack.getContext()).getMemberAccess().isAccessible((OgnlContext) stack.getContext(), ReflectionContextState.class, field, "");
boolean allowStaticFieldAccess = ((StrutsContext) stack.getContext()).getMemberAccess().isAccessible((StrutsContext) stack.getContext(), ReflectionContextState.class, field, "");
assertFalse(allowStaticFieldAccess);
}
@@ -23,7 +23,6 @@ import ognl.MethodFailedException;
import ognl.NoSuchPropertyException;
import ognl.NullHandler;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
import ognl.OgnlRuntime;
import ognl.SimpleNode;
@@ -90,12 +89,12 @@ public class OgnlUtilTest extends XWorkTestCase {
public void testCanSetADependentObject() {
String dogName = "fido";
OgnlRuntime.setNullHandler(Owner.class, new NullHandler() {
public Object nullMethodResult(OgnlContext context, Object o, String s, Object[] objects) {
OgnlRuntime.setNullHandler(Owner.class, new NullHandler<StrutsContext>() {
public Object nullMethodResult(StrutsContext context, Object o, String s, Object[] objects) {
return null;
}
public Object nullPropertyValue(OgnlContext context, Object o, Object o1) {
public Object nullPropertyValue(StrutsContext context, Object o, Object o1) {
String methodName = o1.toString();
String getter = "set" + methodName.substring(0, 1).toUpperCase() + methodName.substring(1);
Method[] methods = o.getClass().getDeclaredMethods();
@@ -199,7 +198,7 @@ public class OgnlUtilTest extends XWorkTestCase {
public void testExpressionIsCachedIrrespectiveOfItsExecutionStatus() {
Foo foo = new Foo();
OgnlContext context = ognlUtil.createDefaultContext(foo);
StrutsContext context = ognlUtil.createDefaultContext(foo);
// Expression which executes with success
try {
@@ -223,7 +222,7 @@ public class OgnlUtilTest extends XWorkTestCase {
ognlUtil.setContainer(container); // Must be explicitly set as the generated OgnlUtil instance has no container
ognlUtil.setEnableExpressionCache("true");
Foo foo = new Foo();
OgnlContext context = ognlUtil.createDefaultContext(foo);
StrutsContext context = ognlUtil.createDefaultContext(foo);
// Expression which executes with success
try {
@@ -243,7 +242,7 @@ public class OgnlUtilTest extends XWorkTestCase {
public void testMethodExpressionIsCachedIrrespectiveOfItsExecutionStatus() {
Foo foo = new Foo();
OgnlContext context = ognlUtil.createDefaultContext(foo);
StrutsContext context = ognlUtil.createDefaultContext(foo);
// Method expression which executes with success
try {
@@ -846,7 +845,7 @@ public class OgnlUtilTest extends XWorkTestCase {
ChainingInterceptor foo = new ChainingInterceptor();
ChainingInterceptor foo2 = new ChainingInterceptor();
OgnlContext context = ognlUtil.createDefaultContext(null);
StrutsContext context = ognlUtil.createDefaultContext(null);
SimpleNode expression = (SimpleNode) Ognl.parseExpression("{'a','ruby','b','tom'}");
Ognl.getValue(expression, context, "aksdj");
@@ -903,7 +902,7 @@ public class OgnlUtilTest extends XWorkTestCase {
public void testBeanMapExpressions() throws OgnlException, NoSuchMethodException {
Foo foo = new Foo();
OgnlContext context = ognlUtil.createDefaultContext(foo);
StrutsContext context = ognlUtil.createDefaultContext(foo);
SecurityMemberAccess sma = (SecurityMemberAccess) context.getMemberAccess();
sma.useExcludedPackageNames("org.apache.struts2.ognl");
@@ -19,7 +19,6 @@
package org.apache.struts2.ognl;
import ognl.MemberAccess;
import ognl.OgnlContext;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.struts2.TestBean;
import org.apache.struts2.config.ConfigurationException;
@@ -55,7 +54,7 @@ import static org.mockito.Mockito.when;
public class SecurityMemberAccessTest {
private OgnlContext context;
private StrutsContext context;
private FooBar target;
protected SecurityMemberAccess sma;
protected ProviderAllowlist mockedProviderAllowlist;
@@ -64,12 +63,12 @@ public class SecurityMemberAccessTest {
@Before
public void setUp() {
context = ognl.Ognl.createDefaultContext(null);
target = new FooBar();
mockedProviderAllowlist = mock(ProviderAllowlist.class);
mockedThreadAllowlist = mock(ThreadAllowlist.class);
proxyService = new StrutsProxyService(new StrutsProxyCacheFactory<>("1000", "basic"));
assignNewSma(true);
context = new StrutsContext(sma);
}
protected void assignNewSma(boolean allowStaticFieldAccess) {
@@ -37,7 +37,6 @@ import org.apache.struts2.util.ValueStack;
import org.apache.struts2.util.location.LocatableProperties;
import org.apache.struts2.util.reflection.ReflectionContextState;
import ognl.Ognl;
import ognl.OgnlContext;
import java.util.ArrayList;
import java.util.Collection;
@@ -57,7 +56,8 @@ public class SetPropertiesTest extends XWorkTestCase {
public void testOgnlUtilEmptyStringAsLong() {
Bar bar = new Bar();
OgnlContext context = Ognl.createDefaultContext(bar, new SecurityMemberAccess(null, null));
StrutsContext context = new StrutsContext(new SecurityMemberAccess(null, null));
context.withRoot(bar);
context.put(XWorkConverter.REPORT_CONVERSION_ERRORS, Boolean.TRUE);
bar.setId(null);
@@ -81,7 +81,7 @@ public class SetPropertiesTest extends XWorkTestCase {
ValueStack vs = ActionContext.getContext().getValueStack();
vs.getContext().put(XWorkConverter.REPORT_CONVERSION_ERRORS, Boolean.TRUE);
XWorkConverter c = (XWorkConverter) ((OgnlTypeConverterWrapper) Ognl.getTypeConverter((OgnlContext) vs.getContext())).getTarget();
XWorkConverter c = (XWorkConverter) ((OgnlTypeConverterWrapper) ((StrutsContext) vs.getContext()).getTypeConverter()).getTarget();
c.registerConverter(Cat.class.getName(), new FooBarConverter());
vs.push(foo);
@@ -97,7 +97,7 @@ public class SetPropertiesTest extends XWorkTestCase {
ValueStack vs = ActionContext.getContext().getValueStack();
vs.getContext().put(XWorkConverter.REPORT_CONVERSION_ERRORS, Boolean.TRUE);
XWorkConverter c = (XWorkConverter) ((OgnlTypeConverterWrapper) Ognl.getTypeConverter((OgnlContext) vs.getContext())).getTarget();
XWorkConverter c = (XWorkConverter) ((OgnlTypeConverterWrapper) ((StrutsContext) vs.getContext()).getTypeConverter()).getTarget();
c.registerConverter(Cat.class.getName(), new FooBarConverter());
vs.push(foo);
@@ -0,0 +1,72 @@
/*
* 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.TypeConverter;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
@SuppressWarnings("unchecked")
public class StrutsContextTest {
@Test
public void shouldCreateContextWithRequiredMemberAccess() {
MemberAccess<StrutsContext> memberAccess = mock(MemberAccess.class);
var context = new StrutsContext(memberAccess);
assertThat(context).isNotNull();
assertThat(context.getMemberAccess()).isSameAs(memberAccess);
}
@Test
public 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
public 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
public void shouldImplementMapInterface() {
MemberAccess<StrutsContext> memberAccess = mock(MemberAccess.class);
var context = new StrutsContext(memberAccess);
context.put("testKey", "testValue");
assertThat(context.get("testKey")).isEqualTo("testValue");
}
}
@@ -19,8 +19,8 @@
package org.apache.struts2.util;
import org.apache.struts2.ognl.SecurityMemberAccess;
import org.apache.struts2.ognl.StrutsContext;
import jakarta.servlet.jsp.tagext.TagSupport;
import ognl.OgnlContext;
import org.apache.struts2.StrutsInternalTestCase;
import org.apache.struts2.views.jsp.ActionTag;
@@ -28,12 +28,12 @@ import java.lang.reflect.Member;
public class SecurityMemberAccessInServletsTest extends StrutsInternalTestCase {
private OgnlContext context;
private StrutsContext context;
@Override
public void setUp() throws Exception {
super.setUp();
context = ognl.Ognl.createDefaultContext(null);
context = new StrutsContext(new SecurityMemberAccess(null, null));
}
public void testJavaxServletPackageAccess() throws Exception {
@@ -0,0 +1,272 @@
# Hibernate Proxy Detection Optimization
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Eliminate `LinkageError` exceptions thrown when Hibernate is not on the classpath by detecting availability once at class-load time.
**Architecture:** Add a static availability check in `StrutsProxyService` that probes for `org.hibernate.proxy.HibernateProxy` once during class initialization. All Hibernate-related methods short-circuit immediately when Hibernate is absent. Same pattern applied to deprecated `ProxyUtil`.
**Tech Stack:** Java 17, JUnit 5, AssertJ, Mockito
---
### Task 1: Add Hibernate Availability Check to StrutsProxyService
**Files:**
- Modify: `core/src/main/java/org/apache/struts2/util/StrutsProxyService.java`
- Test: `core/src/test/java/org/apache/struts2/util/StrutsProxyServiceTest.java`
- [ ] **Step 1: Write the failing test — verify no LinkageError is thrown when Hibernate classes are used**
The existing tests already call `isHibernateProxy()` and `isHibernateProxyMember()` with non-Hibernate objects. We need a test that verifies the short-circuit behavior works correctly. Add this test to `StrutsProxyServiceTest.java`:
```java
@Test
public void isHibernateProxyDoesNotThrowWhenCalledRepeatedly() {
// Verify that calling isHibernateProxy many times for different objects
// does not cause performance issues (no exceptions thrown internally)
for (int i = 0; i < 1000; i++) {
assertThat(proxyService.isHibernateProxy(new Object())).isFalse();
}
}
@Test
public void isHibernateProxyMemberDoesNotThrowWhenCalledRepeatedly() throws NoSuchMethodException {
Method method = Object.class.getMethod("toString");
for (int i = 0; i < 1000; i++) {
assertThat(proxyService.isHibernateProxyMember(method)).isFalse();
}
}
```
- [ ] **Step 2: Run tests to verify they pass (baseline — these pass even without the fix because Hibernate IS on the test classpath)**
Run: `mvn test -DskipAssembly -pl core -Dtest=StrutsProxyServiceTest#isHibernateProxyDoesNotThrowWhenCalledRepeatedly+isHibernateProxyMemberDoesNotThrowWhenCalledRepeatedly`
Expected: PASS
- [ ] **Step 3: Add static Hibernate availability flag to StrutsProxyService**
In `core/src/main/java/org/apache/struts2/util/StrutsProxyService.java`, add a static availability check at the top of the class and modify the three Hibernate methods to short-circuit:
```java
// Add this field near the top of the class, after the class declaration:
private static final boolean HIBERNATE_AVAILABLE = isHibernateAvailable();
private static boolean isHibernateAvailable() {
try {
Class.forName("org.hibernate.proxy.HibernateProxy");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
```
Then modify the three Hibernate methods to short-circuit:
**`isHibernateProxy`** — change from:
```java
@Override
public boolean isHibernateProxy(Object object) {
try {
return object != null && HibernateProxy.class.isAssignableFrom(object.getClass());
} catch (LinkageError ignored) {
return false;
}
}
```
to:
```java
@Override
public boolean isHibernateProxy(Object object) {
if (!HIBERNATE_AVAILABLE || object == null) {
return false;
}
try {
return HibernateProxy.class.isAssignableFrom(object.getClass());
} catch (LinkageError ignored) {
return false;
}
}
```
**`isHibernateProxyMember`** — change from:
```java
@Override
public boolean isHibernateProxyMember(Member member) {
try {
return hasMember(HibernateProxy.class, member);
} catch (LinkageError ignored) {
return false;
}
}
```
to:
```java
@Override
public boolean isHibernateProxyMember(Member member) {
if (!HIBERNATE_AVAILABLE) {
return false;
}
try {
return hasMember(HibernateProxy.class, member);
} catch (LinkageError ignored) {
return false;
}
}
```
**`getHibernateProxyTarget`** — change from:
```java
@Override
public Object getHibernateProxyTarget(Object object) {
try {
return Hibernate.unproxy(object);
} catch (LinkageError ignored) {
return object;
}
}
```
to:
```java
@Override
public Object getHibernateProxyTarget(Object object) {
if (!HIBERNATE_AVAILABLE) {
return object;
}
try {
return Hibernate.unproxy(object);
} catch (LinkageError ignored) {
return object;
}
}
```
- [ ] **Step 4: Run the full StrutsProxyService test suite**
Run: `mvn test -DskipAssembly -pl core -Dtest=StrutsProxyServiceTest`
Expected: All tests PASS
- [ ] **Step 5: Run the Spring integration test suite**
Run: `mvn test -DskipAssembly -pl core -Dtest=StrutsProxyServiceSpringIntegrationTest`
Expected: All tests PASS
- [ ] **Step 6: Commit**
```bash
git add core/src/main/java/org/apache/struts2/util/StrutsProxyService.java core/src/test/java/org/apache/struts2/util/StrutsProxyServiceTest.java
git commit -m "WW-5622 Optimize Hibernate proxy detection to avoid LinkageError exceptions
Add static availability check for Hibernate classes in StrutsProxyService.
When Hibernate is not on the classpath, all Hibernate-related methods
short-circuit immediately without throwing/catching LinkageError.
This eliminates a significant performance penalty for applications
that don't use Hibernate."
```
---
### Task 2: Apply Same Fix to Deprecated ProxyUtil
**Files:**
- Modify: `core/src/main/java/org/apache/struts2/util/ProxyUtil.java`
- [ ] **Step 1: Add the same static availability check to ProxyUtil**
In `core/src/main/java/org/apache/struts2/util/ProxyUtil.java`, add the same pattern:
```java
// Add after the isProxyMemberCache field:
private static final boolean HIBERNATE_AVAILABLE = isHibernateAvailable();
private static boolean isHibernateAvailable() {
try {
Class.forName("org.hibernate.proxy.HibernateProxy");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
```
Then modify the three Hibernate methods in ProxyUtil identically to Task 1:
**`isHibernateProxy`**:
```java
@Deprecated(since = "7.2")
public static boolean isHibernateProxy(Object object) {
if (!HIBERNATE_AVAILABLE || object == null) {
return false;
}
try {
return HibernateProxy.class.isAssignableFrom(object.getClass());
} catch (LinkageError ignored) {
return false;
}
}
```
**`isHibernateProxyMember`**:
```java
@Deprecated(since = "7.2")
public static boolean isHibernateProxyMember(Member member) {
if (!HIBERNATE_AVAILABLE) {
return false;
}
try {
return hasMember(HibernateProxy.class, member);
} catch (LinkageError ignored) {
return false;
}
}
```
**`getHibernateProxyTarget`**:
```java
@Deprecated(since = "7.2")
public static Object getHibernateProxyTarget(Object object) {
if (!HIBERNATE_AVAILABLE) {
return object;
}
try {
return Hibernate.unproxy(object);
} catch (LinkageError ignored) {
return object;
}
}
```
- [ ] **Step 2: Run existing ProxyUtil tests**
Run: `mvn test -DskipAssembly -pl core -Dtest=ProxyUtilTest`
Expected: PASS (or if no dedicated test exists, run the SecurityMemberAccess tests which exercise ProxyUtil indirectly)
Run: `mvn test -DskipAssembly -pl core -Dtest=SecurityMemberAccessTest`
Expected: PASS
- [ ] **Step 3: Commit**
```bash
git add core/src/main/java/org/apache/struts2/util/ProxyUtil.java
git commit -m "WW-5622 Apply same Hibernate availability optimization to deprecated ProxyUtil"
```
---
### Task 3: Run Full Test Suite
- [ ] **Step 1: Run all core tests**
Run: `mvn test -DskipAssembly -pl core`
Expected: All tests PASS
- [ ] **Step 2: Run spring plugin tests (exercises proxy detection heavily)**
Run: `mvn test -DskipAssembly -pl plugins/spring`
Expected: All tests PASS
- [ ] **Step 3: Run json plugin tests (StrutsJSONWriter has Hibernate-related class name checks)**
Run: `mvn test -DskipAssembly -pl plugins/json`
Expected: All tests PASS
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,263 @@
# OGNL 3.5.x Upgrade — Design Spec
> **Jira:** [WW-5326](https://issues.apache.org/jira/browse/WW-5326)
## Goal
Upgrade Apache Struts from OGNL 3.4.10 to OGNL 3.5.0-BETA4+ and introduce `StrutsContext extends OgnlContext<StrutsContext>` as the framework's own OGNL evaluation context. This lays the foundation for treating OGNL as an execution sandbox with typed, Struts-specific context state.
## Motivation
- **Forward-looking maintenance**: stay current with OGNL development, avoid a larger migration later
- **Real-world validation**: Struts is the primary consumer of OGNL — upgrading validates the 3.5.x generic API
- **Java 17 baseline**: OGNL 3.5.x requires Java 17, aligning with Struts 7.x
- **Type safety**: self-bounded generics (`OgnlContext<C>`) enable Struts to have a properly typed context instead of stringly-typed map entries
- **Sandbox foundation**: `StrutsContext` is the first step toward isolated OGNL evaluation contexts (`OgnlRuntime` instance-based isolation is future work)
## Non-Goals
- Instance-based `OgnlRuntime` / true sandbox isolation (future OGNL work)
- Consuming new OGNL features (null-safe operator `?.`, dual-mode evaluation) — those come as separate follow-ups
- Behavioral changes to security model, accessor logic, or expression evaluation
## Current State
### OGNL Usage in Struts
- **Version**: 3.4.10 (defined in root `pom.xml` as `ognl.version`)
- **Core dependency**: `core/pom.xml` depends on `ognl:ognl`
- **Context creation**: 3 call sites use `Ognl.createDefaultContext()`:
- `OgnlUtil.createDefaultContext()` (line 738)
- `OgnlValueStack.setRoot()` (line 124)
- `OgnlReflectionContextFactory.createDefaultContext()` (line 33)
- **No custom OgnlContext subclass**: Struts uses `OgnlContext` directly
- **Context state via map entries**: flags like `DENY_METHOD_EXECUTION`, `CREATE_NULL_OBJECTS`, `VALUE_STACK`, conversion state — all stored as stringly-typed map entries in `OgnlContext` and accessed via `ReflectionContextState` static methods
### OGNL Interface Implementations in Struts
| Interface | Struts Implementation |
|---|---|
| `MemberAccess` | `SecurityMemberAccess` |
| `TypeConverter` | `OgnlTypeConverterWrapper` |
| `ClassResolver` | `RootAccessor` (interface), `CompoundRootAccessor` (impl) |
| `PropertyAccessor` | `RootAccessor`, `CompoundRootAccessor`, `ObjectProxyPropertyAccessor`, + 8 classes extending `ObjectPropertyAccessor`/`ListPropertyAccessor`/`MapPropertyAccessor`/etc. |
| `MethodAccessor` | `RootAccessor`, `CompoundRootAccessor`, `XWorkMethodAccessor` |
| `NullHandler` | `OgnlNullHandlerWrapper` |
### Tiles Plugin OGNL Usage
6-8 files in `plugins/tiles` use OGNL directly:
- `ScopePropertyAccessor`, `AnyScopePropertyAccessor`, `NestedObjectDelegatePropertyAccessor`, `DelegatePropertyAccessor`
- `OGNLAttributeEvaluator`, `PropertyAccessorDelegateFactory`, `TilesContextPropertyAccessorDelegateFactory`
- Associated test files
## OGNL 3.5.x Key API Changes
### Self-Bounded Generics
All core interfaces and classes are now generic with `<C extends OgnlContext<C>>`:
```java
public class OgnlContext<C extends OgnlContext<C>> implements Map<String, Object>
public interface MemberAccess<C extends OgnlContext<C>>
public interface ClassResolver<C extends OgnlContext<C>>
public interface TypeConverter<C extends OgnlContext<C>>
public interface PropertyAccessor<C extends OgnlContext<C>>
public interface MethodAccessor<C extends OgnlContext<C>>
public interface NullHandler<C extends OgnlContext<C>>
public class ObjectPropertyAccessor<C extends OgnlContext<C>> implements PropertyAccessor<C>
// ... all base accessor classes similarly parameterized
```
### OgnlContext Constructor Changes
```java
// New (memberAccess first, required non-null)
public OgnlContext(MemberAccess<C> memberAccess, ClassResolver<C> classResolver, TypeConverter<C> typeConverter)
// Deprecated (old parameter order)
@Deprecated(forRemoval = true)
OgnlContext(ClassResolver<C> classResolver, TypeConverter<C> typeConverter, MemberAccess<C> memberAccess)
```
### OgnlContext.Builder
```java
public static class Builder<C extends OgnlContext<C>> {
public Builder(Function<Builder<C>, C> provider)
public Builder<C> withMemberAccess(MemberAccess<C> memberAccess)
public Builder<C> withClassResolver(ClassResolver<C> classResolver)
public Builder<C> withTypeConverter(TypeConverter<C> converter)
public Builder<C> withRoot(Object value)
public C build()
}
```
### Other Changes
- `SecurityManager` support removed
- Null-safe navigation operator (`?.`) added
- `setRoot()` deprecated in favor of `withRoot()` (fluent)
- Java 17 baseline
### Unchanged
- `Ognl` class remains abstract with only static methods (no instance-based evaluation)
- `OgnlRuntime` remains a static utility (global accessor/cache registration)
## Design
### Approach: Direct StrutsContext Construction
Struts creates `StrutsContext` directly, bypassing `Ognl.createDefaultContext()`. This gives Struts full ownership of context lifecycle and avoids the global-state issues of `Ognl.withBuilderProvider()`.
### StrutsContext
```java
package org.apache.struts2.ognl;
public class StrutsContext extends OgnlContext<StrutsContext> {
// Phase 1: just the constructor, delegate to super
public StrutsContext(SecurityMemberAccess memberAccess,
RootAccessor resolver,
OgnlTypeConverterWrapper converter) {
super(memberAccess, resolver, converter);
}
// Phase 2 (incremental): promote map entries to typed fields
// private ValueStack valueStack;
// private boolean reportErrorsOnNoProperty;
// private boolean throwExceptionOnFailure;
// private boolean createNullObjects;
// private boolean denyMethodExecution;
// private boolean denyIndexedAccessExecution;
// private String conversionPropertyFullName;
// private String currentPropertyPath;
// private Class<?> lastBeanClassAccessed;
// private String lastBeanPropertyAccessed;
}
```
Phase 1 introduces the class with zero behavioral change — it's just an `OgnlContext` subclass. The typed fields are a follow-up.
### Generic Type Ripple
All OGNL interface implementations parameterize with `<StrutsContext>`:
```java
// Core interfaces
public class SecurityMemberAccess implements MemberAccess<StrutsContext>
public class OgnlTypeConverterWrapper implements ognl.TypeConverter<StrutsContext>
public interface RootAccessor extends PropertyAccessor<StrutsContext>, MethodAccessor<StrutsContext>, ClassResolver<StrutsContext>
public class OgnlNullHandlerWrapper implements ognl.NullHandler<StrutsContext>
// Accessors (extend generic base classes)
public class CompoundRootAccessor implements RootAccessor
public class ObjectProxyPropertyAccessor implements PropertyAccessor<StrutsContext>
public class ObjectAccessor extends ObjectPropertyAccessor<StrutsContext>
public class ParameterPropertyAccessor extends ObjectPropertyAccessor<StrutsContext>
public class HttpParametersPropertyAccessor extends ObjectPropertyAccessor<StrutsContext>
public class XWorkObjectPropertyAccessor extends ObjectPropertyAccessor<StrutsContext>
public class XWorkEnumerationAccessor extends EnumerationPropertyAccessor<StrutsContext> // verify base class
public class XWorkIteratorPropertyAccessor extends IteratorPropertyAccessor<StrutsContext> // verify base class
public class XWorkCollectionPropertyAccessor extends ObjectPropertyAccessor<StrutsContext>
public class XWorkListPropertyAccessor extends ListPropertyAccessor<StrutsContext>
public class XWorkMapPropertyAccessor extends MapPropertyAccessor<StrutsContext>
public class XWorkMethodAccessor extends ObjectMethodAccessor<StrutsContext>
```
Method signatures change `OgnlContext` parameters to `StrutsContext` throughout.
### Context Creation
Replace `Ognl.createDefaultContext()` with direct construction:
```java
// OgnlUtil.createDefaultContext()
protected StrutsContext createDefaultContext(Object root, ClassResolver<StrutsContext> resolver) {
if (resolver == null) {
resolver = container.getInstance(RootAccessor.class);
}
StrutsContext ctx = new StrutsContext(
container.getInstance(SecurityMemberAccess.class), resolver, defaultConverter);
ctx.withRoot(root);
return ctx;
}
// OgnlValueStack.setRoot()
StrutsContext ognlContext = new StrutsContext(securityMemberAccess, accessor,
new OgnlTypeConverterWrapper(xworkConverter));
ognlContext.withRoot(this.root);
// OgnlReflectionContextFactory — already @Deprecated(forRemoval=true) since 6.8.0
// Keep using Ognl.createDefaultContext(root) with raw type, or remove entirely
```
### Tiles Plugin
The tiles plugin accessors operate on tiles-specific objects, not on `StrutsContext` directly. Options:
- Parameterize with raw `OgnlContext` (use `PropertyAccessor<OgnlContext>`) if OGNL allows it
- Use wildcard `PropertyAccessor<?>` if supported
- Parameterize with `StrutsContext` if tiles always runs within a Struts context
Decision: determine during implementation based on what compiles cleanly.
### XWorkTypeConverterWrapper
Currently casts `Map` context to `OgnlContext`. After upgrade, `ognl.TypeConverter<StrutsContext>` passes `StrutsContext` directly — the cast goes away. Struts' own `TypeConverter` interface (in `conversion` package) may also need its `convertValue` signature updated.
### ReflectionContextState
Initially unchanged — continues to work via `Map<String, Object>` interface that `StrutsContext` inherits from `OgnlContext`. Promoting to typed fields is a follow-up.
## Implementation Phases
### Phase 1: Version bump + StrutsContext + generics (this effort)
1. Bump `ognl.version` to `3.5.0-BETA4` in root `pom.xml`
2. Create `StrutsContext extends OgnlContext<StrutsContext>` (constructor only)
3. Update all OGNL interface implementations with `<StrutsContext>` type parameter (~20 classes in core)
4. Update method signatures: `OgnlContext``StrutsContext` in all accessor/handler implementations
5. Replace `Ognl.createDefaultContext()` with direct `StrutsContext` construction (3 call sites)
6. Update tiles plugin accessor classes (~6-8 files)
7. Update test files (~50+ files referencing `OgnlContext`)
8. Verify all tests pass
### Phase 2: Typed context fields (follow-up)
- Promote `ReflectionContextState` map entries to `StrutsContext` typed fields
- Update accessors to use typed getters instead of `context.get("string.key")`
- Deprecate `ReflectionContextState` static methods
### Phase 3: Sandbox features (future, requires OGNL changes)
- Instance-based `OgnlRuntime` (OGNL-side work)
- Per-sandbox accessor registrations
- Isolated evaluation engines
## Risk Areas
### OgnlRuntime global statics
`OgnlRuntime.setPropertyAccessor(Class<?>, PropertyAccessor<C>)` is generic but the registration is global. Registering `PropertyAccessor<StrutsContext>` may cause unchecked warnings or issues when OGNL internally retrieves accessors with a different context type. May need raw types at registration boundary.
### OGNL internal context preservation
If OGNL internally creates new `OgnlContext` instances during expression evaluation (rather than preserving the passed-in `StrutsContext`), typed fields would be lost. BETA1 addressed "context root preservation during nested evaluations" but this needs runtime verification.
### Tiles plugin type compatibility
Tiles accessors may not naturally fit `StrutsContext` parameterization. Need to determine the right generic type during implementation.
### OGNL BETA stability
OGNL 3.5.0 is still in BETA. API changes may occur in subsequent releases. This is acceptable given the user is an OGNL contributor and can influence the API.
## Expected Outcomes
- Struts compiles and all tests pass against OGNL 3.5.0-BETA4
- `StrutsContext` exists as the framework's OGNL context class
- All OGNL interface implementations are properly parameterized with `<StrutsContext>`
- Foundation is in place for typed context fields and eventual sandbox isolation
- Any OGNL API issues discovered are reported/fixed upstream
@@ -28,7 +28,7 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;
import ognl.OgnlContext;
import org.apache.struts2.ognl.StrutsContext;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
@@ -43,7 +43,7 @@ public class SecurityMemberAccessProxyTest extends XWorkJUnit4TestCase {
private static final String PROXY_MEMBER_METHOD = "isExposeProxy";
private static final String TEST_SUB_BEAN_CLASS_METHOD = "getIssueId";
private OgnlContext context;
private StrutsContext context;
private ActionProxy proxy;
private SecurityMemberAccess sma;
private ProxyService proxyService;
@@ -57,14 +57,13 @@ public class SecurityMemberAccessProxyTest extends XWorkJUnit4TestCase {
XmlConfigurationProvider provider = new StrutsXmlConfigurationProvider("org/apache/struts2/spring/actionContext-xwork.xml");
loadConfigurationProviders(provider);
context = ognl.Ognl.createDefaultContext(null);
proxy = actionProxyFactory.createActionProxy(null, "chaintoAOPedTestSubBeanAction", null, context);
proxyObjectProxyMember = proxy.getAction().getClass().getMethod(PROXY_MEMBER_METHOD);
proxyObjectNonProxyMember = proxy.getAction().getClass().getMethod(TEST_SUB_BEAN_CLASS_METHOD);
proxyService = new StrutsProxyService(new StrutsProxyCacheFactory<>("1000", "basic"));
sma = new SecurityMemberAccess(null, null);
sma.setProxyService(proxyService);
context = new StrutsContext(sma);
proxy = actionProxyFactory.createActionProxy(null, "chaintoAOPedTestSubBeanAction", null, context);
proxyObjectProxyMember = proxy.getAction().getClass().getMethod(PROXY_MEMBER_METHOD);
proxyObjectNonProxyMember = proxy.getAction().getClass().getMethod(TEST_SUB_BEAN_CLASS_METHOD);
}
/**
@@ -27,6 +27,7 @@ import java.util.Map;
/**
* Accesses attributes in any scope.
*/
@SuppressWarnings("rawtypes")
public class AnyScopePropertyAccessor implements PropertyAccessor {
@Override
@@ -29,6 +29,7 @@ import ognl.PropertyAccessor;
* @param <T> The type of the accessed root object.
* @since 2.2.0
*/
@SuppressWarnings("rawtypes")
public class DelegatePropertyAccessor<T> implements PropertyAccessor {
/**
@@ -29,6 +29,7 @@ import ognl.PropertyAccessor;
* @param <T> The root object type from which the target object will be extracted.
* @since 2.2.0
*/
@SuppressWarnings("rawtypes")
public class NestedObjectDelegatePropertyAccessor<T> implements PropertyAccessor {
/**
@@ -28,6 +28,7 @@ import ognl.PropertyAccessor;
* @param <T> The type of the root object to evaluate.
* @since 2.2.0
*/
@SuppressWarnings("rawtypes")
public interface PropertyAccessorDelegateFactory<T> {
/**
@@ -25,6 +25,7 @@ import org.apache.tiles.request.Request;
/**
* Accesses a scope.
*/
@SuppressWarnings("rawtypes")
public class ScopePropertyAccessor implements PropertyAccessor {
/**
+2 -1
View File
@@ -123,7 +123,7 @@
<jaxb-impl.version>4.0.7</jaxb-impl.version>
<log4j2.version>2.25.4</log4j2.version>
<mockito.version>5.23.0</mockito.version>
<ognl.version>3.4.10</ognl.version>
<ognl.version>3.5.0-BETA4</ognl.version>
<slf4j.version>2.0.17</slf4j.version>
<spring.version>6.2.12</spring.version>
<struts-annotations.version>2.0</struts-annotations.version>
@@ -314,6 +314,7 @@
<exclude>src/main/webapp/fonts/**/*</exclude>
<exclude>thoughts/**/*.md</exclude>
<exclude>test-output/**</exclude>
<exclude>docs/**</exclude>
</inputExcludes>
</configuration>
</plugin>