You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2017/06/01 17:13:08 UTC

[2/3] camel git commit: CAMEL-11377: Optimise - Bean expression invoking bean can use static method instead of creating new objects

CAMEL-11377: Optimise - Bean expression invoking bean can use static method instead of creating new objects


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/32c1f654
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/32c1f654
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/32c1f654

Branch: refs/heads/master
Commit: 32c1f6547a5259be168b5a532bcd21c3cbfc7d63
Parents: a05fde8
Author: Claus Ibsen <da...@apache.org>
Authored: Thu Jun 1 16:29:52 2017 +0200
Committer: Claus Ibsen <da...@apache.org>
Committed: Thu Jun 1 16:29:52 2017 +0200

----------------------------------------------------------------------
 .../camel/language/bean/BeanExpression.java     | 269 +++++++++----------
 1 file changed, 126 insertions(+), 143 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/32c1f654/camel-core/src/main/java/org/apache/camel/language/bean/BeanExpression.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/language/bean/BeanExpression.java b/camel-core/src/main/java/org/apache/camel/language/bean/BeanExpression.java
index 9ff76ba..21255db 100644
--- a/camel-core/src/main/java/org/apache/camel/language/bean/BeanExpression.java
+++ b/camel-core/src/main/java/org/apache/camel/language/bean/BeanExpression.java
@@ -25,7 +25,6 @@ import org.apache.camel.ExchangePattern;
 import org.apache.camel.Expression;
 import org.apache.camel.ExpressionIllegalSyntaxException;
 import org.apache.camel.Predicate;
-import org.apache.camel.Processor;
 import org.apache.camel.component.bean.BeanExpressionProcessor;
 import org.apache.camel.component.bean.BeanHolder;
 import org.apache.camel.component.bean.ConstantBeanHolder;
