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 2016/05/03 08:37:20 UTC

[2/2] camel git commit: CAMEL-5252: Simple language. Lazy eval nested functions that avoid provisional conversion to String value when using simple in method call OGNL expression style. This allows to call methods with the nested functions as-is.

CAMEL-5252: Simple language. Lazy eval nested functions that avoid provisional conversion to String value when using simple in method call OGNL expression style. This allows to call methods with the nested functions as-is.


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

Branch: refs/heads/master
Commit: b3a208aecd9ef57a74c9da27cbec87806148eef5
Parents: d659cd3
Author: Claus Ibsen <da...@apache.org>
Authored: Mon May 2 14:30:55 2016 +0200
Committer: Claus Ibsen <da...@apache.org>
Committed: Tue May 3 08:37:07 2016 +0200

----------------------------------------------------------------------
 .../apache/camel/builder/ExpressionBuilder.java | 151 ++++++++++++-------
 .../camel/language/simple/SimpleLanguage.java   |   4 +
 .../camel/language/simple/SimpleTokenizer.java  |  18 ++-
 .../simple/ast/SimpleFunctionExpression.java    |  14 +-
 .../simple/ast/SimpleFunctionStart.java         |   7 +-
 .../SimpleParserExpressionInvalidTest.java      |   3 +-
 .../camel/language/simple/SimpleTest.java       |  38 +++--
 .../camel/component/sql/stored/ParserTest.java  |  10 +-
 8 files changed, 168 insertions(+), 77 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/b3a208ae/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java b/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java
index 7b11ca6..2f0f296 100644
--- a/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java
+++ b/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java
@@ -44,6 +44,7 @@ import org.apache.camel.Producer;
 import org.apache.camel.component.bean.BeanInvocation;
 import org.apache.camel.component.properties.PropertiesComponent;
 import org.apache.camel.language.bean.BeanLanguage;
+import org.apache.camel.language.simple.SimpleLanguage;
 import org.apache.camel.model.language.MethodCallExpression;
 import org.apache.camel.processor.DefaultExchangeFormatter;
 import org.apache.camel.spi.ExchangeFormatter;
