diff --git a/src/main/java/ognl/OgnlContext.java b/src/main/java/ognl/OgnlContext.java index 3d937c08..8e01ded3 100644 --- a/src/main/java/ognl/OgnlContext.java +++ b/src/main/java/ognl/OgnlContext.java @@ -39,7 +39,9 @@ public class OgnlContext implements Map { private static final String TRACE_EVALUATIONS_CONTEXT_KEY = "_traceEvaluations"; private static final String LAST_EVALUATION_CONTEXT_KEY = "_lastEvaluation"; private static final String KEEP_LAST_EVALUATION_CONTEXT_KEY = "_keepLastEvaluation"; + private static final String IGNORE_READ_METHODS_CONTEXT_KEY = "_ignoreReadMethods"; private static final String PROPERTY_KEY_PREFIX = "ognl"; + private static final boolean DEFAULT_IGNORE_READ_METHODS = false; private static boolean DEFAULT_TRACE_EVALUATIONS = false; private static boolean DEFAULT_KEEP_LAST_EVALUATION = false; @@ -53,6 +55,7 @@ public class OgnlContext implements Map { private Evaluation currentEvaluation; private Evaluation lastEvaluation; private boolean keepLastEvaluation = DEFAULT_KEEP_LAST_EVALUATION; + private boolean ignoreReadMethods = DEFAULT_IGNORE_READ_METHODS; private final Map internalContext; @@ -67,6 +70,7 @@ public class OgnlContext implements Map { RESERVED_KEYS.put(TRACE_EVALUATIONS_CONTEXT_KEY, null); RESERVED_KEYS.put(LAST_EVALUATION_CONTEXT_KEY, null); RESERVED_KEYS.put(KEEP_LAST_EVALUATION_CONTEXT_KEY, null); + RESERVED_KEYS.put(IGNORE_READ_METHODS_CONTEXT_KEY, null); try { String property; @@ -242,6 +246,26 @@ public void setKeepLastEvaluation(boolean value) { keepLastEvaluation = value; } + + /** + * Returns true if read methods of properties are ignored when accessing properties. The default is false. + * + * @return true if read methods of properties are ignored when accessing properties, false otherwise. + */ + public boolean isIgnoreReadMethods() { + return ignoreReadMethods; + } + + + /** + * Sets read methods of properties are ignored when accessing properties. The default is false. + * + * @param value true if read methods of properties are ignored when accessing properties, false otherwise. + */ + public void setIgnoreReadMethods(boolean value) { + this.ignoreReadMethods = value; + } + public void setCurrentObject(Object value) { currentObject = value; } @@ -476,6 +500,9 @@ public Object get(Object key) { case OgnlContext.KEEP_LAST_EVALUATION_CONTEXT_KEY: result = isKeepLastEvaluation() ? Boolean.TRUE : Boolean.FALSE; break; + case OgnlContext.IGNORE_READ_METHODS_CONTEXT_KEY: + result = isIgnoreReadMethods() ? Boolean.TRUE : Boolean.FALSE; + break; default: throw new IllegalArgumentException("unknown reserved key '" + key + "'"); } @@ -511,6 +538,10 @@ public Object put(String key, Object value) { result = isKeepLastEvaluation() ? Boolean.TRUE : Boolean.FALSE; setKeepLastEvaluation(OgnlOps.booleanValue(value)); break; + case OgnlContext.IGNORE_READ_METHODS_CONTEXT_KEY: + result = isIgnoreReadMethods() ? Boolean.TRUE : Boolean.FALSE; + setIgnoreReadMethods(OgnlOps.booleanValue(value)); + break; default: throw new IllegalArgumentException("unknown reserved key '" + key + "'"); } @@ -549,6 +580,9 @@ public Object remove(Object key) { case OgnlContext.KEEP_LAST_EVALUATION_CONTEXT_KEY: throw new IllegalArgumentException("Can't remove " + OgnlContext.KEEP_LAST_EVALUATION_CONTEXT_KEY + " from context"); + case OgnlContext.IGNORE_READ_METHODS_CONTEXT_KEY: + throw new IllegalArgumentException("Can't remove " + + OgnlContext.IGNORE_READ_METHODS_CONTEXT_KEY + " from context"); default: throw new IllegalArgumentException("Unknown reserved key '" + key + "'"); } diff --git a/src/main/java/ognl/OgnlRuntime.java b/src/main/java/ognl/OgnlRuntime.java index 855ac2af..ef21eefa 100644 --- a/src/main/java/ognl/OgnlRuntime.java +++ b/src/main/java/ognl/OgnlRuntime.java @@ -1698,7 +1698,7 @@ public static Object getMethodValue(OgnlContext context, Object target, String p throws OgnlException, IllegalAccessException, NoSuchMethodException { Object result = null; Method m = getGetMethod((target == null) ? null : target.getClass(), propertyName); - if (m == null) + if (m == null && !context.isIgnoreReadMethods()) m = getReadMethod((target == null) ? null : target.getClass(), propertyName, null); if (checkAccessAndExistence) { diff --git a/src/test/java/ognl/OgnlContextTest.java b/src/test/java/ognl/OgnlContextTest.java index 3d14029c..35cc227a 100644 --- a/src/test/java/ognl/OgnlContextTest.java +++ b/src/test/java/ognl/OgnlContextTest.java @@ -24,10 +24,7 @@ import java.util.HashMap; import java.util.Map; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; class OgnlContextTest { @@ -125,4 +122,18 @@ void currentEvaluation_shouldNotBeNull() throws OgnlException { private static OgnlContext createOgnlContext() { return new OgnlContext(null, null, new DefaultMemberAccess(false)); } + + @Test + void ignoreReadMethod() { + OgnlContext context = createOgnlContext(); + assertFalse(context.isIgnoreReadMethods()); + assertEquals(Boolean.FALSE, context.get("_ignoreReadMethods")); + context.setIgnoreReadMethods(true); + assertTrue(context.isIgnoreReadMethods()); + assertEquals(Boolean.TRUE, context.get("_ignoreReadMethods")); + assertEquals(Boolean.TRUE, context.put("_ignoreReadMethods", false)); + assertFalse(context.isIgnoreReadMethods()); + assertEquals(Boolean.FALSE, context.get("_ignoreReadMethods")); + assertThrows(IllegalArgumentException.class, () -> context.remove("_ignoreReadMethods")); + } } diff --git a/src/test/java/ognl/TestObjectPropertyAccessor.java b/src/test/java/ognl/TestObjectPropertyAccessor.java index c462b636..77c8dc2e 100644 --- a/src/test/java/ognl/TestObjectPropertyAccessor.java +++ b/src/test/java/ognl/TestObjectPropertyAccessor.java @@ -19,7 +19,11 @@ import java.beans.IntrospectionException; import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.Map; +import java.util.concurrent.Future; /** * Tests various methods / functionality of {@link ObjectPropertyAccessor}. @@ -68,6 +72,24 @@ public void setage(String age) { } } + public static class KafkaFetcher { + private final List> completedFutures = new ArrayList<>(); + + public boolean hasCompletedFutures() { + return !completedFutures.isEmpty(); + } + } + + public void testGetPossibleProperty() throws OgnlException { + OgnlContext context = (OgnlContext) this.context; + KafkaFetcher fetcher = new KafkaFetcher(); + assertEquals(Boolean.FALSE, propertyAccessor.getPossibleProperty(context, fetcher, "completedFutures")); + OgnlContext defaultContext = Ognl.createDefaultContext(null, new ExcludedObjectMemberAccess(true)); + defaultContext.setIgnoreReadMethods(true); + assertEquals(Collections.emptyList(), new ObjectPropertyAccessor().getPossibleProperty(defaultContext, + fetcher, "completedFutures")); + } + public void testSetPossibleProperty() throws OgnlException, IntrospectionException { OgnlContext context = (OgnlContext) this.context; SimplePublicClass simplePublic = new SimplePublicClass();