@@ -110,10 +109,8 @@ public class BeanExpression implements Expression, Predicate {
 
         if (OgnlHelper.isValidOgnlExpression(method)) {
             // okay the method is an ognl expression
-            OgnlInvokeProcessor ognl = new OgnlInvokeProcessor(beanHolder, beanName, method);
             try {
-                ognl.process(exchange);
-                return ognl.getResult();
+                return invokeOgnlMethod(beanHolder, beanName, method, exchange);
             } catch (Exception e) {
                 if (e instanceof RuntimeBeanExpressionException) {
                     throw (RuntimeBeanExpressionException) e;
@@ -227,177 +224,163 @@ public class BeanExpression implements Expression, Predicate {
      * For more advanced OGNL you may have to look for a real framework such as OGNL, Mvel or dynamic
      * programming language such as Groovy, JuEL, JavaScript.
      */
-    private static final class OgnlInvokeProcessor implements Processor {
-
-        private final String ognl;
-        private final BeanHolder beanHolder;
-        private final String beanName;
-        private Object result;
-
-        private OgnlInvokeProcessor(BeanHolder beanHolder, String beanName, String ognl) {
-            this.beanHolder = beanHolder;
-            this.beanName = beanName;
-            this.ognl = ognl;
-            // we must start with having bean as the result
-            this.result = beanHolder.getBean();
+    private static Object invokeOgnlMethod(BeanHolder beanHolder, String beanName, String ognl, Exchange exchange) {
+
+        // we must start with having bean as the result
+        Object result = beanHolder.getBean();
+
+        // copy the original exchange to avoid side effects on it
+        Exchange resultExchange = exchange.copy();
+        // remove any existing exception in case we do OGNL on the exception
+        resultExchange.setException(null);
+        // force to use InOut to retrieve the result on the OUT message
+        resultExchange.setPattern(ExchangePattern.InOut);
+        // do not propagate any method name when using OGNL, as with OGNL we
+        // compute and provide the method name to explicit to invoke
+        resultExchange.getIn().removeHeader(Exchange.BEAN_METHOD_NAME);
+
+        // current ognl path as we go along
+        String ognlPath = "";
+
+        // loop and invoke each method
+        Object beanToCall = beanHolder.getBean();
+        Class<?> beanType = beanHolder.getBeanInfo().getType();
+
+        // there must be a bean to call with, we currently does not support OGNL expressions on using purely static methods
+        if (beanToCall == null && beanType == null) {
+            throw new IllegalArgumentException("Bean instance and bean type is null. OGNL bean expressions requires to have either a bean instance of the class name of the bean to use.");
         }
 
-        public void process(Exchange exchange) throws Exception {
-            // copy the original exchange to avoid side effects on it
-            Exchange resultExchange = exchange.copy();
-            // remove any existing exception in case we do OGNL on the exception
-            resultExchange.setException(null);
-            // force to use InOut to retrieve the result on the OUT message
-            resultExchange.setPattern(ExchangePattern.InOut);
-            // do not propagate any method name when using OGNL, as with OGNL we
-            // compute and provide the method name to explicit to invoke
-            resultExchange.getIn().removeHeader(Exchange.BEAN_METHOD_NAME);
-
-            // current ognl path as we go along
-            String ognlPath = "";
+        if (ognl != null) {
+            // must be a valid method name according to java identifier ruling
+            OgnlHelper.validateMethodName(ognl);
+        }
 
-            // loop and invoke each method
-            Object beanToCall = beanHolder.getBean();
-            Class<?> beanType = beanHolder.getBeanInfo().getType();
+        // Split ognl except when this is not a Map, Array
+        // and we would like to keep the dots within the key name
+        List<String> methods = OgnlHelper.splitOgnl(ognl);
 
-            // there must be a bean to call with, we currently does not support OGNL expressions on using purely static methods
-            if (beanToCall == null && beanType == null) {
-                throw new IllegalArgumentException("Bean instance and bean type is null. OGNL bean expressions requires to have either a bean instance of the class name of the bean to use.");
+        for (String methodName : methods) {
+            BeanHolder holder;
+            if (beanToCall != null) {
+                holder = new ConstantBeanHolder(beanToCall, exchange.getContext());
+            } else if (beanType != null) {
+                holder = new ConstantTypeBeanHolder(beanType, exchange.getContext());
+            } else {
+                holder = null;
             }
 
-            if (ognl != null) {
-                // must be a valid method name according to java identifier ruling
-                OgnlHelper.validateMethodName(ognl);
-            }
+            // support the null safe operator
+            boolean nullSafe = OgnlHelper.isNullSafeOperator(methodName);
 
-            // Split ognl except when this is not a Map, Array
-            // and we would like to keep the dots within the key name
-            List<String> methods = OgnlHelper.splitOgnl(ognl);
-
-            for (String methodName : methods) {
-                BeanHolder holder;
-                if (beanToCall != null) {
-                    holder = new ConstantBeanHolder(beanToCall, exchange.getContext());
-                } else if (beanType != null) {
-                    holder = new ConstantTypeBeanHolder(beanType, exchange.getContext());
-                } else {
-                    holder = null;
-                }
+            if (holder == null) {
+                String name = getBeanName(null, beanHolder);
+                throw new RuntimeBeanExpressionException(exchange, name, ognl, "last method returned null and therefore cannot continue to invoke method " + methodName + " on a null instance");
+            }
 
-                // support the null safe operator
-                boolean nullSafe = OgnlHelper.isNullSafeOperator(methodName);
+            // keep up with how far are we doing
+            ognlPath += methodName;
 
-                if (holder == null) {
-                    String name = getBeanName(null, beanHolder);
-                    throw new RuntimeBeanExpressionException(exchange, name, ognl, "last method returned null and therefore cannot continue to invoke method " + methodName + " on a null instance");
-                }
+            // get rid of leading ?. or . as we only needed that to determine if null safe was enabled or not
+            methodName = OgnlHelper.removeLeadingOperators(methodName);
 
-                // keep up with how far are we doing
-                ognlPath += methodName;
+            // are we doing an index lookup (eg in Map/List/array etc)?
+            String key = null;
+            KeyValueHolder<String, String> index = OgnlHelper.isOgnlIndex(methodName);
+            if (index != null) {
+                methodName = index.getKey();
+                key = index.getValue();
+            }
 
-                // get rid of leading ?. or . as we only needed that to determine if null safe was enabled or not
-                methodName = OgnlHelper.removeLeadingOperators(methodName);
+            // only invoke if we have a method name to use to invoke
+            if (methodName != null) {
+                Object newResult = invokeBean(holder, beanName, methodName, resultExchange);
 
-                // are we doing an index lookup (eg in Map/List/array etc)?
-                String key = null;
-                KeyValueHolder<String, String> index = OgnlHelper.isOgnlIndex(methodName);
-                if (index != null) {
-                    methodName = index.getKey();
-                    key = index.getValue();
+                // check for exception and rethrow if we failed
+                if (resultExchange.getException() != null) {
+                    throw new RuntimeBeanExpressionException(exchange, beanName, methodName, resultExchange.getException());
                 }
 
-                // only invoke if we have a method name to use to invoke
-                if (methodName != null) {
-                    Object newResult = invokeBean(holder, beanName, methodName, resultExchange);
-
-                    // check for exception and rethrow if we failed
-                    if (resultExchange.getException() != null) {
-                        throw new RuntimeBeanExpressionException(exchange, beanName, methodName, resultExchange.getException());
-                    }
+                result = newResult;
+            }
 
-                    result = newResult;
+            // if there was a key then we need to lookup using the key
+            if (key != null) {
+                // if key is a nested simple expression then re-evaluate that again
+                if (SimpleLanguage.hasSimpleFunction(key)) {
+                    key = SimpleLanguage.expression(key).evaluate(exchange, String.class);
                 }
-
-                // if there was a key then we need to lookup using the key
                 if (key != null) {
-                    // if key is a nested simple expression then re-evaluate that again
-                    if (SimpleLanguage.hasSimpleFunction(key)) {
-                        key = SimpleLanguage.expression(key).evaluate(exchange, String.class);
-                    }
-                    if (key != null) {
-                        result = lookupResult(resultExchange, key, result, nullSafe, ognlPath, holder.getBean());
-                    }
-                }
-
-                // check null safe for null results
-                if (result == null && nullSafe) {
-                    return;
+                    result = lookupResult(resultExchange, key, result, nullSafe, ognlPath, holder.getBean());
                 }
+            }
 
-                // prepare for next bean to invoke
-                beanToCall = result;
-                beanType = null;
+            // check null safe for null results
+            if (result == null && nullSafe) {
+                return null;
             }
+
+            // prepare for next bean to invoke
+            beanToCall = result;
+            beanType = null;
         }
 
-        private Object lookupResult(Exchange exchange, String key, Object result, boolean nullSafe, String ognlPath, Object bean) {
-            ObjectHelper.notEmpty(key, "key", "in Simple language ognl path: " + ognlPath);
+        return result;
+    }
 
-            // trim key
-            key = key.trim();
+    private static Object lookupResult(Exchange exchange, String key, Object result, boolean nullSafe, String ognlPath, Object bean) {
+        StringHelper.notEmpty(key, "key", "in Simple language ognl path: " + ognlPath);
 
-            // remove any enclosing quotes
-            key = StringHelper.removeLeadingAndEndingQuotes(key);
+        // trim key
+        key = key.trim();
 
-            // try map first
-            Map<?, ?> map = exchange.getContext().getTypeConverter().convertTo(Map.class, result);
-            if (map != null) {
-                return map.get(key);
-            }
+        // remove any enclosing quotes
+        key = StringHelper.removeLeadingAndEndingQuotes(key);
+
+        // try map first
+        Map<?, ?> map = exchange.getContext().getTypeConverter().convertTo(Map.class, result);
+        if (map != null) {
+            return map.get(key);
+        }
 
-            // special for list is last keyword
-            Integer num = exchange.getContext().getTypeConverter().tryConvertTo(Integer.class, key);
-            boolean checkList = key.startsWith("last") || num != null;
-
-            if (checkList) {
-                List<?> list = exchange.getContext().getTypeConverter().convertTo(List.class, result);
-                if (list != null) {
-                    if (key.startsWith("last")) {
-                        num = list.size() - 1;
-
-                        // maybe its an expression to subtract a number after last
-                        String after = ObjectHelper.after(key, "-");
-                        if (after != null) {
-                            Integer redux = exchange.getContext().getTypeConverter().tryConvertTo(Integer.class, after.trim());
-                            if (redux != null) {
-                                num -= redux;
-                            } else {
-                                throw new ExpressionIllegalSyntaxException(key);
-                            }
+        // special for list is last keyword
+        Integer num = exchange.getContext().getTypeConverter().tryConvertTo(Integer.class, key);
+        boolean checkList = key.startsWith("last") || num != null;
+
+        if (checkList) {
+            List<?> list = exchange.getContext().getTypeConverter().convertTo(List.class, result);
+            if (list != null) {
+                if (key.startsWith("last")) {
+                    num = list.size() - 1;
+
+                    // maybe its an expression to subtract a number after last
+                    String after = StringHelper.after(key, "-");
+                    if (after != null) {
+                        Integer redux = exchange.getContext().getTypeConverter().tryConvertTo(Integer.class, after.trim());
+                        if (redux != null) {
+                            num -= redux;
+                        } else {
+                            throw new ExpressionIllegalSyntaxException(key);
                         }
                     }
-                    if (num != null && num >= 0 && list.size() > num - 1 && list.size() > 0) {
-                        return list.get(num);
-                    }
-                    if (!nullSafe) {
-                        // not null safe then its mandatory so thrown out of bounds exception
-                        throw new IndexOutOfBoundsException("Index: " + num + ", Size: " + list.size()
-                                + " out of bounds with List from bean: " + bean + "using OGNL path [" + ognlPath + "]");
-                    }
                 }
-            }
-
-            if (!nullSafe) {
-                throw new IndexOutOfBoundsException("Key: " + key + " not found in bean: " + bean + " of type: "
-                        + ObjectHelper.classCanonicalName(bean) + " using OGNL path [" + ognlPath + "]");
-            } else {
-                // null safe so we can return null
-                return null;
+                if (num != null && num >= 0 && list.size() > num - 1 && list.size() > 0) {
+                    return list.get(num);
+                }
+                if (!nullSafe) {
+                    // not null safe then its mandatory so thrown out of bounds exception
+                    throw new IndexOutOfBoundsException("Index: " + num + ", Size: " + list.size()
+                            + " out of bounds with List from bean: " + bean + "using OGNL path [" + ognlPath + "]");
+                }
             }
         }
 
-        public Object getResult() {
-            return result;
+        if (!nullSafe) {
+            throw new IndexOutOfBoundsException("Key: " + key + " not found in bean: " + bean + " of type: "
+                    + ObjectHelper.classCanonicalName(bean) + " using OGNL path [" + ognlPath + "]");
+        } else {
+            // null safe so we can return null
+            return null;
         }
     }