Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -30,13 +29,13 @@ public OgnlNullHandlerWrapper(NullHandler target) {
}

@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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
public class OgnlReflectionContextFactory implements ReflectionContextFactory {

@Override
@SuppressWarnings({"rawtypes", "unchecked"})
public OgnlContext createDefaultContext(Object root) {
return Ognl.createDefaultContext(root);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,14 @@
*/
package org.apache.struts2.ognl;

import ognl.OgnlContext;
import org.apache.struts2.conversion.TypeConverter;

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;

Expand All @@ -38,7 +37,7 @@ public OgnlTypeConverterWrapper(TypeConverter converter) {
}

@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);
}

Expand Down
59 changes: 31 additions & 28 deletions core/src/main/java/org/apache/struts2/ognl/OgnlUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@

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;
Expand Down Expand Up @@ -211,14 +211,14 @@
* @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;
}

/**
Expand Down Expand Up @@ -247,9 +247,9 @@
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);
Expand Down Expand Up @@ -309,9 +309,9 @@
* 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);
Expand Down Expand Up @@ -368,10 +368,10 @@
}

private boolean isEvalExpression(Object tree, Map<String, Object> context) throws OgnlException {
if (tree instanceof SimpleNode node) {

Check warning on line 371 in core/src/main/java/org/apache/struts2/ognl/OgnlUtil.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Provide the parametrized type for this generic.

See more on https://sonarcloud.io/project/issues?id=apache_struts&issues=AZ1mePcE6XBGhgATtBlR&open=AZ1mePcE6XBGhgATtBlR&pullRequest=1654
OgnlContext ognlContext = null;

Check warning on line 372 in core/src/main/java/org/apache/struts2/ognl/OgnlUtil.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Provide the parametrized type for this generic.

See more on https://sonarcloud.io/project/issues?id=apache_struts&issues=AZ1mePcE6XBGhgATtBlS&open=AZ1mePcE6XBGhgATtBlS&pullRequest=1654

if (context instanceof OgnlContext oc) {

Check warning on line 374 in core/src/main/java/org/apache/struts2/ognl/OgnlUtil.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Provide the parametrized type for this generic.

See more on https://sonarcloud.io/project/issues?id=apache_struts&issues=AZ1mePcE6XBGhgATtBlT&open=AZ1mePcE6XBGhgATtBlT&pullRequest=1654
ognlContext = oc;
}
return node.isEvalChain(ognlContext) || node.isSequence(ognlContext);
Expand All @@ -380,10 +380,10 @@
}

private boolean isArithmeticExpression(Object tree, Map<String, Object> context) throws OgnlException {
if (tree instanceof SimpleNode node) {

Check warning on line 383 in core/src/main/java/org/apache/struts2/ognl/OgnlUtil.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Provide the parametrized type for this generic.

See more on https://sonarcloud.io/project/issues?id=apache_struts&issues=AZ1mePcE6XBGhgATtBlU&open=AZ1mePcE6XBGhgATtBlU&pullRequest=1654
OgnlContext ognlContext = null;

Check warning on line 384 in core/src/main/java/org/apache/struts2/ognl/OgnlUtil.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Provide the parametrized type for this generic.

See more on https://sonarcloud.io/project/issues?id=apache_struts&issues=AZ1mePcE6XBGhgATtBlV&open=AZ1mePcE6XBGhgATtBlV&pullRequest=1654

if (context instanceof OgnlContext oc) {

Check warning on line 386 in core/src/main/java/org/apache/struts2/ognl/OgnlUtil.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Provide the parametrized type for this generic.

See more on https://sonarcloud.io/project/issues?id=apache_struts&issues=AZ1mePcE6XBGhgATtBlW&open=AZ1mePcE6XBGhgATtBlW&pullRequest=1654
ognlContext = oc;
}
return node.isOperation(ognlContext);
Expand All @@ -392,10 +392,10 @@
}

private boolean isSimpleMethod(Object tree, Map<String, Object> context) throws OgnlException {
if (tree instanceof SimpleNode node) {

Check warning on line 395 in core/src/main/java/org/apache/struts2/ognl/OgnlUtil.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Provide the parametrized type for this generic.

See more on https://sonarcloud.io/project/issues?id=apache_struts&issues=AZ1mePcE6XBGhgATtBlX&open=AZ1mePcE6XBGhgATtBlX&pullRequest=1654
OgnlContext ognlContext = null;

Check warning on line 396 in core/src/main/java/org/apache/struts2/ognl/OgnlUtil.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Provide the parametrized type for this generic.

See more on https://sonarcloud.io/project/issues?id=apache_struts&issues=AZ1mePcE6XBGhgATtBlY&open=AZ1mePcE6XBGhgATtBlY&pullRequest=1654

if (context instanceof OgnlContext oc) {

Check warning on line 398 in core/src/main/java/org/apache/struts2/ognl/OgnlUtil.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Provide the parametrized type for this generic.

See more on https://sonarcloud.io/project/issues?id=apache_struts&issues=AZ1mePcE6XBGhgATtBlZ&open=AZ1mePcE6XBGhgATtBlZ&pullRequest=1654
ognlContext = oc;
}
return node.isSimpleMethod(ognlContext) && !node.isChain(ognlContext);
Expand Down Expand Up @@ -424,7 +424,7 @@
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));
}

Expand All @@ -434,7 +434,7 @@
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));
}

Expand Down Expand Up @@ -548,8 +548,8 @@
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;
Expand Down Expand Up @@ -654,7 +654,7 @@
*/
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();
Expand Down Expand Up @@ -724,18 +724,21 @@
}
}

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
Expand All @@ -762,13 +765,13 @@
* @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);
}
}

