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;
 

Reply via email to