From 4fd7bad2f279df72ff08bac0c5cd4232bfbff6f5 Mon Sep 17 00:00:00 2001 From: Allan-QLB Date: Wed, 27 Nov 2024 13:36:06 +0800 Subject: [PATCH 1/2] add parameter ignoreRead in ObjectPropertyAccessor --- .../java/ognl/ObjectPropertyAccessor.java | 16 ++++++++++++- src/main/java/ognl/OgnlRuntime.java | 24 +++++++++++++++++-- .../java/ognl/TestObjectPropertyAccessor.java | 20 ++++++++++++++++ 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/src/main/java/ognl/ObjectPropertyAccessor.java b/src/main/java/ognl/ObjectPropertyAccessor.java index 37143826..c1573062 100644 --- a/src/main/java/ognl/ObjectPropertyAccessor.java +++ b/src/main/java/ognl/ObjectPropertyAccessor.java @@ -31,6 +31,20 @@ */ public class ObjectPropertyAccessor implements PropertyAccessor { + /** + * Ignore detecting and invoking read method when get property value. + */ + private final boolean ignoreReadMethod; + + + public ObjectPropertyAccessor() { + this(false); + } + + public ObjectPropertyAccessor(boolean ignoreReadMethod) { + this.ignoreReadMethod = ignoreReadMethod; + } + /** * Returns OgnlRuntime.NotFound if the property does not exist. * @@ -44,7 +58,7 @@ public Object getPossibleProperty(OgnlContext context, Object target, String nam Object result; try { - if ((result = OgnlRuntime.getMethodValue(context, target, name, true)) == OgnlRuntime.NotFound) { + if ((result = OgnlRuntime.getMethodValue(context, target, name, true, ignoreReadMethod)) == OgnlRuntime.NotFound) { result = OgnlRuntime.getFieldValue(context, target, name, true); } } catch (OgnlException ex) { diff --git a/src/main/java/ognl/OgnlRuntime.java b/src/main/java/ognl/OgnlRuntime.java index 855ac2af..ddb6a7c9 100644 --- a/src/main/java/ognl/OgnlRuntime.java +++ b/src/main/java/ognl/OgnlRuntime.java @@ -1677,7 +1677,7 @@ public static Object callConstructor(OgnlContext context, String className, Obje @Deprecated public static Object getMethodValue(OgnlContext context, Object target, String propertyName) throws OgnlException, IllegalAccessException, NoSuchMethodException, IntrospectionException { - return getMethodValue(context, target, propertyName, false); + return getMethodValue(context, target, propertyName, false, false); } /** @@ -1696,9 +1696,29 @@ public static Object getMethodValue(OgnlContext context, Object target, String p */ public static Object getMethodValue(OgnlContext context, Object target, String propertyName, boolean checkAccessAndExistence) throws OgnlException, IllegalAccessException, NoSuchMethodException { + return getMethodValue(context, target, propertyName, checkAccessAndExistence, false); + } + + /** + * If the checkAccessAndExistence flag is true this method will check to see if the method + * exists and if it is accessible according to the context's MemberAccess. If neither test + * passes this will return NotFound. + * + * @param context the current execution context. + * @param target the object to invoke the property name get on. + * @param propertyName the name of the property to be retrieved from target. + * @param checkAccessAndExistence true if this method should check access levels and existence for propertyName of target, false otherwise. + * @param ignoreReadMethod true if this method should try to detect and invoke read method of the target property, false otherwise. + * @return the result invoking property retrieval of propertyName for target. + * @throws OgnlException for lots of different reasons. + * @throws IllegalAccessException if access not permitted. + * @throws NoSuchMethodException if no property accessor exists. + */ + public static Object getMethodValue(OgnlContext context, Object target, String propertyName, boolean checkAccessAndExistence, boolean ignoreReadMethod) + throws OgnlException, IllegalAccessException, NoSuchMethodException { Object result = null; Method m = getGetMethod((target == null) ? null : target.getClass(), propertyName); - if (m == null) + if (m == null && !ignoreReadMethod) m = getReadMethod((target == null) ? null : target.getClass(), propertyName, null); if (checkAccessAndExistence) { diff --git a/src/test/java/ognl/TestObjectPropertyAccessor.java b/src/test/java/ognl/TestObjectPropertyAccessor.java index c462b636..a3125414 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,22 @@ 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")); + assertEquals(Collections.emptyList(), new ObjectPropertyAccessor(true).getPossibleProperty(Ognl.createDefaultContext(null, new ExcludedObjectMemberAccess(true)), + fetcher, "completedFutures")); + } + public void testSetPossibleProperty() throws OgnlException, IntrospectionException { OgnlContext context = (OgnlContext) this.context; SimplePublicClass simplePublic = new SimplePublicClass(); From f8d6dd7d72821f3e21333530355c296ce2a02579 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=A6=E5=88=A9=E6=96=8C?= <68638598+Allan-QLB@users.noreply.github.com> Date: Fri, 27 Dec 2024 10:45:11 +0800 Subject: [PATCH 2/2] make parameter `ignoreReadMethods` within context scope --- .../java/ognl/ObjectPropertyAccessor.java | 16 +-------- src/main/java/ognl/OgnlContext.java | 34 +++++++++++++++++++ src/main/java/ognl/OgnlRuntime.java | 24 ++----------- src/test/java/ognl/OgnlContextTest.java | 19 ++++++++--- .../java/ognl/TestObjectPropertyAccessor.java | 4 ++- 5 files changed, 55 insertions(+), 42 deletions(-) diff --git a/src/main/java/ognl/ObjectPropertyAccessor.java b/src/main/java/ognl/ObjectPropertyAccessor.java index c1573062..37143826 100644 --- a/src/main/java/ognl/ObjectPropertyAccessor.java +++ b/src/main/java/ognl/ObjectPropertyAccessor.java @@ -31,20 +31,6 @@ */ public class ObjectPropertyAccessor implements PropertyAccessor { - /** - * Ignore detecting and invoking read method when get property value. - */ - private final boolean ignoreReadMethod; - - - public ObjectPropertyAccessor() { - this(false); - } - - public ObjectPropertyAccessor(boolean ignoreReadMethod) { - this.ignoreReadMethod = ignoreReadMethod; - } - /** * Returns OgnlRuntime.NotFound if the property does not exist. * @@ -58,7 +44,7 @@ public Object getPossibleProperty(OgnlContext context, Object target, String nam Object result; try { - if ((result = OgnlRuntime.getMethodValue(context, target, name, true, ignoreReadMethod)) == OgnlRuntime.NotFound) { + if ((result = OgnlRuntime.getMethodValue(context, target, name, true)) == OgnlRuntime.NotFound) { result = OgnlRuntime.getFieldValue(context, target, name, true); } } catch (OgnlException ex) { 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 ddb6a7c9..ef21eefa 100644 --- a/src/main/java/ognl/OgnlRuntime.java +++ b/src/main/java/ognl/OgnlRuntime.java @@ -1677,7 +1677,7 @@ public static Object callConstructor(OgnlContext context, String className, Obje @Deprecated public static Object getMethodValue(OgnlContext context, Object target, String propertyName) throws OgnlException, IllegalAccessException, NoSuchMethodException, IntrospectionException { - return getMethodValue(context, target, propertyName, false, false); + return getMethodValue(context, target, propertyName, false); } /** @@ -1696,29 +1696,9 @@ public static Object getMethodValue(OgnlContext context, Object target, String p */ public static Object getMethodValue(OgnlContext context, Object target, String propertyName, boolean checkAccessAndExistence) throws OgnlException, IllegalAccessException, NoSuchMethodException { - return getMethodValue(context, target, propertyName, checkAccessAndExistence, false); - } - - /** - * If the checkAccessAndExistence flag is true this method will check to see if the method - * exists and if it is accessible according to the context's MemberAccess. If neither test - * passes this will return NotFound. - * - * @param context the current execution context. - * @param target the object to invoke the property name get on. - * @param propertyName the name of the property to be retrieved from target. - * @param checkAccessAndExistence true if this method should check access levels and existence for propertyName of target, false otherwise. - * @param ignoreReadMethod true if this method should try to detect and invoke read method of the target property, false otherwise. - * @return the result invoking property retrieval of propertyName for target. - * @throws OgnlException for lots of different reasons. - * @throws IllegalAccessException if access not permitted. - * @throws NoSuchMethodException if no property accessor exists. - */ - public static Object getMethodValue(OgnlContext context, Object target, String propertyName, boolean checkAccessAndExistence, boolean ignoreReadMethod) - throws OgnlException, IllegalAccessException, NoSuchMethodException { Object result = null; Method m = getGetMethod((target == null) ? null : target.getClass(), propertyName); - if (m == null && !ignoreReadMethod) + 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 a3125414..77c8dc2e 100644 --- a/src/test/java/ognl/TestObjectPropertyAccessor.java +++ b/src/test/java/ognl/TestObjectPropertyAccessor.java @@ -84,7 +84,9 @@ public void testGetPossibleProperty() throws OgnlException { OgnlContext context = (OgnlContext) this.context; KafkaFetcher fetcher = new KafkaFetcher(); assertEquals(Boolean.FALSE, propertyAccessor.getPossibleProperty(context, fetcher, "completedFutures")); - assertEquals(Collections.emptyList(), new ObjectPropertyAccessor(true).getPossibleProperty(Ognl.createDefaultContext(null, new ExcludedObjectMemberAccess(true)), + OgnlContext defaultContext = Ognl.createDefaultContext(null, new ExcludedObjectMemberAccess(true)); + defaultContext.setIgnoreReadMethods(true); + assertEquals(Collections.emptyList(), new ObjectPropertyAccessor().getPossibleProperty(defaultContext, fetcher, "completedFutures")); }