Skip to content

Commit 09e516f

Browse files
authored
CAMEL-22852: camel-core - Add length/size function to simple language (#20799)
1 parent 462fde2 commit 09e516f

File tree

9 files changed

+426
-40
lines changed

9 files changed

+426
-40
lines changed

catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/simple.json

Lines changed: 22 additions & 20 deletions
Large diffs are not rendered by default.

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

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
*/
1717
package org.apache.camel.language.csimple.joor;
1818

19+
import java.io.File;
1920
import java.nio.charset.StandardCharsets;
2021
import java.security.MessageDigest;
2122
import java.util.ArrayList;
@@ -2240,6 +2241,56 @@ public void testUuid() {
22402241
assertExpression("${uuid(mygen)}", "1234");
22412242
}
22422243

2244+
@Test
2245+
public void testSize() {
2246+
exchange.getMessage().setBody(new int[] { 4, 7, 9 });
2247+
Expression expression = context.resolveLanguage("csimple").createExpression("${size()}");
2248+
int len = expression.evaluate(exchange, int.class);
2249+
assertEquals(3, len);
2250+
2251+
exchange.getMessage().setBody("Hello World");
2252+
len = expression.evaluate(exchange, int.class);
2253+
assertEquals(11, len);
2254+
2255+
exchange.getMessage().setBody(List.of("A", "B", "C", "D"));
2256+
len = expression.evaluate(exchange, int.class);
2257+
assertEquals(4, len);
2258+
2259+
exchange.getMessage().setBody(Map.of("A", 1, "B", 2, "C", 3));
2260+
len = expression.evaluate(exchange, int.class);
2261+
assertEquals(3, len);
2262+
2263+
File f = new File("src/test/resources/log4j2.properties");
2264+
exchange.getMessage().setBody(f);
2265+
len = expression.evaluate(exchange, int.class);
2266+
assertEquals(f.length(), len);
2267+
}
2268+
2269+
@Test
2270+
public void testLength() {
2271+
exchange.getMessage().setBody(new int[] { 4, 7, 9 });
2272+
Expression expression = context.resolveLanguage("csimple").createExpression("${length()}");
2273+
int len = expression.evaluate(exchange, int.class);
2274+
assertEquals(3, len);
2275+
2276+
exchange.getMessage().setBody("Hello World");
2277+
len = expression.evaluate(exchange, int.class);
2278+
assertEquals(11, len);
2279+
2280+
exchange.getMessage().setBody(List.of("A", "BB", "CCC", "DDDD"));
2281+
len = expression.evaluate(exchange, int.class);
2282+
assertEquals(18, len);
2283+
2284+
exchange.getMessage().setBody(Map.of("A", 1, "BB", 22, "CC", 333));
2285+
len = expression.evaluate(exchange, int.class);
2286+
assertEquals(20, len);
2287+
2288+
File f = new File("src/test/resources/log4j2.properties");
2289+
exchange.getMessage().setBody(f);
2290+
len = expression.evaluate(exchange, int.class);
2291+
assertEquals(f.length(), len);
2292+
}
2293+
22432294
@Test
22442295
public void testTrim() {
22452296
exchange.getMessage().setBody(" Hello World ");

core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/simple/simple.json

Lines changed: 22 additions & 20 deletions
Large diffs are not rendered by default.

core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,10 @@ log sensitive data from the message itself.
294294

295295
|concat(exp,exp,separator) |String |Performs a string concat using two expressions (message body as default) with optional separator
296296

297+
|length(exp) |int |The payload length (number of bytes) of the message body (or expression).
298+
299+
|size(exp) |int |The size of the message body (or expression). If the payload is java.util.Collection or java.util.Map based then the size is the number of elements; otherwise the payload size in bytes.
300+
297301
|uppercase(exp) |String |Uppercases the message body (or expression)
298302

299303
|lowercase(exp) |String |Lowercases the message body (or expression)

core/camel-core-languages/src/main/java/org/apache/camel/language/csimple/CSimpleHelper.java

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616
*/
1717
package org.apache.camel.language.csimple;
1818

19+
import java.io.InputStream;
1920
import java.lang.reflect.Array;
2021
import java.security.MessageDigest;
2122
import java.util.ArrayList;
23+
import java.util.Collection;
2224
import java.util.Date;
2325
import java.util.Iterator;
2426
import java.util.LinkedHashMap;
@@ -39,6 +41,7 @@
3941
import org.apache.camel.InvalidPayloadException;
4042
import org.apache.camel.Message;
4143
import org.apache.camel.RuntimeCamelException;
44+
import org.apache.camel.StreamCache;
4245
import org.apache.camel.spi.ExchangeFormatter;
4346
import org.apache.camel.spi.Language;
4447
import org.apache.camel.spi.PropertiesComponent;
@@ -826,4 +829,68 @@ public static String lowercase(Exchange exchange, Object value) {
826829
return body;
827830
}
828831

832+
public static int length(Exchange exchange, Object value) {
833+
try {
834+
if (value instanceof byte[] arr) {
835+
return arr.length;
836+
} else if (value instanceof char[] arr) {
837+
return arr.length;
838+
} else if (value instanceof int[] arr) {
839+
return arr.length;
840+
} else if (value instanceof long[] arr) {
841+
return arr.length;
842+
} else if (value instanceof double[] arr) {
843+
return arr.length;
844+
}
845+
846+
String data = exchange.getContext().getTypeConverter().tryConvertTo(String.class, exchange, value);
847+
if (data != null) {
848+
return data.length();
849+
}
850+
} finally {
851+
if (value instanceof StreamCache streamCache) {
852+
streamCache.reset();
853+
}
854+
}
855+
return 0;
856+
}
857+
858+
public static int size(Exchange exchange, Object value) {
859+
try {
860+
// calculate length
861+
if (value instanceof byte[] arr) {
862+
return arr.length;
863+
} else if (value instanceof char[] arr) {
864+
return arr.length;
865+
} else if (value instanceof int[] arr) {
866+
return arr.length;
867+
} else if (value instanceof long[] arr) {
868+
return arr.length;
869+
} else if (value instanceof double[] arr) {
870+
return arr.length;
871+
} else if (value instanceof String s) {
872+
return s.length();
873+
} else if (value instanceof Collection<?> c) {
874+
return c.size();
875+
} else if (value instanceof Map<?, ?> m) {
876+
return m.size();
877+
} else {
878+
// fall back to stream to read
879+
InputStream is = exchange.getContext().getTypeConverter().tryConvertTo(InputStream.class, exchange, value);
880+
int len = 0;
881+
while (is.read() != -1) {
882+
len++;
883+
}
884+
return len;
885+
}
886+
} catch (Exception e) {
887+
// ignore
888+
} finally {
889+
if (value instanceof StreamCache streamCache) {
890+
streamCache.reset();
891+
}
892+
}
893+
return 0;
894+
}
895+
829896
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,12 @@ public final class SimpleConstants {
183183
@Metadata(description = "The trim function trims the message body (or expression) by removing all leading and trailing white spaces.",
184184
label = "function", javaType = "String", displayName = "Trim")
185185
public static final String TRIM = "trim(exp)";
186+
@Metadata(description = "The payload length (number of bytes) of the message body (or expression).",
187+
label = "function", javaType = "int", displayName = "Length")
188+
public static final String LENGTH = "length(exp)";
189+
@Metadata(description = "The size of the message body (or expression). If the payload is java.util.Collection or java.util.Map based then the size is the number of elements; otherwise the payload size in bytes.",
190+
label = "function", javaType = "int", displayName = "Size")
191+
public static final String SIZE = "size(exp)";
186192
@Metadata(description = "Uppercases the message body (or expression)",
187193
label = "function", javaType = "String", displayName = "Uppercase")
188194
public static final String UPPERCASE = "uppercase(exp)";

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

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.security.MessageDigest;
2424
import java.util.ArrayList;
2525
import java.util.Arrays;
26+
import java.util.Collection;
2627
import java.util.Date;
2728
import java.util.Iterator;
2829
import java.util.LinkedHashMap;
@@ -40,6 +41,7 @@
4041
import org.apache.camel.Expression;
4142
import org.apache.camel.InvalidPayloadException;
4243
import org.apache.camel.Predicate;
44+
import org.apache.camel.StreamCache;
4345
import org.apache.camel.spi.ClassResolver;
4446
import org.apache.camel.spi.ExchangeFormatter;
4547
import org.apache.camel.spi.Language;
@@ -340,6 +342,138 @@ public String toString() {
340342
};
341343
}
342344

345+
/**
346+
* Returns the size of the expression (number of elements in collection/map; otherwise size of payload in bytes)
347+
*/
348+
public static Expression sizeExpression(final String expression) {
349+
return new ExpressionAdapter() {
350+
private Expression exp;
351+
352+
@Override
353+
public void init(CamelContext context) {
354+
if (expression != null) {
355+
exp = context.resolveLanguage("simple").createExpression(expression);
356+
exp.init(context);
357+
}
358+
}
359+
360+
@Override
361+
public Object evaluate(Exchange exchange) {
362+
Object body;
363+
if (exp != null) {
364+
body = exp.evaluate(exchange, Object.class);
365+
} else {
366+
body = exchange.getMessage().getBody(Object.class);
367+
}
368+
if (body != null) {
369+
try {
370+
// calculate length
371+
if (body instanceof byte[] arr) {
372+
return arr.length;
373+
} else if (body instanceof char[] arr) {
374+
return arr.length;
375+
} else if (body instanceof int[] arr) {
376+
return arr.length;
377+
} else if (body instanceof long[] arr) {
378+
return arr.length;
379+
} else if (body instanceof double[] arr) {
380+
return arr.length;
381+
} else if (body instanceof String s) {
382+
return s.length();
383+
} else if (body instanceof Collection<?> c) {
384+
return c.size();
385+
} else if (body instanceof Map<?, ?> m) {
386+
return m.size();
387+
} else {
388+
// fall back to stream to read
389+
InputStream is
390+
= exchange.getContext().getTypeConverter().tryConvertTo(InputStream.class, exchange, body);
391+
int len = 0;
392+
while (is.read() != -1) {
393+
len++;
394+
}
395+
return len;
396+
}
397+
} catch (Exception e) {
398+
// ignore
399+
} finally {
400+
if (body instanceof StreamCache streamCache) {
401+
streamCache.reset();
402+
}
403+
}
404+
}
405+
return null;
406+
}
407+
408+
@Override
409+
public String toString() {
410+
if (expression != null) {
411+
return "size(" + expression + ")";
412+
} else {
413+
return "size()";
414+
}
415+
}
416+
};
417+
}
418+
419+
/**
420+
* Returns the length of the expression (length of payload in bytes)
421+
*/
422+
public static Expression lengthExpression(final String expression) {
423+
return new ExpressionAdapter() {
424+
private Expression exp;
425+
426+
@Override
427+
public void init(CamelContext context) {
428+
if (expression != null) {
429+
exp = context.resolveLanguage("simple").createExpression(expression);
430+
exp.init(context);
431+
}
432+
}
433+
434+
@Override
435+
public Object evaluate(Exchange exchange) {
436+
Object body;
437+
if (exp != null) {
438+
body = exp.evaluate(exchange, Object.class);
439+
} else {
440+
body = exchange.getMessage().getBody(Object.class);
441+
}
442+
try {
443+
if (body instanceof byte[] arr) {
444+
return arr.length;
445+
} else if (body instanceof char[] arr) {
446+
return arr.length;
447+
} else if (body instanceof int[] arr) {
448+
return arr.length;
449+
} else if (body instanceof long[] arr) {
450+
return arr.length;
451+
} else if (body instanceof double[] arr) {
452+
return arr.length;
453+
}
454+
String data = exchange.getContext().getTypeConverter().tryConvertTo(String.class, exchange, body);
455+
if (data != null) {
456+
return data.length();
457+
}
458+
} finally {
459+
if (body instanceof StreamCache streamCache) {
460+
streamCache.reset();
461+
}
462+
}
463+
return null;
464+
}
465+
466+
@Override
467+
public String toString() {
468+
if (expression != null) {
469+
return "length(" + expression + ")";
470+
} else {
471+
return "length()";
472+
}
473+
}
474+
};
475+
}
476+
343477
/**
344478
* A ternary condition expression
345479
*/

0 commit comments

Comments
 (0)