This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 4c0096f66d95 camel-core - Add safeQuote function to simple language
4c0096f66d95 is described below
commit 4c0096f66d95909a23cba98f9768e7cffcebddb3
Author: Claus Ibsen <[email protected]>
AuthorDate: Fri Jan 30 17:59:09 2026 +0100
camel-core - Add safeQuote function to simple language
---
.../org/apache/camel/catalog/languages/simple.json | 53 +++++++++---------
.../language/csimple/joor/OriginalSimpleTest.java | 49 ++++++++++++++++-
.../JsonPathSimpleInitBlockFunctionTest.java | 4 +-
.../org/apache/camel/language/simple/simple.json | 53 +++++++++---------
.../modules/languages/pages/simple-language.adoc | 18 +++++++
.../camel/language/csimple/CSimpleHelper.java | 13 +++++
.../camel/language/simple/SimpleConstants.java | 4 ++
.../language/simple/SimpleExpressionBuilder.java | 62 ++++++++++++++++++++++
.../simple/ast/SimpleFunctionExpression.java | 34 ++++++++++++
.../apache/camel/language/simple/SimpleTest.java | 47 ++++++++++++++++
10 files changed, 282 insertions(+), 55 deletions(-)
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/simple.json
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/simple.json
index d6c522ed7dc5..aef6018b1262 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/simple.json
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/simple.json
@@ -107,31 +107,32 @@
"reverse(val...)": { "index": 80, "kind": "function", "displayName":
"Reverse Values", "group": "function", "label": "function", "required": false,
"javaType": "List", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns a list of all the
values, but in reverse order", "ognl": false, "suffix": "}" },
"routeGroup": { "index": 81, "kind": "function", "displayName": "Route
Group", "group": "function", "label": "function", "required": false,
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "The route group of the
current route the Exchange is being routed. Not all routes have a group
assigned, so this may be null.", "ognl": false, "suffix": "}" },
"routeId": { "index": 82, "kind": "function", "displayName": "Route Id",
"group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "The route id of the
current route the Exchange is being routed", "ognl": false, "suffix": "}" },
- "setVariable(key,exp)": { "index": 83, "kind": "function", "displayName":
"Set Variable", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Sets an attachment
with payload from the message body\/expression.", "ognl": false, "suffix": "}"
},
- "setHeader(name,type,exp)": { "index": 84, "kind": "function",
"displayName": "Set Header", "group": "function", "label": "function",
"required": false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Sets a message header with the given expression (optional converting to the
given type)", "ognl": false, "suffix": "}" },
- "setVariable(name,type,exp)": { "index": 85, "kind": "function",
"displayName": "Set Variable", "group": "function", "label": "function",
"required": false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Sets a variable with the given expression (optional converting to the given
type)", "ognl": false, "suffix": "}" },
- "shuffle(val...)": { "index": 86, "kind": "function", "displayName":
"Shuffle Values", "group": "function", "label": "function", "required": false,
"javaType": "List", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns a list of all the
values shuffled in random order", "ognl": false, "suffix": "}" },
- "size(exp)": { "index": 87, "kind": "function", "displayName": "Size",
"group": "function", "label": "function", "required": false, "javaType": "int",
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "description": "Returns the number of elements in collection
or array based payloads. If the value is null then 0 is returned, otherwise
1.", "ognl": false, "suffix": "}" },
- "skip(num)": { "index": 88, "kind": "function", "displayName": "Skip First
Items from the Message Body", "group": "function", "label": "function",
"required": false, "javaType": "java.util.Iterator", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The skip function iterates the message body and skips
the first number of items. This can be used with the Splitter EIP to split a
message body and skip the first N number of [...]
- "split(exp,separator)": { "index": 89, "kind": "function", "displayName":
"Split String Values", "group": "function", "label": "function", "required":
false, "javaType": "String[]", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Splits the message body\/expression as a String value using the separator into
a String array", "ognl": false, "suffix": "}" },
- "stepId": { "index": 90, "kind": "function", "displayName": "Step Id",
"group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the id of the
current step the Exchange is being routed.", "ognl": false, "suffix": "}" },
- "substring(head,tail)": { "index": 91, "kind": "function", "displayName":
"Substring", "group": "function", "label": "function", "required": false,
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Returns a substring of
the message body\/expression. If only one positive number, then the returned
string is clipped from the beginning. If only one negative number, then the
returned string is clipped fr [...]
- "substringAfter(exp,before)": { "index": 92, "kind": "function",
"displayName": "Substring After", "group": "function", "label": "function",
"required": false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Returns a substring of the message body\/expression that comes after. Returns
null if nothing comes after.", "ognl": false, "suffix": "}" },
- "substringBefore(exp,before)": { "index": 93, "kind": "function",
"displayName": "Substring Before", "group": "function", "label": "function",
"required": false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Returns a substring of the message body\/expression that comes before. Returns
null if nothing comes before.", "ognl": false, "suffix": "}" },
- "substringBetween(exp,after,before)": { "index": 94, "kind": "function",
"displayName": "Substring Between", "group": "function", "label": "function",
"required": false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Returns a substring of the message body\/expression that are between after and
before. Returns null if nothing comes between.", "ognl": false, "suffix": "}" },
- "sum(val...)": { "index": 95, "kind": "function", "displayName":
"Calculate Sum Number", "group": "function", "label": "function", "required":
false, "javaType": "long", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Sums together all the values as integral numbers. This function can also be
used to subtract by using negative numbers.", "ognl": false, "suffix": "}" },
- "sys.name": { "index": 96, "kind": "function", "displayName": "JVM System
Property", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "The JVM system
property with the given name", "ognl": false, "suffix": "}" },
- "threadId": { "index": 97, "kind": "function", "displayName": "Thread Id",
"group": "function", "label": "function", "required": false, "javaType":
"long", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the id of the
current thread. Can be used for logging.", "ognl": false, "suffix": "}" },
- "threadName": { "index": 98, "kind": "function", "displayName": "Thread
Name", "group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the name of the
current thread. Can be used for logging.", "ognl": false, "suffix": "}" },
- "throwException(type,msg)": { "index": 99, "kind": "function",
"displayName": "Throw Exception", "group": "function", "label": "function",
"required": false, "javaType": "java.lang.Exception", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "Deliberately throws an error. Uses
IllegalArgumentException by default if no type is specified (use fully
qualified classname).", "ognl": false, "suffix": "}" },
- "trim(exp)": { "index": 100, "kind": "function", "displayName": "Trim",
"group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "The trim function trims
the message body (or expression) by removing all leading and trailing white
spaces.", "ognl": false, "suffix": "}" },
- "type:name.field": { "index": 101, "kind": "function", "displayName":
"Java Field Value", "group": "function", "label": "function", "required":
false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "To
refer to a type or field by its classname. To refer to a field, you can append
.FIELD_NAME. For example, you can refer to the constant field from Exchange as:
`org.apache.camel.Exchange.FILE_NAME`", [...]
- "kindOfType(exp)": { "index": 102, "kind": "function", "displayName":
"Kind of Type", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "What kind of type is
the value (null,number,string,boolean,array,object)", "ognl": false, "suffix":
"}" },
- "uppercase(exp)": { "index": 103, "kind": "function", "displayName":
"Uppercase", "group": "function", "label": "function", "required": false,
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Uppercases the message
body (or expression)", "ognl": false, "suffix": "}" },
- "uuid(type)": { "index": 104, "kind": "function", "displayName": "Generate
UUID", "group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns a UUID using the
Camel `UuidGenerator`. You can choose between `default`, `classic`, `short` and
`simple` as the type. If no type is given, the default is used. It is also
possible to use a custom `Uuid [...]
- "variable.name": { "index": 105, "kind": "function", "displayName":
"Variable", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "The variable with the
given name", "ognl": true, "suffix": "}" },
- "variableAs(key,type)": { "index": 106, "kind": "function", "displayName":
"Variable As", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Converts the variable
to the given type (classname).", "ognl": false, "suffix": "}" },
- "variables": { "index": 107, "kind": "function", "displayName":
"Variables", "group": "function", "label": "function", "required": false,
"javaType": "java.util.Map", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Returns all the variables from the current Exchange in a Map", "ognl": false,
"suffix": "}" },
- "xpath(input,exp)": { "index": 108, "kind": "function", "displayName":
"XPath", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "When working with XML
data, then this allows using the XPath language, for example, to extract data
from the message body (in XML format). This requires having camel-xpath JAR on
the classpath. For input (optiona [...]
+ "safeQuote(exp)": { "index": 83, "kind": "function", "displayName": "Safe
Quote", "group": "function", "label": "function", "required": false,
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Returns the message
body (or expression) safely quoted if needed", "ognl": false, "suffix": "}" },
+ "setVariable(key,exp)": { "index": 84, "kind": "function", "displayName":
"Set Variable", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Sets an attachment
with payload from the message body\/expression.", "ognl": false, "suffix": "}"
},
+ "setHeader(name,type,exp)": { "index": 85, "kind": "function",
"displayName": "Set Header", "group": "function", "label": "function",
"required": false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Sets a message header with the given expression (optional converting to the
given type)", "ognl": false, "suffix": "}" },
+ "setVariable(name,type,exp)": { "index": 86, "kind": "function",
"displayName": "Set Variable", "group": "function", "label": "function",
"required": false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Sets a variable with the given expression (optional converting to the given
type)", "ognl": false, "suffix": "}" },
+ "shuffle(val...)": { "index": 87, "kind": "function", "displayName":
"Shuffle Values", "group": "function", "label": "function", "required": false,
"javaType": "List", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns a list of all the
values shuffled in random order", "ognl": false, "suffix": "}" },
+ "size(exp)": { "index": 88, "kind": "function", "displayName": "Size",
"group": "function", "label": "function", "required": false, "javaType": "int",
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "description": "Returns the number of elements in collection
or array based payloads. If the value is null then 0 is returned, otherwise
1.", "ognl": false, "suffix": "}" },
+ "skip(num)": { "index": 89, "kind": "function", "displayName": "Skip First
Items from the Message Body", "group": "function", "label": "function",
"required": false, "javaType": "java.util.Iterator", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The skip function iterates the message body and skips
the first number of items. This can be used with the Splitter EIP to split a
message body and skip the first N number of [...]
+ "split(exp,separator)": { "index": 90, "kind": "function", "displayName":
"Split String Values", "group": "function", "label": "function", "required":
false, "javaType": "String[]", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Splits the message body\/expression as a String value using the separator into
a String array", "ognl": false, "suffix": "}" },
+ "stepId": { "index": 91, "kind": "function", "displayName": "Step Id",
"group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the id of the
current step the Exchange is being routed.", "ognl": false, "suffix": "}" },
+ "substring(head,tail)": { "index": 92, "kind": "function", "displayName":
"Substring", "group": "function", "label": "function", "required": false,
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Returns a substring of
the message body\/expression. If only one positive number, then the returned
string is clipped from the beginning. If only one negative number, then the
returned string is clipped fr [...]
+ "substringAfter(exp,before)": { "index": 93, "kind": "function",
"displayName": "Substring After", "group": "function", "label": "function",
"required": false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Returns a substring of the message body\/expression that comes after. Returns
null if nothing comes after.", "ognl": false, "suffix": "}" },
+ "substringBefore(exp,before)": { "index": 94, "kind": "function",
"displayName": "Substring Before", "group": "function", "label": "function",
"required": false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Returns a substring of the message body\/expression that comes before. Returns
null if nothing comes before.", "ognl": false, "suffix": "}" },
+ "substringBetween(exp,after,before)": { "index": 95, "kind": "function",
"displayName": "Substring Between", "group": "function", "label": "function",
"required": false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Returns a substring of the message body\/expression that are between after and
before. Returns null if nothing comes between.", "ognl": false, "suffix": "}" },
+ "sum(val...)": { "index": 96, "kind": "function", "displayName":
"Calculate Sum Number", "group": "function", "label": "function", "required":
false, "javaType": "long", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Sums together all the values as integral numbers. This function can also be
used to subtract by using negative numbers.", "ognl": false, "suffix": "}" },
+ "sys.name": { "index": 97, "kind": "function", "displayName": "JVM System
Property", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "The JVM system
property with the given name", "ognl": false, "suffix": "}" },
+ "threadId": { "index": 98, "kind": "function", "displayName": "Thread Id",
"group": "function", "label": "function", "required": false, "javaType":
"long", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the id of the
current thread. Can be used for logging.", "ognl": false, "suffix": "}" },
+ "threadName": { "index": 99, "kind": "function", "displayName": "Thread
Name", "group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the name of the
current thread. Can be used for logging.", "ognl": false, "suffix": "}" },
+ "throwException(type,msg)": { "index": 100, "kind": "function",
"displayName": "Throw Exception", "group": "function", "label": "function",
"required": false, "javaType": "java.lang.Exception", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "Deliberately throws an error. Uses
IllegalArgumentException by default if no type is specified (use fully
qualified classname).", "ognl": false, "suffix": "}" },
+ "trim(exp)": { "index": 101, "kind": "function", "displayName": "Trim",
"group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "The trim function trims
the message body (or expression) by removing all leading and trailing white
spaces.", "ognl": false, "suffix": "}" },
+ "type:name.field": { "index": 102, "kind": "function", "displayName":
"Java Field Value", "group": "function", "label": "function", "required":
false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "To
refer to a type or field by its classname. To refer to a field, you can append
.FIELD_NAME. For example, you can refer to the constant field from Exchange as:
`org.apache.camel.Exchange.FILE_NAME`", [...]
+ "kindOfType(exp)": { "index": 103, "kind": "function", "displayName":
"Kind of Type", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "What kind of type is
the value (null,number,string,boolean,array,object)", "ognl": false, "suffix":
"}" },
+ "uppercase(exp)": { "index": 104, "kind": "function", "displayName":
"Uppercase", "group": "function", "label": "function", "required": false,
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Uppercases the message
body (or expression)", "ognl": false, "suffix": "}" },
+ "uuid(type)": { "index": 105, "kind": "function", "displayName": "Generate
UUID", "group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns a UUID using the
Camel `UuidGenerator`. You can choose between `default`, `classic`, `short` and
`simple` as the type. If no type is given, the default is used. It is also
possible to use a custom `Uuid [...]
+ "variable.name": { "index": 106, "kind": "function", "displayName":
"Variable", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "The variable with the
given name", "ognl": true, "suffix": "}" },
+ "variableAs(key,type)": { "index": 107, "kind": "function", "displayName":
"Variable As", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Converts the variable
to the given type (classname).", "ognl": false, "suffix": "}" },
+ "variables": { "index": 108, "kind": "function", "displayName":
"Variables", "group": "function", "label": "function", "required": false,
"javaType": "java.util.Map", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Returns all the variables from the current Exchange in a Map", "ognl": false,
"suffix": "}" },
+ "xpath(input,exp)": { "index": 109, "kind": "function", "displayName":
"XPath", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "When working with XML
data, then this allows using the XPath language, for example, to extract data
from the message body (in XML format). This requires having camel-xpath JAR on
the classpath. For input (optiona [...]
}
}
diff --git
a/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleTest.java
b/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleTest.java
index 1591bdcc7590..6e7d6a2ebd12 100644
---
a/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleTest.java
+++
b/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleTest.java
@@ -2635,6 +2635,53 @@ public class OriginalSimpleTest extends
LanguageTestSupport {
assertEquals("\"Hi\"", s);
}
+ @Test
+ public void testSafeQuote() {
+ exchange.getMessage().setBody("Hello World");
+
+ Expression expression =
context.resolveLanguage("csimple").createExpression("${safeQuote()}");
+ String s = expression.evaluate(exchange, String.class);
+ assertEquals("\"Hello World\"", s);
+
+ expression =
context.resolveLanguage("csimple").createExpression("${safeQuote(${body})}");
+ s = expression.evaluate(exchange, String.class);
+ assertEquals("\"Hello World\"", s);
+
+ expression =
context.resolveLanguage("csimple").createExpression("${safeQuote('Hi')}");
+ s = expression.evaluate(exchange, String.class);
+ assertEquals("\"Hi\"", s);
+
+ expression =
context.resolveLanguage("csimple").createExpression("${safeQuote(''Hi'')}");
+ s = expression.evaluate(exchange, String.class);
+ assertEquals("\"Hi\"", s);
+
+ exchange.getMessage().setBody(123);
+ expression =
context.resolveLanguage("csimple").createExpression("${safeQuote()}");
+ s = expression.evaluate(exchange, String.class);
+ assertEquals("123", s);
+
+ expression =
context.resolveLanguage("csimple").createExpression("${safeQuote(${body})}");
+ s = expression.evaluate(exchange, String.class);
+ assertEquals("123", s);
+
+ exchange.getMessage().setBody(true);
+ expression =
context.resolveLanguage("csimple").createExpression("${safeQuote()}");
+ s = expression.evaluate(exchange, String.class);
+ assertEquals("true", s);
+
+ expression =
context.resolveLanguage("csimple").createExpression("${safeQuote(${body})}");
+ s = expression.evaluate(exchange, String.class);
+ assertEquals("true", s);
+
+ Map<String, String> m = new LinkedHashMap<>();
+ m.put("A", "1");
+ m.put("B", "2");
+ exchange.getMessage().setBody(m);
+ expression =
context.resolveLanguage("csimple").createExpression("${safeQuote()}");
+ s = expression.evaluate(exchange, String.class);
+ assertEquals("\"{A=1, B=2}\"", s);
+ }
+
@Test
public void testTrim() {
exchange.getMessage().setBody(" Hello World ");
@@ -2879,7 +2926,7 @@ public class OriginalSimpleTest extends
LanguageTestSupport {
Integer i = expression.evaluate(exchange, Integer.class);
assertEquals(987, i);
- expression =
context.resolveLanguage("simple").createExpression("${abs(-5)}");
+ expression =
context.resolveLanguage("csimple").createExpression("${abs(-5)}");
i = expression.evaluate(exchange, Integer.class);
assertEquals(5, i);
diff --git
a/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSimpleInitBlockFunctionTest.java
b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSimpleInitBlockFunctionTest.java
index 4dbd116bd935..195a40ce2fd8 100644
---
a/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSimpleInitBlockFunctionTest.java
+++
b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSimpleInitBlockFunctionTest.java
@@ -35,8 +35,8 @@ public class JsonPathSimpleInitBlockFunctionTest extends
CamelTestSupport {
"id": "$id",
"type": "$type",
"amount": $price,
- "oldStatus": $price ~> $level() ~> ${quote()}
- "status": ${newStatus($price)} ~> $level() ~> ${quote()}
+ "oldStatus": $price ~> $level() ~> ${safeQuote()}
+ "status": ${newStatus($price)} ~> $level() ~> ${safeQuote()}
}
""";
diff --git
a/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/simple/simple.json
b/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/simple/simple.json
index d6c522ed7dc5..aef6018b1262 100644
---
a/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/simple/simple.json
+++
b/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/simple/simple.json
@@ -107,31 +107,32 @@
"reverse(val...)": { "index": 80, "kind": "function", "displayName":
"Reverse Values", "group": "function", "label": "function", "required": false,
"javaType": "List", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns a list of all the
values, but in reverse order", "ognl": false, "suffix": "}" },
"routeGroup": { "index": 81, "kind": "function", "displayName": "Route
Group", "group": "function", "label": "function", "required": false,
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "The route group of the
current route the Exchange is being routed. Not all routes have a group
assigned, so this may be null.", "ognl": false, "suffix": "}" },
"routeId": { "index": 82, "kind": "function", "displayName": "Route Id",
"group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "The route id of the
current route the Exchange is being routed", "ognl": false, "suffix": "}" },
- "setVariable(key,exp)": { "index": 83, "kind": "function", "displayName":
"Set Variable", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Sets an attachment
with payload from the message body\/expression.", "ognl": false, "suffix": "}"
},
- "setHeader(name,type,exp)": { "index": 84, "kind": "function",
"displayName": "Set Header", "group": "function", "label": "function",
"required": false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Sets a message header with the given expression (optional converting to the
given type)", "ognl": false, "suffix": "}" },
- "setVariable(name,type,exp)": { "index": 85, "kind": "function",
"displayName": "Set Variable", "group": "function", "label": "function",
"required": false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Sets a variable with the given expression (optional converting to the given
type)", "ognl": false, "suffix": "}" },
- "shuffle(val...)": { "index": 86, "kind": "function", "displayName":
"Shuffle Values", "group": "function", "label": "function", "required": false,
"javaType": "List", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns a list of all the
values shuffled in random order", "ognl": false, "suffix": "}" },
- "size(exp)": { "index": 87, "kind": "function", "displayName": "Size",
"group": "function", "label": "function", "required": false, "javaType": "int",
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "description": "Returns the number of elements in collection
or array based payloads. If the value is null then 0 is returned, otherwise
1.", "ognl": false, "suffix": "}" },
- "skip(num)": { "index": 88, "kind": "function", "displayName": "Skip First
Items from the Message Body", "group": "function", "label": "function",
"required": false, "javaType": "java.util.Iterator", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The skip function iterates the message body and skips
the first number of items. This can be used with the Splitter EIP to split a
message body and skip the first N number of [...]
- "split(exp,separator)": { "index": 89, "kind": "function", "displayName":
"Split String Values", "group": "function", "label": "function", "required":
false, "javaType": "String[]", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Splits the message body\/expression as a String value using the separator into
a String array", "ognl": false, "suffix": "}" },
- "stepId": { "index": 90, "kind": "function", "displayName": "Step Id",
"group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the id of the
current step the Exchange is being routed.", "ognl": false, "suffix": "}" },
- "substring(head,tail)": { "index": 91, "kind": "function", "displayName":
"Substring", "group": "function", "label": "function", "required": false,
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Returns a substring of
the message body\/expression. If only one positive number, then the returned
string is clipped from the beginning. If only one negative number, then the
returned string is clipped fr [...]
- "substringAfter(exp,before)": { "index": 92, "kind": "function",
"displayName": "Substring After", "group": "function", "label": "function",
"required": false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Returns a substring of the message body\/expression that comes after. Returns
null if nothing comes after.", "ognl": false, "suffix": "}" },
- "substringBefore(exp,before)": { "index": 93, "kind": "function",
"displayName": "Substring Before", "group": "function", "label": "function",
"required": false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Returns a substring of the message body\/expression that comes before. Returns
null if nothing comes before.", "ognl": false, "suffix": "}" },
- "substringBetween(exp,after,before)": { "index": 94, "kind": "function",
"displayName": "Substring Between", "group": "function", "label": "function",
"required": false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Returns a substring of the message body\/expression that are between after and
before. Returns null if nothing comes between.", "ognl": false, "suffix": "}" },
- "sum(val...)": { "index": 95, "kind": "function", "displayName":
"Calculate Sum Number", "group": "function", "label": "function", "required":
false, "javaType": "long", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Sums together all the values as integral numbers. This function can also be
used to subtract by using negative numbers.", "ognl": false, "suffix": "}" },
- "sys.name": { "index": 96, "kind": "function", "displayName": "JVM System
Property", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "The JVM system
property with the given name", "ognl": false, "suffix": "}" },
- "threadId": { "index": 97, "kind": "function", "displayName": "Thread Id",
"group": "function", "label": "function", "required": false, "javaType":
"long", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the id of the
current thread. Can be used for logging.", "ognl": false, "suffix": "}" },
- "threadName": { "index": 98, "kind": "function", "displayName": "Thread
Name", "group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the name of the
current thread. Can be used for logging.", "ognl": false, "suffix": "}" },
- "throwException(type,msg)": { "index": 99, "kind": "function",
"displayName": "Throw Exception", "group": "function", "label": "function",
"required": false, "javaType": "java.lang.Exception", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "Deliberately throws an error. Uses
IllegalArgumentException by default if no type is specified (use fully
qualified classname).", "ognl": false, "suffix": "}" },
- "trim(exp)": { "index": 100, "kind": "function", "displayName": "Trim",
"group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "The trim function trims
the message body (or expression) by removing all leading and trailing white
spaces.", "ognl": false, "suffix": "}" },
- "type:name.field": { "index": 101, "kind": "function", "displayName":
"Java Field Value", "group": "function", "label": "function", "required":
false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "To
refer to a type or field by its classname. To refer to a field, you can append
.FIELD_NAME. For example, you can refer to the constant field from Exchange as:
`org.apache.camel.Exchange.FILE_NAME`", [...]
- "kindOfType(exp)": { "index": 102, "kind": "function", "displayName":
"Kind of Type", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "What kind of type is
the value (null,number,string,boolean,array,object)", "ognl": false, "suffix":
"}" },
- "uppercase(exp)": { "index": 103, "kind": "function", "displayName":
"Uppercase", "group": "function", "label": "function", "required": false,
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Uppercases the message
body (or expression)", "ognl": false, "suffix": "}" },
- "uuid(type)": { "index": 104, "kind": "function", "displayName": "Generate
UUID", "group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns a UUID using the
Camel `UuidGenerator`. You can choose between `default`, `classic`, `short` and
`simple` as the type. If no type is given, the default is used. It is also
possible to use a custom `Uuid [...]
- "variable.name": { "index": 105, "kind": "function", "displayName":
"Variable", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "The variable with the
given name", "ognl": true, "suffix": "}" },
- "variableAs(key,type)": { "index": 106, "kind": "function", "displayName":
"Variable As", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Converts the variable
to the given type (classname).", "ognl": false, "suffix": "}" },
- "variables": { "index": 107, "kind": "function", "displayName":
"Variables", "group": "function", "label": "function", "required": false,
"javaType": "java.util.Map", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Returns all the variables from the current Exchange in a Map", "ognl": false,
"suffix": "}" },
- "xpath(input,exp)": { "index": 108, "kind": "function", "displayName":
"XPath", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "When working with XML
data, then this allows using the XPath language, for example, to extract data
from the message body (in XML format). This requires having camel-xpath JAR on
the classpath. For input (optiona [...]
+ "safeQuote(exp)": { "index": 83, "kind": "function", "displayName": "Safe
Quote", "group": "function", "label": "function", "required": false,
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Returns the message
body (or expression) safely quoted if needed", "ognl": false, "suffix": "}" },
+ "setVariable(key,exp)": { "index": 84, "kind": "function", "displayName":
"Set Variable", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Sets an attachment
with payload from the message body\/expression.", "ognl": false, "suffix": "}"
},
+ "setHeader(name,type,exp)": { "index": 85, "kind": "function",
"displayName": "Set Header", "group": "function", "label": "function",
"required": false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Sets a message header with the given expression (optional converting to the
given type)", "ognl": false, "suffix": "}" },
+ "setVariable(name,type,exp)": { "index": 86, "kind": "function",
"displayName": "Set Variable", "group": "function", "label": "function",
"required": false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Sets a variable with the given expression (optional converting to the given
type)", "ognl": false, "suffix": "}" },
+ "shuffle(val...)": { "index": 87, "kind": "function", "displayName":
"Shuffle Values", "group": "function", "label": "function", "required": false,
"javaType": "List", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns a list of all the
values shuffled in random order", "ognl": false, "suffix": "}" },
+ "size(exp)": { "index": 88, "kind": "function", "displayName": "Size",
"group": "function", "label": "function", "required": false, "javaType": "int",
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "description": "Returns the number of elements in collection
or array based payloads. If the value is null then 0 is returned, otherwise
1.", "ognl": false, "suffix": "}" },
+ "skip(num)": { "index": 89, "kind": "function", "displayName": "Skip First
Items from the Message Body", "group": "function", "label": "function",
"required": false, "javaType": "java.util.Iterator", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The skip function iterates the message body and skips
the first number of items. This can be used with the Splitter EIP to split a
message body and skip the first N number of [...]
+ "split(exp,separator)": { "index": 90, "kind": "function", "displayName":
"Split String Values", "group": "function", "label": "function", "required":
false, "javaType": "String[]", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Splits the message body\/expression as a String value using the separator into
a String array", "ognl": false, "suffix": "}" },
+ "stepId": { "index": 91, "kind": "function", "displayName": "Step Id",
"group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the id of the
current step the Exchange is being routed.", "ognl": false, "suffix": "}" },
+ "substring(head,tail)": { "index": 92, "kind": "function", "displayName":
"Substring", "group": "function", "label": "function", "required": false,
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Returns a substring of
the message body\/expression. If only one positive number, then the returned
string is clipped from the beginning. If only one negative number, then the
returned string is clipped fr [...]
+ "substringAfter(exp,before)": { "index": 93, "kind": "function",
"displayName": "Substring After", "group": "function", "label": "function",
"required": false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Returns a substring of the message body\/expression that comes after. Returns
null if nothing comes after.", "ognl": false, "suffix": "}" },
+ "substringBefore(exp,before)": { "index": 94, "kind": "function",
"displayName": "Substring Before", "group": "function", "label": "function",
"required": false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Returns a substring of the message body\/expression that comes before. Returns
null if nothing comes before.", "ognl": false, "suffix": "}" },
+ "substringBetween(exp,after,before)": { "index": 95, "kind": "function",
"displayName": "Substring Between", "group": "function", "label": "function",
"required": false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Returns a substring of the message body\/expression that are between after and
before. Returns null if nothing comes between.", "ognl": false, "suffix": "}" },
+ "sum(val...)": { "index": 96, "kind": "function", "displayName":
"Calculate Sum Number", "group": "function", "label": "function", "required":
false, "javaType": "long", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Sums together all the values as integral numbers. This function can also be
used to subtract by using negative numbers.", "ognl": false, "suffix": "}" },
+ "sys.name": { "index": 97, "kind": "function", "displayName": "JVM System
Property", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "The JVM system
property with the given name", "ognl": false, "suffix": "}" },
+ "threadId": { "index": 98, "kind": "function", "displayName": "Thread Id",
"group": "function", "label": "function", "required": false, "javaType":
"long", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the id of the
current thread. Can be used for logging.", "ognl": false, "suffix": "}" },
+ "threadName": { "index": 99, "kind": "function", "displayName": "Thread
Name", "group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the name of the
current thread. Can be used for logging.", "ognl": false, "suffix": "}" },
+ "throwException(type,msg)": { "index": 100, "kind": "function",
"displayName": "Throw Exception", "group": "function", "label": "function",
"required": false, "javaType": "java.lang.Exception", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "Deliberately throws an error. Uses
IllegalArgumentException by default if no type is specified (use fully
qualified classname).", "ognl": false, "suffix": "}" },
+ "trim(exp)": { "index": 101, "kind": "function", "displayName": "Trim",
"group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "The trim function trims
the message body (or expression) by removing all leading and trailing white
spaces.", "ognl": false, "suffix": "}" },
+ "type:name.field": { "index": 102, "kind": "function", "displayName":
"Java Field Value", "group": "function", "label": "function", "required":
false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "To
refer to a type or field by its classname. To refer to a field, you can append
.FIELD_NAME. For example, you can refer to the constant field from Exchange as:
`org.apache.camel.Exchange.FILE_NAME`", [...]
+ "kindOfType(exp)": { "index": 103, "kind": "function", "displayName":
"Kind of Type", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "What kind of type is
the value (null,number,string,boolean,array,object)", "ognl": false, "suffix":
"}" },
+ "uppercase(exp)": { "index": 104, "kind": "function", "displayName":
"Uppercase", "group": "function", "label": "function", "required": false,
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Uppercases the message
body (or expression)", "ognl": false, "suffix": "}" },
+ "uuid(type)": { "index": 105, "kind": "function", "displayName": "Generate
UUID", "group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns a UUID using the
Camel `UuidGenerator`. You can choose between `default`, `classic`, `short` and
`simple` as the type. If no type is given, the default is used. It is also
possible to use a custom `Uuid [...]
+ "variable.name": { "index": 106, "kind": "function", "displayName":
"Variable", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "The variable with the
given name", "ognl": true, "suffix": "}" },
+ "variableAs(key,type)": { "index": 107, "kind": "function", "displayName":
"Variable As", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Converts the variable
to the given type (classname).", "ognl": false, "suffix": "}" },
+ "variables": { "index": 108, "kind": "function", "displayName":
"Variables", "group": "function", "label": "function", "required": false,
"javaType": "java.util.Map", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Returns all the variables from the current Exchange in a Map", "ognl": false,
"suffix": "}" },
+ "xpath(input,exp)": { "index": 109, "kind": "function", "displayName":
"XPath", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "When working with XML
data, then this allows using the XPath language, for example, to extract data
from the message body (in XML format). This requires having camel-xpath JAR on
the classpath. For input (optiona [...]
}
}
diff --git
a/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc
b/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc
index 048c0ddac74c..c536980b241c 100644
---
a/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc
+++
b/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc
@@ -460,6 +460,8 @@ The generator supports different kinds `default`,
`classic`, `short`, `simple` a
|`pad(exp,width,separator)` | `String` | Pads the expression with extra
padding if necessary, according the total width The separator is by default a
space. If the width is negative then padding to the right, otherwise to the
left.
|`replace(from,to)` | `String` | Replace all the string values in the message
body. To make it easier to replace single and double quotes, then you can use
XML escaped values `\"` as double quote, `\'` as single quote, and
`\∅` as empty value.
|`replace(from,to,exp)` | `String` | Replace all the string values in the
given expression. To make it easier to replace single and double quotes, then
you can use XML escaped values `\"` as double quote, `\'` as single
quote, and `\∅` as empty value.
+|`safeQuote() | `String` | Returns the message body safely quoted if needed
+|`safeQuote(exp) | `String` | Returns the expression safely quoted if needed
|`substring(num1)` | `String` | Returns a substring of the message body. If
the number is positive, then the returned string is clipped from the beginning.
If the number is negative, then the returned string is clipped from the ending.
|`substring(num1,num2)` | `String` | Returns a substring of the message body.
If the number is positive, then the returned string is clipped from the
beginning. If the number is negative, then the returned string is clipped from
the ending.
|`substring(num1,num2,exp)` | `String` | Returns a substring of the given
expression. If the number is positive, then the returned string is clipped from
the beginning. If the number is negative, then the returned string is clipped
from the ending.
@@ -532,6 +534,22 @@ If the value is currently in single quote, then this will
be converted to double
If the message body contains `Hello World` then `${quote()}` returns `"Hello
World"`.
And using `${quote('Hi from me')}` then `"Hi from me"` is returned.
+The `safeQuote` function is quoting the value depending on the value type
+(uses the same logic as `kindOfType` function). In essence values that are
null, boolean or numbers are not quoted,
+while everything else is. The `safeQuote` function is useful when working with
JSon data.
+
+For example when doing JSon to JSon mapping you can extract values form the
source document,
+to be included in the output, but the values may or may not need to be quoted.
Then you can use the `~>` chain operator
+to call the `safeQuote` function as shown below:
+
+[source,text]
+----
+{
+ "id": ${jsonpath($.id)} ~> ${safeQuote()}
+ "total": ${jsonpath($.amount)} ~> ${safeQuote()}
+}
+----
+
=== XML & JSon Functions
diff --git
a/core/camel-core-languages/src/main/java/org/apache/camel/language/csimple/CSimpleHelper.java
b/core/camel-core-languages/src/main/java/org/apache/camel/language/csimple/CSimpleHelper.java
index a80f4be9700d..b156f359575e 100644
---
a/core/camel-core-languages/src/main/java/org/apache/camel/language/csimple/CSimpleHelper.java
+++
b/core/camel-core-languages/src/main/java/org/apache/camel/language/csimple/CSimpleHelper.java
@@ -1062,6 +1062,19 @@ public final class CSimpleHelper {
return body;
}
+ public static Object safeQuote(Exchange exchange, Object value) {
+ if (value == null) {
+ return null;
+ }
+ String type = kindOfType(exchange, value);
+ if ("string".equals(type) || "array".equals(type) ||
"object".equals(type)) {
+ String body =
exchange.getContext().getTypeConverter().tryConvertTo(String.class, exchange,
value);
+ body = StringHelper.removeLeadingAndEndingQuotes(body);
+ value = StringQuoteHelper.doubleQuote(body);
+ }
+ return value;
+ }
+
public static String trim(Exchange exchange, Object value) {
String body;
if (value != null) {
diff --git
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleConstants.java
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleConstants.java
index 542180d8c660..f41ae793f8a0 100644
---
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleConstants.java
+++
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleConstants.java
@@ -337,6 +337,10 @@ public final class SimpleConstants {
label = "function")
public static final String ROUTE_ID = "routeId";
+ @Metadata(description = "Returns the message body (or expression) safely
quoted if needed",
+ label = "function", javaType = "String")
+ public static final String SAFE_QUOTE = "safeQuote(exp)";
+
@Metadata(description = "Sets an attachment with payload from the message
body/expression.",
label = "function", javaType = "Object")
public static final String SET_ATTACHMENT = "setVariable(key,exp)";
diff --git
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleExpressionBuilder.java
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleExpressionBuilder.java
index 4f14b97aca21..9d3cb2eff36a 100644
---
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleExpressionBuilder.java
+++
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleExpressionBuilder.java
@@ -643,6 +643,68 @@ public final class SimpleExpressionBuilder {
};
}
+ /**
+ * Safe quotes the given expressions (uses message body if expression is
null) if necessary.
+ */
+ public static Expression safeQuoteExpression(final String expression) {
+ return new ExpressionAdapter() {
+ private Expression exp;
+
+ @Override
+ public void init(CamelContext context) {
+ if (expression != null) {
+ exp =
context.resolveLanguage("simple").createExpression(expression);
+ exp.init(context);
+ }
+ }
+
+ @Override
+ public Object evaluate(Exchange exchange) {
+ Object value;
+ if (exp != null) {
+ value = exp.evaluate(exchange, Object.class);
+ } else {
+ value = exchange.getMessage().getBody(Object.class);
+ }
+ if (value != null) {
+ String type = kindOfType(value);
+ if ("string".equals(type) || "array".equals(type) ||
"object".equals(type)) {
+ String body =
exchange.getContext().getTypeConverter().tryConvertTo(String.class, exchange,
value);
+ body = StringHelper.removeLeadingAndEndingQuotes(body);
+ value = StringQuoteHelper.doubleQuote(body);
+ }
+ }
+ return value;
+ }
+
+ private String kindOfType(Object value) {
+ Class<?> type = value.getClass();
+ if (ObjectHelper.isNumericType(type)) {
+ return "number";
+ } else if (boolean.class == type || Boolean.class == type) {
+ return "boolean";
+ } else if (value instanceof CharSequence) {
+ return "string";
+ } else if (ObjectHelper.isPrimitiveArrayType(type) || value
instanceof Collection
+ || value instanceof Map<?, ?>) {
+ return "array";
+ } else {
+ return "object";
+ }
+ }
+
+
+ @Override
+ public String toString() {
+ if (expression != null) {
+ return "safeQuote(" + expression + ")";
+ } else {
+ return "safeQuote()";
+ }
+ }
+ };
+ }
+
/**
* Double quotes the given expressions (uses message body if expression is
null)
*/
diff --git
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
index 409552bb61aa..52f2cbf77279 100644
---
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
+++
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
@@ -1204,6 +1204,16 @@ public class SimpleFunctionExpression extends
LiteralExpression {
}
return SimpleExpressionBuilder.quoteExpression(exp);
}
+ // safeQuote function
+ remainder = ifStartsWithReturnRemainder("safeQuote(", function);
+ if (remainder != null) {
+ String exp = null;
+ String value = StringHelper.beforeLast(remainder, ")");
+ if (ObjectHelper.isNotEmpty(value)) {
+ exp = StringHelper.removeQuotes(value);
+ }
+ return SimpleExpressionBuilder.safeQuoteExpression(exp);
+ }
// trim function
remainder = ifStartsWithReturnRemainder("trim(", function);
@@ -2977,6 +2987,30 @@ public class SimpleFunctionExpression extends
LiteralExpression {
}
return "Object o = " + exp + ";\n return quote(exchange,
o);";
}
+ // safaeQuote function
+ remainder = ifStartsWithReturnRemainder("safeQuote(", function);
+ if (remainder != null) {
+ String exp = null;
+ String values = StringHelper.beforeLast(remainder, ")");
+ if (ObjectHelper.isNotEmpty(values)) {
+ String[] tokens = codeSplitSafe(values, ',', true, true);
+ if (tokens.length != 1) {
+ throw new SimpleParserException(
+ "Valid syntax: ${safeQuote(exp)} was: " +
function, token.getIndex());
+ }
+ // single quotes should be double quotes
+ String s = tokens[0];
+ if (StringHelper.isSingleQuoted(s)) {
+ s = StringHelper.removeLeadingAndEndingQuotes(s);
+ s = StringQuoteHelper.doubleQuote(s);
+ }
+ exp = s;
+ }
+ if (ObjectHelper.isEmpty(exp)) {
+ exp = "body";
+ }
+ return "Object o = " + exp + ";\n return
safeQuote(exchange, o);";
+ }
// trim function
remainder = ifStartsWithReturnRemainder("trim(", function);
diff --git
a/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java
b/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java
index 6ff906031cda..0e5e5d8fdd5a 100644
---
a/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java
+++
b/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java
@@ -2960,6 +2960,53 @@ public class SimpleTest extends LanguageTestSupport {
assertEquals("\"Hi\"", s);
}
+ @Test
+ public void testSafeQuote() {
+ exchange.getMessage().setBody("Hello World");
+
+ Expression expression =
context.resolveLanguage("simple").createExpression("${safeQuote()}");
+ String s = expression.evaluate(exchange, String.class);
+ assertEquals("\"Hello World\"", s);
+
+ expression =
context.resolveLanguage("simple").createExpression("${safeQuote(${body})}");
+ s = expression.evaluate(exchange, String.class);
+ assertEquals("\"Hello World\"", s);
+
+ expression =
context.resolveLanguage("simple").createExpression("${safeQuote('Hi')}");
+ s = expression.evaluate(exchange, String.class);
+ assertEquals("\"Hi\"", s);
+
+ expression =
context.resolveLanguage("simple").createExpression("${safeQuote(''Hi'')}");
+ s = expression.evaluate(exchange, String.class);
+ assertEquals("\"Hi\"", s);
+
+ exchange.getMessage().setBody(123);
+ expression =
context.resolveLanguage("simple").createExpression("${safeQuote()}");
+ s = expression.evaluate(exchange, String.class);
+ assertEquals("123", s);
+
+ expression =
context.resolveLanguage("simple").createExpression("${safeQuote(${body})}");
+ s = expression.evaluate(exchange, String.class);
+ assertEquals("123", s);
+
+ exchange.getMessage().setBody(true);
+ expression =
context.resolveLanguage("simple").createExpression("${safeQuote()}");
+ s = expression.evaluate(exchange, String.class);
+ assertEquals("true", s);
+
+ expression =
context.resolveLanguage("simple").createExpression("${safeQuote(${body})}");
+ s = expression.evaluate(exchange, String.class);
+ assertEquals("true", s);
+
+ Map<String, String> m = new LinkedHashMap<>();
+ m.put("A", "1");
+ m.put("B", "2");
+ exchange.getMessage().setBody(m);
+ expression =
context.resolveLanguage("simple").createExpression("${safeQuote()}");
+ s = expression.evaluate(exchange, String.class);
+ assertEquals("\"{A=1, B=2}\"", s);
+ }
+
@Test
public void testTrim() {
exchange.getMessage().setBody(" Hello World ");