Introduces new callMethod() function to be used to execute actions
Project: http://git-wip-us.apache.org/repos/asf/struts/repo Commit: http://git-wip-us.apache.org/repos/asf/struts/commit/b28b78c0 Tree: http://git-wip-us.apache.org/repos/asf/struts/tree/b28b78c0 Diff: http://git-wip-us.apache.org/repos/asf/struts/diff/b28b78c0 Branch: refs/heads/support-2-3 Commit: b28b78c062f0bf3c79793a25aab8c9b6c12bce6e Parents: 8d172b8 Author: Lukasz Lenart <lukaszlen...@apache.org> Authored: Fri Jun 3 13:10:58 2016 +0200 Committer: Lukasz Lenart <lukaszlen...@apache.org> Committed: Fri Jun 3 13:10:58 2016 +0200 ---------------------------------------------------------------------- .../xwork2/DefaultActionInvocation.java | 4 +- .../com/opensymphony/xwork2/ognl/OgnlUtil.java | 64 ++++++++++++++++++++ .../opensymphony/xwork2/ognl/OgnlUtilTest.java | 15 +++++ 3 files changed, 81 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/struts/blob/b28b78c0/xwork-core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java ---------------------------------------------------------------------- diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java b/xwork-core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java index fcf397e..d4c995c 100644 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java +++ b/xwork-core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java @@ -427,13 +427,13 @@ public class DefaultActionInvocation implements ActionInvocation { Object methodResult; try { - methodResult = ognlUtil.getValue(methodName + "()", getStack().getContext(), action); + methodResult = ognlUtil.callMethod(methodName + "()", getStack().getContext(), action); } catch (MethodFailedException e) { // if reason is missing method, try find version with "do" prefix if (e.getReason() instanceof NoSuchMethodException) { try { String altMethodName = "do" + methodName.substring(0, 1).toUpperCase() + methodName.substring(1) + "()"; - methodResult = ognlUtil.getValue(altMethodName, getStack().getContext(), action); + methodResult = ognlUtil.callMethod(altMethodName, getStack().getContext(), action); } catch (MethodFailedException e1) { // if still method doesn't exist, try checking UnknownHandlers if (e1.getReason() instanceof NoSuchMethodException) { http://git-wip-us.apache.org/repos/asf/struts/blob/b28b78c0/xwork-core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java ---------------------------------------------------------------------- diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java b/xwork-core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java index 40d112b..42132ba 100644 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java +++ b/xwork-core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java @@ -290,6 +290,9 @@ public class OgnlUtil { 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; } @@ -309,6 +312,32 @@ public class OgnlUtil { return false; } + private boolean isArithmeticExpression(Object tree, Map<String, Object> context) throws OgnlException { + if (tree instanceof SimpleNode) { + SimpleNode node = (SimpleNode) tree; + OgnlContext ognlContext = null; + + if (context!=null && context instanceof OgnlContext) { + ognlContext = (OgnlContext) context; + } + return node.isOperation(ognlContext); + } + return false; + } + + private boolean isSimpleMethod(Object tree, Map<String, Object> context) throws OgnlException { + if (tree instanceof SimpleNode) { + SimpleNode node = (SimpleNode) tree; + OgnlContext ognlContext = null; + + if (context!=null && context instanceof OgnlContext) { + ognlContext = (OgnlContext) context; + } + return node.isSimpleMethod(ognlContext) && !node.isChain(ognlContext); + } + return false; + } + public Object getValue(final String name, final Map<String, Object> context, final Object root) throws OgnlException { return compileAndExecute(name, context, new OgnlTask<Object>() { public Object execute(Object tree) throws OgnlException { @@ -317,6 +346,14 @@ public class OgnlUtil { }); } + public Object callMethod(final String name, final Map<String, Object> context, final Object root) throws OgnlException { + return compileAndExecuteMethod(name, context, new OgnlTask<Object>() { + public Object execute(Object tree) throws OgnlException { + return Ognl.getValue(tree, context, root); + } + }); + } + public Object getValue(final String name, final Map<String, Object> context, final Object root, final Class resultType) throws OgnlException { return compileAndExecute(name, context, new OgnlTask<Object>() { public Object execute(Object tree) throws OgnlException { @@ -351,6 +388,27 @@ public class OgnlUtil { return exec; } + private <T> Object compileAndExecuteMethod(String expression, Map<String, Object> context, OgnlTask<T> task) throws OgnlException { + Object tree; + if (enableExpressionCache) { + tree = expressions.get(expression); + if (tree == null) { + tree = Ognl.parseExpression(expression); + checkSimpleMethod(tree, context); + } + } else { + tree = Ognl.parseExpression(expression); + checkSimpleMethod(tree, context); + } + + final T exec = task.execute(tree); + // if cache is enabled and it's a valid expression, puts it in + if(enableExpressionCache) { + expressions.putIfAbsent(expression, tree); + } + return exec; + } + public Object compile(String expression, Map<String, Object> context) throws OgnlException { return compileAndExecute(expression,context,new OgnlTask<Object>() { public Object execute(Object tree) throws OgnlException { @@ -365,6 +423,12 @@ public class OgnlUtil { } } + private void checkSimpleMethod(Object tree, Map<String, Object> context) throws OgnlException { + if (!isSimpleMethod(tree, context)) { + throw new OgnlException("It isn't a simple method which can be called!"); + } + } + /** * 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 http://git-wip-us.apache.org/repos/asf/struts/blob/b28b78c0/xwork-core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java ---------------------------------------------------------------------- diff --git a/xwork-core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java b/xwork-core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java index a0d3f2b..f8ca5a6 100644 --- a/xwork-core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java +++ b/xwork-core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java @@ -765,6 +765,21 @@ public class OgnlUtilTest extends XWorkTestCase { assertEquals(expected.getMessage(), "Eval expressions/chained expressions have been disabled!"); } + public void testCallMethod() throws Exception { + Foo foo = new Foo(); + + Exception expected = null; + try { + ognlUtil.callMethod("#booScope=@myclass@DEFAULT_SCOPE,#bootScope.init()", ognlUtil.createDefaultContext(foo), foo); + fail(); + } catch (OgnlException e) { + expected = e; + } + assertNotNull(expected); + assertSame(OgnlException.class, expected.getClass()); + assertEquals(expected.getMessage(), "It isn't a simple method which can be called!"); + } + public static class Email { String address;