Skip to content

Commit 2313b59

Browse files
committed
CAMEL-23035: camel-core - Simple language using colon or question mark can conflict with ternary operator
1 parent 15151e3 commit 2313b59

4 files changed

Lines changed: 39 additions & 56 deletions

File tree

components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleOperatorTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,24 @@ public void testElvis() {
806806
assertExpression("${body} ?: 'World'", 1);
807807
}
808808

809+
@Test
810+
public void testTernaryLog() {
811+
exchange.getIn().setBody("Hello World");
812+
assertExpression(">>> Message received from WebSocket Client : ${body}",
813+
">>> Message received from WebSocket Client : Hello World");
814+
815+
exchange.getMessage().setHeader(Exchange.FILE_NAME, "foo.txt");
816+
assertExpression("This is a test bug ${header.CamelFileName}",
817+
"This is a test bug foo.txt");
818+
819+
assertExpression("This is a test bug : ${header.CamelFileName}",
820+
"This is a test bug : foo.txt");
821+
822+
assertExpression("This is a test bug ? ${header.CamelFileName}",
823+
"This is a test bug ? foo.txt");
824+
825+
}
826+
809827
@Override
810828
protected String getLanguageName() {
811829
return "csimple";

components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleTest.java

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2938,10 +2938,10 @@ public void testTernaryOperator() {
29382938
// Test with body
29392939
exchange.getIn().setBody("Hello World");
29402940
exchange.getIn().setHeader("foo", 44);
2941-
assertExpression("${header.foo > 0 ? ${body} : 'Bye World'}", "Hello World");
2941+
assertExpression("${header.foo > 0 ? body : 'Bye World'}", "Hello World");
29422942
exchange.getIn().setHeader("foo", -123);
2943-
assertExpression("${header.foo > 0 ? ${body} : 'Bye World'}", "Bye World");
2944-
assertExpression("${header.foo > 0 ? ${body} : ${null}}", null);
2943+
assertExpression("${header.foo > 0 ? body : 'Bye World'}", "Bye World");
2944+
assertExpression("${header.foo > 0 ? body : null}", null);
29452945

29462946
// Test with file name
29472947
exchange.getIn().setHeader("CamelFileName", "testfile.txt");
@@ -2981,13 +2981,7 @@ public void testTernaryOperatorWithNull() {
29812981

29822982
@Test
29832983
public void testTernaryOperatorNested() {
2984-
// Nested ternary operators
2985-
exchange.getIn().setHeader("score", 95);
2986-
assertExpression("${header.score >= 90 ? 'A' : ${header.score} >= 80 ? 'B' : 'C'}", "A");
2987-
exchange.getIn().setHeader("score", 85);
2988-
assertExpression("${header.score >= 90 ? 'A' : ${header.score} >= 80 ? 'B' : 'C'}", "B");
2989-
exchange.getIn().setHeader("score", 75);
2990-
assertExpression("${header.score >= 90 ? 'A' : ${header.score} >= 80 ? 'B' : 'C'}", "C");
2984+
// not supported in csimple
29912985
}
29922986

29932987
@Test

core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleExpressionParser.java

Lines changed: 6 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import org.apache.camel.language.simple.ast.SimpleFunctionEnd;
3232
import org.apache.camel.language.simple.ast.SimpleFunctionStart;
3333
import org.apache.camel.language.simple.ast.SimpleNode;
34-
import org.apache.camel.language.simple.ast.TernaryExpression;
3534
import org.apache.camel.language.simple.ast.UnaryExpression;
3635
import org.apache.camel.language.simple.types.ChainOperatorType;
3736
import org.apache.camel.language.simple.types.OtherOperatorType;
@@ -143,11 +142,10 @@ protected List<SimpleNode> parseTokens() {
143142
// parse the expression using the following grammar
144143
nextToken();
145144
while (!token.getType().isEol()) {
146-
// an expression supports just template (eg text), functions, unary, ternary, or other operator
145+
// an expression supports just template (eg text), functions, unary, or other operator
147146
templateText();
148147
functionText();
149148
unaryOperator();
150-
ternaryOperator();
151149
chainOperator();
152150
otherOperator();
153151
nextToken();
@@ -165,8 +163,6 @@ protected List<SimpleNode> parseTokens() {
165163
prepareBlocks();
166164
// compact and stack unary operators
167165
prepareUnaryExpressions();
168-
// compact and stack ternary expressions
169-
prepareTernaryExpressions();
170166
// compact and stack chain expressions
171167
prepareChainExpression();
172168
// compact and stack other expressions
@@ -248,7 +244,6 @@ protected void parseAndCreateAstModel() {
248244

249245
// counter to keep track of number of functions in the tokens
250246
AtomicInteger functions = new AtomicInteger();
251-
AtomicInteger ternary = new AtomicInteger();
252247

253248
LiteralNode imageToken = null;
254249
for (SimpleToken token : tokens) {
@@ -258,7 +253,7 @@ protected void parseAndCreateAstModel() {
258253
}
259254

260255
// create a node from the token
261-
SimpleNode node = createNode(token, functions, ternary);
256+
SimpleNode node = createNode(token, functions);
262257
if (node != null) {
263258
// a new token was created so the current image token need to be added first
264259
if (imageToken != null) {
@@ -285,8 +280,8 @@ protected void parseAndCreateAstModel() {
285280
}
286281
}
287282

288-
private SimpleNode createNode(SimpleToken token, AtomicInteger functions, AtomicInteger ternary) {
289-
// expression only support functions, unary operators, ternary operators, and other operators
283+
private SimpleNode createNode(SimpleToken token, AtomicInteger functions) {
284+
// expression only support functions, unary operators, operators, and other operators
290285
if (token.getType().isFunctionStart()) {
291286
// starting a new function
292287
functions.incrementAndGet();
@@ -300,14 +295,6 @@ private SimpleNode createNode(SimpleToken token, AtomicInteger functions, Atomic
300295
if (!nodes.isEmpty() && nodes.get(nodes.size() - 1) instanceof SimpleFunctionEnd) {
301296
return new UnaryExpression(token);
302297
}
303-
} else if (token.getType().isTernaryStart()) {
304-
// starting a new ternary
305-
ternary.incrementAndGet();
306-
return new TernaryExpression(token);
307-
} else if (ternary.get() > 0 && token.getType().isTernaryEnd()) {
308-
// there must be a start ternary already, to let this be an end ternary
309-
ternary.decrementAndGet();
310-
return new TernaryExpression(token);
311298
} else if (token.getType().isChain()) {
312299
return new ChainExpression(token);
313300
} else if (token.getType().isOther()) {
@@ -394,9 +381,9 @@ static void parseLiteralNode(StringBuilder sb, SimpleNode node, String exp) {
394381
// - other operator = operator attached to both the left and right hand side nodes
395382

396383
protected void templateText() {
397-
// for template, we accept anything but functions / ternary operator / other operator
384+
// for template, we accept anything but functions / other operator
398385
while (!token.getType().isFunctionStart() && !token.getType().isFunctionEnd() && !token.getType().isEol()
399-
&& !token.getType().isTernary() && !token.getType().isOther() && !token.getType().isChain()) {
386+
&& !token.getType().isOther() && !token.getType().isChain()) {
400387
nextToken();
401388
}
402389
}
@@ -481,33 +468,6 @@ protected boolean chainOperator() {
481468
return false;
482469
}
483470

484-
protected boolean ternaryOperator() {
485-
if (accept(TokenType.ternaryOperator)) {
486-
nextToken();
487-
// there should be at least one whitespace after the operator
488-
expectAndAcceptMore(TokenType.whiteSpace);
489-
490-
// then we expect either some quoted text, another function, or a numeric, boolean or null value
491-
if (singleQuotedLiteralWithFunctionsText()
492-
|| doubleQuotedLiteralWithFunctionsText()
493-
|| functionText()
494-
|| numericValue()
495-
|| booleanValue()
496-
|| nullValue()) {
497-
// then after the right hand side value, there should be a whitespace if there is more tokens
498-
nextToken();
499-
if (!token.getType().isEol()) {
500-
expect(TokenType.whiteSpace);
501-
}
502-
} else {
503-
throw new SimpleParserException(
504-
"Ternary operator does not support token " + token, token.getIndex());
505-
}
506-
return true;
507-
}
508-
return false;
509-
}
510-
511471
protected boolean unaryOperator() {
512472
if (accept(TokenType.unaryOperator)) {
513473
nextToken();

core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleOperatorTest.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -895,6 +895,17 @@ public void testTernaryLog() {
895895
exchange.getIn().setBody("Hello World");
896896
assertExpression(">>> Message received from WebSocket Client : ${body}",
897897
">>> Message received from WebSocket Client : Hello World");
898+
899+
exchange.getMessage().setHeader(Exchange.FILE_NAME, "foo.txt");
900+
assertExpression("This is a test bug ${header.CamelFileName}",
901+
"This is a test bug foo.txt");
902+
903+
assertExpression("This is a test bug : ${header.CamelFileName}",
904+
"This is a test bug : foo.txt");
905+
906+
assertExpression("This is a test bug ? ${header.CamelFileName}",
907+
"This is a test bug ? foo.txt");
908+
898909
}
899910

900911
@Test

0 commit comments

Comments
 (0)