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 2023/12/13 14:58:28 UTC
(camel) 01/01: CAMEL-17825: Hash generator in the Simple language
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch hash
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 6a5eda686502eb8391249048303298fae01d3f5b
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Dec 13 15:58:15 2023 +0100
CAMEL-17825: Hash generator in the Simple language
---
.../modules/languages/pages/simple-language.adoc | 3 ++
.../language/simple/SimpleExpressionBuilder.java | 36 +++++++++++++++++
.../simple/ast/SimpleFunctionExpression.java | 20 ++++++++++
.../apache/camel/language/simple/SimpleTest.java | 46 ++++++++++++++++++++++
.../java/org/apache/camel/util/StringHelper.java | 12 ++++++
5 files changed, 117 insertions(+)
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 32d75641fcc..4789404a6cb 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
@@ -255,6 +255,9 @@ If no type is given the default is used. It is also possible to use a custom `Uu
and bind the bean to the xref:manual::registry.adoc[Registry] with an id. For example `${uuid(myGenerator}`
where the ID is _myGenerator_.
+|hash(exp,algorithm) |String |Returns a hashed value (string in hex decimal) using JDK MessageDigest.
+The algorithm can be SHA-256 (default) or SHA3-256.
+
|jsonpath(exp) | Object | When working with JSon data, then this allows to use the JsonPath language
for example to extract data from the message body (in JSon format). This requires having camel-jsonpath JAR on the classpath.
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 b39e822adee..0be12c475a1 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
@@ -16,6 +16,7 @@
*/
package org.apache.camel.language.simple;
+import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
@@ -191,6 +192,41 @@ public final class SimpleExpressionBuilder {
};
}
+ /**
+ * Hashes the value using the given algorithm
+ */
+ public static Expression hashExpression(final String expression, final String algorithm) {
+ return new ExpressionAdapter() {
+ private Expression exp;
+
+ @Override
+ public void init(CamelContext context) {
+ exp = context.resolveLanguage("simple").createExpression(expression);
+ exp.init(context);
+ }
+
+ @Override
+ public Object evaluate(Exchange exchange) {
+ byte[] data = exp.evaluate(exchange, byte[].class);
+ if (data != null && data.length > 0) {
+ try {
+ MessageDigest digest = MessageDigest.getInstance(algorithm);
+ byte[] bytes = digest.digest(data);
+ return StringHelper.bytesToHex(bytes);
+ } catch (Exception e) {
+ throw CamelExecutionException.wrapCamelExecutionException(exchange, e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return "hash(" + expression + "," + algorithm + ")";
+ }
+ };
+ }
+
/**
* Returns a random number between min and max (exclusive)
*/
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 d9dfbf3474f..ddc8fd13425 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
@@ -663,6 +663,26 @@ public class SimpleFunctionExpression extends LiteralExpression {
return SimpleExpressionBuilder.uuidExpression(null);
}
+ // hash function
+ remainder = ifStartsWithReturnRemainder("hash(", function);
+ if (remainder != null) {
+ String values = StringHelper.before(remainder, ")");
+ if (values == null || ObjectHelper.isEmpty(values)) {
+ throw new SimpleParserException(
+ "Valid syntax: ${hash(value,algorithm)} or ${hash(value)} was: " + function, token.getIndex());
+ }
+ if (values.contains(",")) {
+ String[] tokens = values.split(",", 2);
+ if (tokens.length > 2) {
+ throw new SimpleParserException(
+ "Valid syntax: ${hash(value,algorithm)} or ${hash(value)} was: " + function, token.getIndex());
+ }
+ return SimpleExpressionBuilder.hashExpression(tokens[0].trim(), tokens[1].trim());
+ } else {
+ return SimpleExpressionBuilder.hashExpression(values.trim(), "SHA-256");
+ }
+ }
+
// empty function
remainder = ifStartsWithReturnRemainder("empty(", function);
if (remainder != null) {
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 63503dc95e1..4e54af27e31 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
@@ -16,6 +16,8 @@
*/
package org.apache.camel.language.simple;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
@@ -44,6 +46,7 @@ import org.apache.camel.spi.PropertiesComponent;
import org.apache.camel.spi.Registry;
import org.apache.camel.spi.UuidGenerator;
import org.apache.camel.util.InetAddressUtil;
+import org.apache.camel.util.StringHelper;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.ResourceLock;
import org.junit.jupiter.api.parallel.Resources;
@@ -2153,6 +2156,49 @@ public class SimpleTest extends LanguageTestSupport {
assertExpression("${uuid(mygen)}", "1234");
}
+ @Test
+ public void testHash() throws Exception {
+ Expression expression = context.resolveLanguage("simple").createExpression("${hash(hello)}");
+ String s = expression.evaluate(exchange, String.class);
+ assertNotNull(s);
+ MessageDigest digest = MessageDigest.getInstance("SHA-256");
+ byte[] bytes = digest.digest("hello".getBytes(StandardCharsets.UTF_8));
+ String expected = StringHelper.bytesToHex(bytes);
+ assertEquals(expected, s);
+
+ expression = context.resolveLanguage("simple").createExpression("${hash(${body})}");
+ s = expression.evaluate(exchange, String.class);
+ assertNotNull(s);
+ digest = MessageDigest.getInstance("SHA-256");
+ bytes = digest.digest(exchange.getMessage().getBody(String.class).getBytes(StandardCharsets.UTF_8));
+ expected = StringHelper.bytesToHex(bytes);
+ assertEquals(expected, s);
+
+ expression = context.resolveLanguage("simple").createExpression("${hash(${header.foo})}");
+ s = expression.evaluate(exchange, String.class);
+ assertNotNull(s);
+
+ expression = context.resolveLanguage("simple").createExpression("${hash(hello,SHA3-256)}");
+ s = expression.evaluate(exchange, String.class);
+ assertNotNull(s);
+
+ expression = context.resolveLanguage("simple").createExpression("${hash(${body},SHA3-256)}");
+ s = expression.evaluate(exchange, String.class);
+ assertNotNull(s);
+ digest = MessageDigest.getInstance("SHA3-256");
+ bytes = digest.digest(exchange.getMessage().getBody(String.class).getBytes(StandardCharsets.UTF_8));
+ expected = StringHelper.bytesToHex(bytes);
+ assertEquals(expected, s);
+
+ expression = context.resolveLanguage("simple").createExpression("${hash(${header.foo},SHA3-256)}");
+ s = expression.evaluate(exchange, String.class);
+ assertNotNull(s);
+
+ expression = context.resolveLanguage("simple").createExpression("${hash(${header.unknown})}");
+ s = expression.evaluate(exchange, String.class);
+ assertNull(s);
+ }
+
@Test
public void testNewEmpty() {
assertExpressionCreateNewEmpty("list", List.class, v -> ((List) v).isEmpty());
diff --git a/core/camel-util/src/main/java/org/apache/camel/util/StringHelper.java b/core/camel-util/src/main/java/org/apache/camel/util/StringHelper.java
index 6736b52ef8f..c5611e3ee33 100644
--- a/core/camel-util/src/main/java/org/apache/camel/util/StringHelper.java
+++ b/core/camel-util/src/main/java/org/apache/camel/util/StringHelper.java
@@ -1214,4 +1214,16 @@ public final class StringHelper {
return true;
}
+ public static String bytesToHex(byte[] hash) {
+ StringBuilder sb = new StringBuilder(2 * hash.length);
+ for (byte b : hash) {
+ String hex = Integer.toHexString(0xff & b);
+ if (hex.length() == 1) {
+ sb.append('0');
+ }
+ sb.append(hex);
+ }
+ return sb.toString();
+ }
+
}