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;
}
}