Expand All @@ -783,13 +786,13 @@
* @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);
}
}
}
16 changes: 6 additions & 10 deletions core/src/main/java/org/apache/struts2/ognl/OgnlValueStack.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@
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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -121,12 +119,12 @@ protected void setOgnlUtil(OgnlUtil ognlUtil) {
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)
Expand Down Expand Up @@ -508,9 +506,7 @@ private Object readResolve() {

@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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
}

@Inject
@SuppressWarnings({"rawtypes", "unchecked"})
protected void setCompoundRootAccessor(RootAccessor compoundRootAccessor) {
this.compoundRootAccessor = compoundRootAccessor;
OgnlRuntime.setPropertyAccessor(CompoundRoot.class, compoundRootAccessor);
Expand All @@ -61,7 +62,7 @@
}

@Inject
protected void setMethodAccessor(MethodAccessor methodAccessor) {

Check warning on line 65 in core/src/main/java/org/apache/struts2/ognl/OgnlValueStackFactory.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Provide the parametrized type for this generic.

See more on https://sonarcloud.io/project/issues?id=apache_struts&issues=AZ1mePa16XBGhgATtBlP&open=AZ1mePa16XBGhgATtBlP&pullRequest=1654
OgnlRuntime.setMethodAccessor(Object.class, methodAccessor);
}

Expand Down Expand Up @@ -110,6 +111,7 @@
* {@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) {
Expand Down Expand Up @@ -145,6 +147,7 @@
}
}

@SuppressWarnings({"rawtypes", "unchecked"})
protected void registerPropertyAccessors() throws ClassNotFoundException {
Set<String> names = container.getInstanceNames(PropertyAccessor.class);
for (String name : names) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -54,7 +53,7 @@
* 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);

Expand Down Expand Up @@ -115,7 +114,7 @@
}

@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)) {
Expand All @@ -130,7 +129,7 @@
}

@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;
}
Expand All @@ -145,7 +144,7 @@
}

@Override
public boolean isAccessible(OgnlContext context, Object target, Member member, String propertyName) {
public boolean isAccessible(StrutsContext context, Object target, Member member, String propertyName) {

Check failure on line 147 in core/src/main/java/org/apache/struts2/ognl/SecurityMemberAccess.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this method to reduce its Cognitive Complexity from 22 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=apache_struts&issues=AZ1mePbS6XBGhgATtBlQ&open=AZ1mePbS6XBGhgATtBlQ&pullRequest=1654
LOG.debug("Checking access for [target: {}, member: {}, property: {}]", target, member, propertyName);

if (member == null) {
Expand Down
53 changes: 53 additions & 0 deletions core/src/main/java/org/apache/struts2/ognl/StrutsContext.java
Original file line number Diff line number Diff line change
@@ -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);
}
}
Loading
Loading