This is an automated email from the ASF dual-hosted git repository. kusal pushed a commit to branch WW-5340-ognlutil-refactor in repository https://gitbox.apache.org/repos/asf/struts.git
commit 452cb774a92fb65627afbb4827f931d55b64d520 Author: Kusal Kithul-Godage <g...@kusal.io> AuthorDate: Thu Aug 31 17:20:46 2023 +1000 WW-5340 Refactor OgnlUtil, specifically calls to Ognl#getValue,setValue,parseExpression --- .../com/opensymphony/xwork2/ognl/OgnlUtil.java | 99 ++++++++++------------ 1 file changed, 47 insertions(+), 52 deletions(-) diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java index 005d17eba..beee54cb4 100644 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java +++ b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java @@ -529,8 +529,7 @@ public class OgnlUtil { } /** - * Wrapper around Ognl.setValue() to handle type conversion for collection elements. - * Ideally, this should be handled by OGNL directly. + * Wrapper around Ognl#setValue * * @param name the name * @param context context map @@ -540,16 +539,7 @@ public class OgnlUtil { * @throws OgnlException in case of ognl errors */ public void setValue(final String name, final Map<String, Object> context, final Object root, final Object value) throws OgnlException { - compileAndExecute(name, context, (OgnlTask<Void>) tree -> { - if (isEvalExpression(tree, context)) { - throw new OgnlException("Eval expression/chained expressions cannot be used as parameter name"); - } - if (isArithmeticExpression(tree, context)) { - throw new OgnlException("Arithmetic expressions cannot be used as parameter name"); - } - Ognl.setValue(tree, context, root, value); - return null; - }); + ognlSet(name, context, root, value, context, this::checkEnableEvalExpression, this::checkEvalExpression, this::checkArithmeticExpression); } private boolean isEvalExpression(Object tree, Map<String, Object> context) throws OgnlException { @@ -592,58 +582,55 @@ public class OgnlUtil { } public Object getValue(final String name, final Map<String, Object> context, final Object root) throws OgnlException { - return compileAndExecute(name, context, tree -> Ognl.getValue(tree, context, root)); + return getValue(name, context, root, null); } public Object callMethod(final String name, final Map<String, Object> context, final Object root) throws OgnlException { - return compileAndExecuteMethod(name, context, tree -> Ognl.getValue(tree, context, root)); + return ognlGet(name, context, root, null, context, this::checkSimpleMethod); } public Object getValue(final String name, final Map<String, Object> context, final Object root, final Class<?> resultType) throws OgnlException { - return compileAndExecute(name, context, tree -> Ognl.getValue(tree, context, root, resultType)); + return ognlGet(name, context, root, resultType, context, this::checkEnableEvalExpression); } - public Object compile(String expression) throws OgnlException { return compile(expression, null); } - private <T> Object compileAndExecute(String expression, Map<String, Object> context, OgnlTask<T> task) throws OgnlException { - Object tree; - if (enableExpressionCache) { - tree = expressionCache.get(expression); - if (tree == null) { - tree = Ognl.parseExpression(expression); - checkEnableEvalExpression(tree, context); - expressionCache.putIfAbsent(expression, tree); - } - } else { - tree = Ognl.parseExpression(expression); - checkEnableEvalExpression(tree, context); + private void ognlSet(String expr, Map<String, Object> context, Object root, Object value, Map<String, Object> checkContext, TreeCheck ...treeChecks) throws OgnlException { + Object tree = toTree(expr); + for (TreeCheck check : treeChecks) { + check.consume(tree, checkContext); } + Ognl.setValue(tree, context, root, value); + } - return task.execute(tree); + private <T> T ognlGet(String expr, Map<String, Object> context, Object root, Class<T> resultType, Map<String, Object> checkContext, TreeCheck ...treeChecks) throws OgnlException { + Object tree = toTree(expr); + for (TreeCheck check : treeChecks) { + check.consume(tree, checkContext); + } + return (T) Ognl.getValue(tree, context, root, resultType); } - private <T> Object compileAndExecuteMethod(String expression, Map<String, Object> context, OgnlTask<T> task) throws OgnlException { - Object tree; + private Object toTree(String expr) throws OgnlException { + Object tree = null; if (enableExpressionCache) { - tree = expressionCache.get(expression); - if (tree == null) { - tree = Ognl.parseExpression(expression); - checkSimpleMethod(tree, context); - expressionCache.putIfAbsent(expression, tree); + tree = expressionCache.get(expr); + } + if (tree == null) { + tree = Ognl.parseExpression(expr); + if (enableExpressionCache) { + expressionCache.put(expr, tree); } - } else { - tree = Ognl.parseExpression(expression); - checkSimpleMethod(tree, context); } - - return task.execute(tree); + return tree; } public Object compile(String expression, Map<String, Object> context) throws OgnlException { - return compileAndExecute(expression, context, tree -> tree); + Object tree = toTree(expression); + checkEnableEvalExpression(tree, context); + return tree; } private void checkEnableEvalExpression(Object tree, Map<String, Object> context) throws OgnlException { @@ -658,6 +645,18 @@ public class OgnlUtil { } } + private void checkEvalExpression(Object tree, Map<String, Object> context) throws OgnlException { + if (isEvalExpression(tree, context)) { + throw new OgnlException("Eval expression/chained expressions cannot be used as parameter name"); + } + } + + private void checkArithmeticExpression(Object tree, Map<String, Object> context) throws OgnlException { + if (isArithmeticExpression(tree, context)) { + throw new OgnlException("Arithmetic expressions cannot be used as parameter name"); + } + } + /** * Copies the properties in the object "from" and sets them in the object "to" * using specified type converter, or {@link com.opensymphony.xwork2.conversion.impl.XWorkConverter} if none @@ -732,12 +731,8 @@ public class OgnlUtil { PropertyDescriptor toPd = toPdHash.get(fromPd.getName()); if ((toPd != null) && (toPd.getWriteMethod() != null)) { try { - compileAndExecute(fromPd.getName(), context, expr -> { - Object value = Ognl.getValue(expr, contextFrom, from); - Ognl.setValue(expr, contextTo, to, value); - return null; - }); - + Object value = ognlGet(fromPd.getName(), contextFrom, from, null, context, this::checkEnableEvalExpression); + ognlSet(fromPd.getName(), contextTo, to, value, context); } catch (OgnlException e) { LOG.debug("Got OGNL exception", e); } @@ -809,7 +804,7 @@ public class OgnlUtil { final String propertyName = propertyDescriptor.getDisplayName(); Method readMethod = propertyDescriptor.getReadMethod(); if (readMethod != null) { - final Object value = compileAndExecute(propertyName, null, expr -> Ognl.getValue(expr, sourceMap, source)); + final Object value = ognlGet(propertyName, sourceMap, source, null, null, this::checkEnableEvalExpression); beanMap.put(propertyName, value); } else { beanMap.put(propertyName, "There is no read method for " + propertyName); @@ -899,8 +894,8 @@ public class OgnlUtil { return Ognl.createDefaultContext(root, memberAccess, resolver, defaultConverter); } - private interface OgnlTask<T> { - T execute(Object tree) throws OgnlException; + @FunctionalInterface + private interface TreeCheck { + void consume(Object tree, Map<String, Object> context) throws OgnlException; } - }