@@ -126,10 +127,11 @@ public final class ExpressionBuilder {
     public static Expression headerExpression(final String headerName) {
         return new ExpressionAdapter() {
             public Object evaluate(Exchange exchange) {
-                Object header = exchange.getIn().getHeader(headerName);
+                String name = simpleExpression(headerName).evaluate(exchange, String.class);
+                Object header = exchange.getIn().getHeader(name);
                 if (header == null) {
                     // fall back on a property
-                    header = exchange.getProperty(headerName);
+                    header = exchange.getProperty(name);
                 }
                 return header;
             }
@@ -153,10 +155,11 @@ public final class ExpressionBuilder {
     public static <T> Expression headerExpression(final String headerName, final Class<T> type) {
         return new ExpressionAdapter() {
             public Object evaluate(Exchange exchange) {
-                Object header = exchange.getIn().getHeader(headerName, type);
+                String name = simpleExpression(headerName).evaluate(exchange, String.class);
+                Object header = exchange.getIn().getHeader(name, type);
                 if (header == null) {
                     // fall back on a property
-                    header = exchange.getProperty(headerName, type);
+                    header = exchange.getProperty(name, type);
                 }
                 return header;
             }
@@ -174,30 +177,32 @@ public final class ExpressionBuilder {
      * Will fallback and look in properties if not found in headers.
      *
      * @param headerName the name of the header the expression will return
-     * @param name the type to convert to as a FQN class name
+     * @param typeName the type to convert to as a FQN class name
      * @return an expression object which will return the header value
      */
-    public static Expression headerExpression(final String headerName, final String name) {
+    public static Expression headerExpression(final String headerName, final String typeName) {
         return new ExpressionAdapter() {
             public Object evaluate(Exchange exchange) {
                 Class<?> type;
                 try {
-                    type = exchange.getContext().getClassResolver().resolveMandatoryClass(name);
+                    String text = simpleExpression(typeName).evaluate(exchange, String.class);
+                    type = exchange.getContext().getClassResolver().resolveMandatoryClass(text);
                 } catch (ClassNotFoundException e) {
                     throw ObjectHelper.wrapCamelExecutionException(exchange, e);
                 }
 
-                Object header = exchange.getIn().getHeader(headerName, type);
+                String text = simpleExpression(headerName).evaluate(exchange, String.class);
+                Object header = exchange.getIn().getHeader(text, type);
                 if (header == null) {
                     // fall back on a property
-                    header = exchange.getProperty(headerName, type);
+                    header = exchange.getProperty(text, type);
                 }
                 return header;
             }
 
             @Override
             public String toString() {
-                return "headerAs(" + headerName + ", " + name + ")";
+                return "headerAs(" + headerName + ", " + typeName + ")";
             }
         };
     }
@@ -212,7 +217,8 @@ public final class ExpressionBuilder {
         return new KeyedOgnlExpressionAdapter(ognl, "headerOgnl(" + ognl + ")",
             new KeyedOgnlExpressionAdapter.KeyedEntityRetrievalStrategy() {
                 public Object getKeyedEntity(Exchange exchange, String key) {
-                    return exchange.getIn().getHeader(key);
+                    String text = simpleExpression(key).evaluate(exchange, String.class);
+                    return exchange.getIn().getHeader(text);
                 }
             });
     }
@@ -250,11 +256,12 @@ public final class ExpressionBuilder {
                     return null;
                 }
 
+                String text = simpleExpression(headerName).evaluate(exchange, String.class);
                 Message out = exchange.getOut();
-                Object header = out.getHeader(headerName);
+                Object header = out.getHeader(text);
                 if (header == null) {
                     // let's try the exchange header
-                    header = exchange.getProperty(headerName);
+                    header = exchange.getProperty(text);
                 }
                 return header;
             }
@@ -376,6 +383,9 @@ public final class ExpressionBuilder {
                 if (exception == null) {
                     return null;
                 }
+
+                // ognl is able to evaluate method name if it contains nested functions
+                // so we should not eager evaluate ognl as a string
                 return new MethodCallExpression(exception, ognl).evaluate(exchange);
             }
 
@@ -430,7 +440,8 @@ public final class ExpressionBuilder {
     public static Expression refExpression(final String ref) {
         return new ExpressionAdapter() {
             public Object evaluate(Exchange exchange) {
-                return exchange.getContext().getRegistry().lookupByName(ref);
+                String text = simpleExpression(ref).evaluate(exchange, String.class);
+                return exchange.getContext().getRegistry().lookupByName(text);
             }
 
             @Override
@@ -540,7 +551,8 @@ public final class ExpressionBuilder {
     public static Expression propertyExpression(final String propertyName) {
         return new ExpressionAdapter() {
             public Object evaluate(Exchange exchange) {
-                return exchange.getProperty(propertyName);
+                String text = simpleExpression(propertyName).evaluate(exchange, String.class);
+                return exchange.getProperty(text);
             }
 
             @Override
@@ -559,7 +571,8 @@ public final class ExpressionBuilder {
     public static Expression exchangePropertyExpression(final String propertyName) {
         return new ExpressionAdapter() {
             public Object evaluate(Exchange exchange) {
-                return exchange.getProperty(propertyName);
+                String text = simpleExpression(propertyName).evaluate(exchange, String.class);
+                return exchange.getProperty(text);
             }
 
             @Override
@@ -579,7 +592,8 @@ public final class ExpressionBuilder {
         return new KeyedOgnlExpressionAdapter(ognl, "propertyOgnl(" + ognl + ")",
             new KeyedOgnlExpressionAdapter.KeyedEntityRetrievalStrategy() {
                 public Object getKeyedEntity(Exchange exchange, String key) {
-                    return exchange.getProperty(key);
+                    String text = simpleExpression(key).evaluate(exchange, String.class);
+                    return exchange.getProperty(text);
                 }
             });
     }
@@ -629,7 +643,8 @@ public final class ExpressionBuilder {
     public static Expression camelContextPropertyExpression(final String propertyName) {
         return new ExpressionAdapter() {
             public Object evaluate(Exchange exchange) {
-                return exchange.getContext().getProperty(propertyName);
+                String text = simpleExpression(propertyName).evaluate(exchange, String.class);
+                return exchange.getContext().getProperty(text);
             }
 
             @Override
@@ -660,7 +675,9 @@ public final class ExpressionBuilder {
                                                       final String defaultValue) {
         return new ExpressionAdapter() {
             public Object evaluate(Exchange exchange) {
-                return System.getProperty(propertyName, defaultValue);
+                String text = simpleExpression(propertyName).evaluate(exchange, String.class);
+                String text2 = simpleExpression(defaultValue).evaluate(exchange, String.class);
+                return System.getProperty(text, text2);
             }
 
             @Override
@@ -691,9 +708,11 @@ public final class ExpressionBuilder {
                                                          final String defaultValue) {
         return new ExpressionAdapter() {
             public Object evaluate(Exchange exchange) {
-                String answer = System.getenv(propertyName);
+                String text = simpleExpression(propertyName).evaluate(exchange, String.class);
+                String answer = System.getenv(text);
                 if (answer == null) {
-                    answer = defaultValue;
+                    String text2 = simpleExpression(defaultValue).evaluate(exchange, String.class);
+                    answer = text2;
                 }
                 return answer;
             }
@@ -768,22 +787,23 @@ public final class ExpressionBuilder {
         return new ExpressionAdapter() {
             public Object evaluate(Exchange exchange) {
                 // it may refer to a class type
-                Class<?> type = exchange.getContext().getClassResolver().resolveClass(name);
+                String text = simpleExpression(name).evaluate(exchange, String.class);
+                Class<?> type = exchange.getContext().getClassResolver().resolveClass(text);
                 if (type != null) {
                     return type;
                 }
 
-                int pos = name.lastIndexOf(".");
+                int pos = text.lastIndexOf(".");
                 if (pos > 0) {
-                    String before = name.substring(0, pos);
-                    String after = name.substring(pos + 1);
+                    String before = text.substring(0, pos);
+                    String after = text.substring(pos + 1);
                     type = exchange.getContext().getClassResolver().resolveClass(before);
                     if (type != null) {
                         return ObjectHelper.lookupConstantFieldValue(type, after);
                     }
                 }
 
-                throw ObjectHelper.wrapCamelExecutionException(exchange, new ClassNotFoundException("Cannot find type " + name));
+                throw ObjectHelper.wrapCamelExecutionException(exchange, new ClassNotFoundException("Cannot find type " + text));
             }
 
             @Override
@@ -849,6 +869,8 @@ public final class ExpressionBuilder {
                 if (body == null) {
                     return null;
                 }
+                // ognl is able to evaluate method name if it contains nested functions
+                // so we should not eager evaluate ognl as a string
                 return new MethodCallExpression(body, ognl).evaluate(exchange);
             }
 
@@ -872,6 +894,8 @@ public final class ExpressionBuilder {
                 if (value == null) {
                     return null;
                 }
+                // ognl is able to evaluate method name if it contains nested functions
+                // so we should not eager evaluate ognl as a string
                 return new MethodCallExpression(value, ognl).evaluate(exchange);
             }
 
@@ -895,6 +919,8 @@ public final class ExpressionBuilder {
                 if (context == null) {
                     return null;
                 }
+                // ognl is able to evaluate method name if it contains nested functions
+                // so we should not eager evaluate ognl as a string
                 return new MethodCallExpression(context, ognl).evaluate(exchange);
             }
 
@@ -914,6 +940,8 @@ public final class ExpressionBuilder {
     public static Expression exchangeOgnlExpression(final String ognl) {
         return new ExpressionAdapter() {
             public Object evaluate(Exchange exchange) {
+                // ognl is able to evaluate method name if it contains nested functions
+                // so we should not eager evaluate ognl as a string
                 return new MethodCallExpression(exchange, ognl).evaluate(exchange);
             }
 
@@ -948,9 +976,10 @@ public final class ExpressionBuilder {
     public static Expression bodyExpression(final String name) {
         return new ExpressionAdapter() {
             public Object evaluate(Exchange exchange) {
+                String text = simpleExpression(name).evaluate(exchange, String.class);
                 Class<?> type;
                 try {
-                    type = exchange.getContext().getClassResolver().resolveMandatoryClass(name);
+                    type = exchange.getContext().getClassResolver().resolveMandatoryClass(text);
                 } catch (ClassNotFoundException e) {
                     throw ObjectHelper.wrapCamelExecutionException(exchange, e);
                 }
@@ -971,9 +1000,10 @@ public final class ExpressionBuilder {
     public static Expression mandatoryBodyExpression(final String name) {
         return new ExpressionAdapter() {
             public Object evaluate(Exchange exchange) {
+                String text = simpleExpression(name).evaluate(exchange, String.class);
                 Class<?> type;
                 try {
-                    type = exchange.getContext().getClassResolver().resolveMandatoryClass(name);
+                    type = exchange.getContext().getClassResolver().resolveMandatoryClass(text);
                 } catch (ClassNotFoundException e) {
                     throw ObjectHelper.wrapCamelExecutionException(exchange, e);
                 }
@@ -1265,9 +1295,10 @@ public final class ExpressionBuilder {
                                                 final String token) {
         return new ExpressionAdapter() {
             public Object evaluate(Exchange exchange) {
+                String text = simpleExpression(token).evaluate(exchange, String.class);
                 Object value = expression.evaluate(exchange, Object.class);
                 Scanner scanner = ObjectHelper.getScanner(exchange, value);
-                scanner.useDelimiter(token);
+                scanner.useDelimiter(text);
                 return scanner;
             }
 
@@ -1522,10 +1553,10 @@ public final class ExpressionBuilder {
      * expressions
      *
      * @param expressions the expression to be concatenated dynamically
-     * @param expression the text description of the expression
+     * @param desription the text description of the expression
      * @return an expression which when evaluated will return the concatenated values
      */
-    public static Expression concatExpression(final Collection<Expression> expressions, final String expression) {
+    public static Expression concatExpression(final Collection<Expression> expressions, final String desription) {
         return new ExpressionAdapter() {
             public Object evaluate(Exchange exchange) {
                 StringBuilder buffer = new StringBuilder();
@@ -1540,8 +1571,8 @@ public final class ExpressionBuilder {
 
             @Override
             public String toString() {
-                if (expression != null) {
-                    return expression;
+                if (desription != null) {
+                    return desription;
                 } else {
                     return "concat" + expressions;
                 }
@@ -1628,7 +1659,7 @@ public final class ExpressionBuilder {
                 } else if ("file".equals(command)) {
                     Long num = exchange.getIn().getHeader(Exchange.FILE_LAST_MODIFIED, Long.class);
                     if (num != null && num > 0) {
-                        date = new Date(num.longValue());
+                        date = new Date(num);
                     } else {
                         date = exchange.getIn().getHeader(Exchange.FILE_LAST_MODIFIED, Date.class);
                         if (date == null) {
@@ -1653,11 +1684,15 @@ public final class ExpressionBuilder {
     public static Expression simpleExpression(final String expression) {
         return new ExpressionAdapter() {
             public Object evaluate(Exchange exchange) {
-                // resolve language using context to have a clear separation of packages
-                // must call evaluate to return the nested language evaluate when evaluating
-                // stacked expressions
-                Language language = exchange.getContext().resolveLanguage("simple");
-                return language.createExpression(expression).evaluate(exchange, Object.class);
+                if (SimpleLanguage.hasSimpleFunction(expression)) {
+                    // resolve language using context to have a clear separation of packages
+                    // must call evaluate to return the nested language evaluate when evaluating
+                    // stacked expressions
+                    Language language = exchange.getContext().resolveLanguage("simple");
+                    return language.createExpression(expression).evaluate(exchange, Object.class);
+                } else {
+                    return expression;
+                }
             }
 
             @Override
@@ -1670,6 +1705,8 @@ public final class ExpressionBuilder {
     public static Expression beanExpression(final String expression) {
         return new ExpressionAdapter() {
             public Object evaluate(Exchange exchange) {
+                // bean is able to evaluate method name if it contains nested functions
+                // so we should not eager evaluate expression as a string
                 // resolve language using context to have a clear separation of packages
                 // must call evaluate to return the nested language evaluate when evaluating
                 // stacked expressions
@@ -1685,7 +1722,7 @@ public final class ExpressionBuilder {
     }
     
     public static Expression beanExpression(final Class<?> beanType, final String methodName) {
-        return BeanLanguage.bean(beanType, methodName);        
+        return BeanLanguage.bean(beanType, methodName);
     }
 
     public static Expression beanExpression(final Object bean, final String methodName) {
@@ -1706,9 +1743,10 @@ public final class ExpressionBuilder {
     public static Expression toExpression(final String uri) {
         return new ExpressionAdapter() {
             public Object evaluate(Exchange exchange) {
-                Endpoint endpoint = exchange.getContext().getEndpoint(uri);
+                String text = simpleExpression(uri).evaluate(exchange, String.class);
+                Endpoint endpoint = exchange.getContext().getEndpoint(text);
                 if (endpoint == null) {
-                    throw new NoSuchEndpointException(uri);
+                    throw new NoSuchEndpointException(text);
                 }
 
                 Producer producer;
@@ -1942,16 +1980,18 @@ public final class ExpressionBuilder {
     public static Expression propertiesComponentExpression(final String key, final String locations) {
         return new ExpressionAdapter() {
             public Object evaluate(Exchange exchange) {
+                String text = simpleExpression(key).evaluate(exchange, String.class);
+                String text2 = simpleExpression(locations).evaluate(exchange, String.class);
                 try {
-                    if (locations != null) {
+                    if (text2 != null) {
                         // the properties component is optional as we got locations
                         // getComponent will create a new component if none already exists
                         Component component = exchange.getContext().getComponent("properties");
                         PropertiesComponent pc = exchange.getContext().getTypeConverter()
                                 .mandatoryConvertTo(PropertiesComponent.class, component);
                         // enclose key with {{ }} to force parsing
-                        String[] paths = locations.split(",");
-                        return pc.parseUri(pc.getPrefixToken() + key + pc.getSuffixToken(), paths);
+                        String[] paths = text2.split(",");
+                        return pc.parseUri(pc.getPrefixToken() + text + pc.getSuffixToken(), paths);
                     } else {
                         // the properties component is mandatory if no locations provided
                         Component component = exchange.getContext().hasComponent("properties");
@@ -1962,7 +2002,7 @@ public final class ExpressionBuilder {
                         PropertiesComponent pc = exchange.getContext().getTypeConverter()
                                 .mandatoryConvertTo(PropertiesComponent.class, component);
                         // enclose key with {{ }} to force parsing
-                        return pc.parseUri(pc.getPrefixToken() + key + pc.getSuffixToken());
+                        return pc.parseUri(pc.getPrefixToken() + text + pc.getSuffixToken());
                     }
                 } catch (Exception e) {
                     throw ObjectHelper.wrapRuntimeCamelException(e);
@@ -1975,7 +2015,14 @@ public final class ExpressionBuilder {
             }
         };
     }
-    
+
+    /**
+     * Returns a random number between 0 and upperbound (exclusive)
+     */
+    public static Expression randomExpression(final int upperbound) {
+        return randomExpression(0, upperbound);
+    }
+
     /**
      * Returns a random number between min and max
      */
@@ -1993,15 +2040,17 @@ public final class ExpressionBuilder {
             }
         };
     }
-    
+
     /**
-     * Returns a random number between 0 and upperbound (exclusive)
+     * Returns a random number between min and max
      */
-    public static Expression randomExpression(final int upperbound) {
+    public static Expression randomExpression(final String min, final String max) {
         return new ExpressionAdapter() {
             public Object evaluate(Exchange exchange) {
+                int num1 = simpleExpression(min).evaluate(exchange, Integer.class);
+                int num2 = simpleExpression(max).evaluate(exchange, Integer.class);
                 Random random = new Random();
-                int randomNum = random.nextInt(upperbound);
+                int randomNum = random.nextInt(num2 - num1) + num1;
                 return randomNum;
             }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/b3a208ae/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java b/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java
index 16d8d14..d77ec36 100644
--- a/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java
+++ b/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java
@@ -101,6 +101,10 @@ public class SimpleLanguage extends LanguageSupport {
     public SimpleLanguage() {
     }
 
+    public static boolean hasSimpleFunction(String expression) {
+        return SimpleTokenizer.hasFunctionStartToken(expression);
+    }
+
     public Predicate createPredicate(String expression) {
         ObjectHelper.notNull(expression, "expression");
 

http://git-wip-us.apache.org/repos/asf/camel/blob/b3a208ae/camel-core/src/main/java/org/apache/camel/language/simple/SimpleTokenizer.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/language/simple/SimpleTokenizer.java b/camel-core/src/main/java/org/apache/camel/language/simple/SimpleTokenizer.java
index 1d5438a..85bb775 100644
--- a/camel-core/src/main/java/org/apache/camel/language/simple/SimpleTokenizer.java
+++ b/camel-core/src/main/java/org/apache/camel/language/simple/SimpleTokenizer.java
@@ -34,15 +34,15 @@ public final class SimpleTokenizer {
 
     static {
         // add known tokens
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.functionStart, "${"));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.functionStart, "$simple{"));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.functionEnd, "}"));
         KNOWN_TOKENS.add(new SimpleTokenType(TokenType.whiteSpace, " "));
         KNOWN_TOKENS.add(new SimpleTokenType(TokenType.whiteSpace, "\t"));
         KNOWN_TOKENS.add(new SimpleTokenType(TokenType.whiteSpace, "\n"));
         KNOWN_TOKENS.add(new SimpleTokenType(TokenType.whiteSpace, "\r"));
         KNOWN_TOKENS.add(new SimpleTokenType(TokenType.singleQuote, "'"));
         KNOWN_TOKENS.add(new SimpleTokenType(TokenType.doubleQuote, "\""));
-        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.functionStart, "${"));
-        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.functionStart, "$simple{"));
-        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.functionEnd, "}"));
         KNOWN_TOKENS.add(new SimpleTokenType(TokenType.booleanValue, "true"));
         KNOWN_TOKENS.add(new SimpleTokenType(TokenType.booleanValue, "false"));
         KNOWN_TOKENS.add(new SimpleTokenType(TokenType.nullValue, "null"));
@@ -85,6 +85,18 @@ public final class SimpleTokenizer {
         // static methods
     }
 
+    public static boolean hasFunctionStartToken(String expression) {
+        if (expression != null) {
+            for (SimpleTokenType type : KNOWN_TOKENS) {
+                if (type.getType() == TokenType.functionStart) {
+                    if (expression.contains(type.getValue())) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
 
     /**
      * @see SimpleLanguage#changeFunctionStartToken(String...)

http://git-wip-us.apache.org/repos/asf/camel/blob/b3a208ae/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java b/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
index 8948931..49cc299 100644
--- a/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
+++ b/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
@@ -34,6 +34,11 @@ public class SimpleFunctionExpression extends LiteralExpression {
         super(token);
     }
 
+    /**
+     * Creates a Camel {@link Expression} based on this model.
+     *
+     * @param expression not in use
+     */
     @Override
     public Expression createExpression(String expression) {
         String function = text.toString();
@@ -43,7 +48,7 @@ public class SimpleFunctionExpression extends LiteralExpression {
     /**
      * Creates a Camel {@link Expression} based on this model.
      *
-     * @param expression the input string
+     * @param expression not in use
      * @param strict whether to throw exception if the expression was not a function,
      *          otherwise <tt>null</tt> is returned
      * @return the created {@link Expression}
@@ -412,12 +417,9 @@ public class SimpleFunctionExpression extends LiteralExpression {
                 if (tokens.length > 2) {
                     throw new SimpleParserException("Valid syntax: ${random(min,max)} or ${random(max)} was: " + function, token.getIndex());
                 }
-                int min = Integer.parseInt(tokens[0].trim());
-                int max = Integer.parseInt(tokens[1].trim());
-                return ExpressionBuilder.randomExpression(min, max);
+                return ExpressionBuilder.randomExpression(tokens[0].trim(), tokens[1].trim());
             } else {
-                int max = Integer.parseInt(values.trim());
-                return ExpressionBuilder.randomExpression(max);
+                return ExpressionBuilder.randomExpression("0", values.trim());
             }
         }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/b3a208ae/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionStart.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionStart.java b/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionStart.java
index 840e1e5..24ab4d8 100644
--- a/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionStart.java
+++ b/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionStart.java
@@ -72,8 +72,8 @@ public class SimpleFunctionStart extends BaseSimpleNode implements BlockStart {
                         String text = ((LiteralNode) child).getText();
                         sb.append(text);
                         quoteEmbeddedFunctions |= ((LiteralNode) child).quoteEmbeddedNodes();
-                    // if its a function or quoted literal, then embed that as text
-                    } else if (child instanceof SimpleFunctionStart || child instanceof SingleQuoteStart || child instanceof DoubleQuoteStart) {
+                    // if its quoted literal then embed that as text
+                    } else if (child instanceof SingleQuoteStart || child instanceof DoubleQuoteStart) {
                         try {
                             // pass in null when we evaluate the nested expressions
                             Expression nested = child.createExpression(null);
@@ -89,6 +89,9 @@ public class SimpleFunctionStart extends BaseSimpleNode implements BlockStart {
                             // must rethrow parser exception as illegal syntax with details about the location
                             throw new SimpleIllegalSyntaxException(expression, e.getIndex(), e.getMessage(), e);
                         }
+                    // if its an inlined function then embed that function as text so it can be evaluated lazy
+                    } else if (child instanceof SimpleFunctionStart) {
+                        sb.append(child);
                     }
                 }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/b3a208ae/camel-core/src/test/java/org/apache/camel/language/simple/SimpleParserExpressionInvalidTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/language/simple/SimpleParserExpressionInvalidTest.java b/camel-core/src/test/java/org/apache/camel/language/simple/SimpleParserExpressionInvalidTest.java
index 69fe8a2..c7fb8a3 100644
--- a/camel-core/src/test/java/org/apache/camel/language/simple/SimpleParserExpressionInvalidTest.java
+++ b/camel-core/src/test/java/org/apache/camel/language/simple/SimpleParserExpressionInvalidTest.java
@@ -61,7 +61,8 @@ public class SimpleParserExpressionInvalidTest extends ExchangeTestSupport {
             parser.parseExpression().evaluate(exchange, String.class);
             fail("Should thrown exception");
         } catch (SimpleIllegalSyntaxException e) {
-            assertEquals(15, e.getIndex());
+            // its a nested function is it reset the index
+            assertEquals(0, e.getIndex());
         }
     }
     

http://git-wip-us.apache.org/repos/asf/camel/blob/b3a208ae/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java b/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java
index c0cd5c0..ada8265 100644
--- a/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java
+++ b/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java
@@ -1514,31 +1514,36 @@ public class SimpleTest extends LanguageTestSupport {
         int iterations = 30;
         int i = 0;
         for (i = 0; i < iterations; i++) {
-            Expression expression = SimpleLanguage.simple("random(1,10)", Integer.class);
+            Expression expression = SimpleLanguage.simple("${random(1,10)}", Integer.class);
             assertTrue(min <= expression.evaluate(exchange, Integer.class) && expression.evaluate(exchange, Integer.class) < max);
         }
         for (i = 0; i < iterations; i++) {
-            Expression expression = SimpleLanguage.simple("random(10)", Integer.class);
+            Expression expression = SimpleLanguage.simple("${random(10)}", Integer.class);
             assertTrue(0 <= expression.evaluate(exchange, Integer.class) && expression.evaluate(exchange, Integer.class) < max);
         }
-        Expression expression = SimpleLanguage.simple("random(1, 10)", Integer.class);
+        Expression expression = SimpleLanguage.simple("${random(1, 10)}", Integer.class);
         assertTrue(min <= expression.evaluate(exchange, Integer.class) && expression.evaluate(exchange, Integer.class) < max);
         
-        Expression expression1 = SimpleLanguage.simple("random( 10)", Integer.class);
+        Expression expression1 = SimpleLanguage.simple("${random( 10)}", Integer.class);
         assertTrue(0 <= expression1.evaluate(exchange, Integer.class) && expression1.evaluate(exchange, Integer.class) < max);
         
         try {
-            assertExpression("random(10,21,30)", null);
+            assertExpression("${random(10,21,30)}", null);
             fail("Should have thrown exception");
-        } catch (SimpleParserException e) {
-            assertEquals("Valid syntax: ${random(min,max)} or ${random(max)} was: random(10,21,30)", e.getMessage());
+        } catch (Exception e) {
+            assertEquals("Valid syntax: ${random(min,max)} or ${random(max)} was: random(10,21,30)", e.getCause().getMessage());
         }
         try {
-            assertExpression("random()", null);
+            assertExpression("${random()}", null);
             fail("Should have thrown exception");
-        } catch (SimpleParserException e) {
-            assertEquals("Valid syntax: ${random(min,max)} or ${random(max)} was: random()", e.getMessage());
+        } catch (Exception e) {
+            assertEquals("Valid syntax: ${random(min,max)} or ${random(max)} was: random()", e.getCause().getMessage());
         }
+
+        exchange.getIn().setHeader("max", 20);
+        Expression expression3 = SimpleLanguage.simple("${random(10,${header.max})}", Integer.class);
+        int num = expression3.evaluate(exchange, Integer.class);
+        assertTrue("Should be 10..20", num >= 0 && num < 20);
     }
 
     public void testListRemoveByInstance() throws Exception {
@@ -1571,6 +1576,19 @@ public class SimpleTest extends LanguageTestSupport {
         assertEquals("B", data.get(0));
     }
 
+    public void testBodyOgnlOnAnimalWithOgnlParams() throws Exception {
+        exchange.getIn().setBody(new Animal("tiger", 13));
+        exchange.getIn().setHeader("friend", new Animal("donkey", 4));
+        assertExpression("${body.setFriend(${header.friend})}", null);
+
+        Animal animal = exchange.getIn().getBody(Animal.class);
+        assertEquals("tiger", animal.getName());
+        assertEquals(13, animal.getAge());
+        assertNotNull("Should have a friend", animal.getFriend());
+        assertEquals("donkey", animal.getFriend().getName());
+        assertEquals(4, animal.getFriend().getAge());
+    }
+
     protected String getLanguageName() {
         return "simple";
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/b3a208ae/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ParserTest.java
----------------------------------------------------------------------
diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ParserTest.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ParserTest.java
index d9e8810..5ed96c4 100644
--- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ParserTest.java
+++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ParserTest.java
@@ -51,7 +51,7 @@ public class ParserTest extends CamelTestSupport {
         InputParameter param1 = (InputParameter) template.getParameterList().get(0);
         Assert.assertEquals("_0", param1.getName());
         Assert.assertEquals(Types.INTEGER, param1.getSqlType());
-        Assert.assertEquals(Integer.valueOf(1), param1.getValueExtractor().eval(exchange, null));
+        Assert.assertEquals(1, param1.getValueExtractor().eval(exchange, null));
 
         InputParameter param2 = (InputParameter) template.getParameterList().get(1);
         Assert.assertEquals("_1", param2.getName());
@@ -85,14 +85,16 @@ public class ParserTest extends CamelTestSupport {
     @Test
     public void nestedSimpleExpression() {
         Exchange exchange = createExchangeWithBody(1);
-        exchange.getIn().setHeader("body", "body");
-        Template template = parser.parseTemplate("ADDNUMBERS2(INTEGER ${${header.body}})");
+        exchange.getIn().setHeader("foo", 1);
+        exchange.getIn().setHeader("bar", 3);
+        Template template = parser.parseTemplate("ADDNUMBERS2(INTEGER ${header.foo},INTEGER ${header.bar})");
         assertEquals(1, ((InputParameter) template.getParameterList().get(0)).getValueExtractor().eval(exchange, null));
+        assertEquals(3, ((InputParameter) template.getParameterList().get(1)).getValueExtractor().eval(exchange, null));
     }
 
     @Test
     public void vendorSpeficSqlType() {
-        Template template = parser.parseTemplate("ADDNUMBERS2(1342 ${${header.body}})");
+        Template template = parser.parseTemplate("ADDNUMBERS2(1342 ${header.foo})");
         assertEquals(1342, ((InputParameter) template.getParameterList().get(0)).getSqlType());
     }