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 e2ba787d518 Tm3 (#12231)
e2ba787d518 is described below
commit e2ba787d518f68340d13bd8a511b1037d50c4988
Author: Claus Ibsen <[email protected]>
AuthorDate: Tue Nov 28 14:50:00 2023 +0100
Tm3 (#12231)
CAMEL-20153: camel-jbang - Transform message command
---
.../apache/camel/builder/ModelRoutesBuilder.java | 43 ++
.../org/apache/camel/builder/RouteBuilder.java | 25 +-
.../org/apache/camel/support/LoggerHelper.java | 16 +-
.../modules/ROOT/pages/camel-jbang.adoc | 139 ++++
.../camel/cli/connector/LocalCliConnector.java | 751 +++++++++++++--------
.../apache/camel/cli/connector/LoggerHelper.java | 37 +
.../apache/camel/dsl/jbang/core/commands/Run.java | 3 +-
.../commands/action/TransformMessageAction.java | 28 +-
8 files changed, 731 insertions(+), 311 deletions(-)
diff --git
a/core/camel-core-model/src/main/java/org/apache/camel/builder/ModelRoutesBuilder.java
b/core/camel-core-model/src/main/java/org/apache/camel/builder/ModelRoutesBuilder.java
new file mode 100644
index 00000000000..2270afe5eda
--- /dev/null
+++
b/core/camel-core-model/src/main/java/org/apache/camel/builder/ModelRoutesBuilder.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.builder;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.model.RoutesDefinition;
+import org.apache.camel.model.rest.RestsDefinition;
+
+/**
+ * A {@link org.apache.camel.RoutesBuilder} that provides access to the model
definitions.
+ */
+public interface ModelRoutesBuilder {
+
+ /**
+ * Prepares the model definitions of this builder.
+ */
+ void prepareModel(CamelContext context) throws Exception;
+
+ /**
+ * Gets the routes
+ */
+ RoutesDefinition getRoutes();
+
+ /**
+ * Gets the rest-dsl
+ */
+ RestsDefinition getRests();
+
+}
diff --git
a/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java
b/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java
index d3a032bc011..0be85d0471c 100644
---
a/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java
+++
b/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java
@@ -68,7 +68,7 @@ import org.slf4j.LoggerFactory;
* A <a href="http://camel.apache.org/dsl.html">Java DSL</a> which is used to
build {@link Route} instances in a
* {@link CamelContext} for smart routing.
*/
-public abstract class RouteBuilder extends BuilderSupport implements
RoutesBuilder, Ordered, ResourceAware {
+public abstract class RouteBuilder extends BuilderSupport implements
RoutesBuilder, ModelRoutesBuilder, Ordered, ResourceAware {
protected Logger log = LoggerFactory.getLogger(getClass());
private Resource resource;
@@ -601,7 +601,7 @@ public abstract class RouteBuilder extends BuilderSupport
implements RoutesBuild
}
@Override
- public void addRoutesToCamelContext(CamelContext context) throws Exception
{
+ public void prepareModel(CamelContext context) throws Exception {
// must configure routes before rests
configureRoutes(context);
configureRests(context);
@@ -617,6 +617,13 @@ public abstract class RouteBuilder extends BuilderSupport
implements RoutesBuild
for (RouteDefinition route : routeCollection.getRoutes()) {
routeCollection.prepareRoute(route);
}
+ }
+
+ @Override
+ public void addRoutesToCamelContext(CamelContext context) throws Exception
{
+ prepareModel(context);
+
+ // this will add the routes to camel
populateRoutes();
if (this instanceof OnCamelContextEvent) {
@@ -885,6 +892,16 @@ public abstract class RouteBuilder extends BuilderSupport
implements RoutesBuild
}
}
+ @Override
+ public RoutesDefinition getRoutes() {
+ return getRouteCollection();
+ }
+
+ @Override
+ public RestsDefinition getRests() {
+ return getRestCollection();
+ }
+
public List<RegistryBeanDefinition> getBeans() {
return beans;
}
@@ -905,10 +922,6 @@ public abstract class RouteBuilder extends BuilderSupport
implements RoutesBuild
return this.routeCollection;
}
- public void setRouteCollection(RoutesDefinition routeCollection) {
- this.routeCollection = routeCollection;
- }
-
public RouteTemplatesDefinition getRouteTemplateCollection() {
return routeTemplateCollection;
}
diff --git
a/core/camel-support/src/main/java/org/apache/camel/support/LoggerHelper.java
b/core/camel-support/src/main/java/org/apache/camel/support/LoggerHelper.java
index 28cca1bf379..ef512e8bbcd 100644
---
a/core/camel-support/src/main/java/org/apache/camel/support/LoggerHelper.java
+++
b/core/camel-support/src/main/java/org/apache/camel/support/LoggerHelper.java
@@ -103,15 +103,17 @@ public final class LoggerHelper {
int cnt = StringHelper.countChar(location, ':');
if (cnt > 1) {
int pos = location.lastIndexOf(':');
- String num = location.substring(pos);
- try {
- return Integer.valueOf(num);
- } catch (Exception e) {
- return null;
+ // in case pos is end of line
+ if (pos < location.length() - 1) {
+ String num = location.substring(pos + 1);
+ try {
+ return Integer.valueOf(num);
+ } catch (Exception e) {
+ return null;
+ }
}
- } else {
- return null;
}
+ return null;
}
}
diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
index a4b7e769ddb..b402046aea3 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
@@ -2244,6 +2244,145 @@ And the output:
Then you can continue to update the `transform.json` until you have the
desired result. And if you make a mistake
then you see an error (in red) with stacktrace that hopefully can help you out
how to fix this.
+=== Transforming directly from Camel DSL source
+
+In the example above we externalize the transformation into a template file
named `transform.json`.
+However, its also possible to transform directly in the Camel DSL route.
+
+In the following we cover the json-transform example from:
https://github.com/apache/camel-kamelets-examples/tree/main/jbang/json-transform
+
+In this example a random beer is fetched via the beer-source kamelet. The beer
data is as follows:
+
+[source,json]
+----
+ {
+ "id": 2104,
+ "uid": "cefb36e1-e42f-4083-8f97-fc4ff85e56fb",
+ "brand": "Pabst Blue Ribbon",
+ "name": "St. Bernardus Abt 12",
+ "style": "Belgian Strong Ale",
+ "hop": "Amarillo",
+ "yeast": "1388 - Belgian Strong Ale",
+ "malts": "Caramel",
+ "ibu": "43 IBU",
+ "alcohol": "3.8%",
+ "blg": "16.0°Blg"
+ }
+----
+
+We save this beer into a file named `sample.json` as we want to use this as
source for message transformation.
+
+Now suppose we want to transform this to a smaller JSon document with only a
few elements, then we can do this
+directly in the route:
+
+[source,yaml]
+----
+- route:
+ nodePrefixId: route-c38
+ id: route-66b0
+ from:
+ uri: kamelet:beer-source
+ id: from-3996
+ steps:
+ - setBody:
+ expression:
+ simple:
+ expression: >-
+ TODO
+ id: simple-b320
+ id: setBody-fa01
+ - log:
+ message: ${body}
+ id: log-0c79
+----
+
+As we can see the route has a `setBody` where we want to transform the
message, which we can do with the simple
+language combined with JQ (or JSonPath). At first, we just write TODO to get
started:
+
+[source,bash]
+----
+camel transform message --body=file:sample.json --source=beer-jq.yaml --watch
--pretty
+----
+
+And the output from the transformation is:
+
+[source,text]
+----
+ Exchange (DefaultExchange) InOut D9F909701338607-0000000000000004
+ Message (DefaultMessage)
+ Body (String) (bytes: 4)
+ TODO
+----
+
+We can now do live updates in the Camel route, and when we save the file, the
transform command will output the changes in the terminal.
+So we modify the DSL to grab the details we want, such as:
+
+[source,yaml]
+----
+ expression: >-
+ {
+ "kind": "${jq(.brand)}",
+ "beer": "${jq(.name)}"
+ }
+ id: simple-b320
+----
+
+Notice how we use inlined JQ expressions to grab the desired data from the
sample, and when saving the file, we have
+the result shown in the terminal:
+
+[source,text]
+----
+ Exchange (DefaultExchange) InOut D9F909701338607-000000000000003E
+ Message (DefaultMessage)
+ Body (String) (bytes: 78)
+ {
+ "kind": "Pabst Blue Ribbon",
+ "beer": "St. Bernardus Abt 12"
+ }
+----
+
+And when we are done with the transformation we can stop by `ctrl + c` to exit
the command.
+
+When transforming messages directly from the DSL (using the `--source`
option), then by default
+Camel will pick the last expression in the route. If you only have one
expression like in this example,
+then that is easy. But when you have many, then you need to tell which one to
use.
+
+You can do this either by referring to the line number in the source code of
the EIP / expression, or
+by its id (if specified).
+
+So suppose the example had many expressions, and the one we want to use is on
line 11, then we can do as follows:
+
+[source,bash]
+----
+camel transform message --body=file:sample.json --source=beer-jq.yaml:11
--watch --pretty
+----
+
+Notice how we specify the line number in the source file name, by prefixing
with `:line-number`.
+The line number does not have to be 100% accurate, as long the number is
within range of the EIP, until
+the next EIP in the route. In the example this means you can pick number in
range 8-17.
+
+If we want to use the id of the expression/EIP, we can do the same as shown
below:
+
+[source,bash]
+----
+camel transform message --body=file:sample.json
--source=beer-jq.yaml:setBody-fa01 --watch --pretty
+----
+
+You can also transform the message from JSon to XML as shown (or any other
kind with fixed structure):
+
+[source,yaml]
+----
+- setBody:
+ expression:
+ simple:
+ expression: >-
+ <beer id="${jq(.id)}">
+ <name>${jq(.name)}</name>
+ <kind>${jq(.brand)}</kind>
+ </beer>
+ id: simple-b320
+ id: setBody-fa01
+----
== Listing what Camel components is available
diff --git
a/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/LocalCliConnector.java
b/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/LocalCliConnector.java
index 641569e55b9..0ddbc80b69d 100644
---
a/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/LocalCliConnector.java
+++
b/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/LocalCliConnector.java
@@ -18,6 +18,7 @@ package org.apache.camel.cli.connector;
import java.io.File;
import java.io.FileInputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.lang.management.ClassLoadingMXBean;
import java.lang.management.GarbageCollectorMXBean;
@@ -25,6 +26,8 @@ import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadMXBean;
+import java.nio.file.Files;
+import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
@@ -48,14 +51,24 @@ import org.apache.camel.NoSuchEndpointException;
import org.apache.camel.Processor;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.Route;
+import org.apache.camel.RoutesBuilder;
import org.apache.camel.api.management.ManagedCamelContext;
+import org.apache.camel.builder.ModelRoutesBuilder;
import org.apache.camel.console.DevConsole;
import org.apache.camel.console.DevConsoleRegistry;
+import org.apache.camel.model.HasExpressionType;
+import org.apache.camel.model.ProcessorDefinition;
+import org.apache.camel.model.ProcessorDefinitionHelper;
+import org.apache.camel.model.RouteDefinition;
+import org.apache.camel.model.language.ExpressionDefinition;
import org.apache.camel.spi.CliConnector;
import org.apache.camel.spi.CliConnectorFactory;
import org.apache.camel.spi.ContextReloadStrategy;
import org.apache.camel.spi.Language;
+import org.apache.camel.spi.Resource;
+import org.apache.camel.spi.ResourceLoader;
import org.apache.camel.spi.ResourceReloadStrategy;
+import org.apache.camel.spi.RoutesLoader;
import org.apache.camel.support.EndpointHelper;
import org.apache.camel.support.MessageHelper;
import org.apache.camel.support.PatternHelper;
@@ -98,6 +111,8 @@ public class LocalCliConnector extends ServiceSupport
implements CliConnector, C
private File traceFile;
private File debugFile;
private long traceFilePos; // keep track of trace offset
+ private byte[] lastSource;
+ private ExpressionDefinition lastSourceExpression;
public LocalCliConnector(CliConnectorFactory cliConnectorFactory) {
this.cliConnectorFactory = cliConnectorFactory;
@@ -216,327 +231,293 @@ public class LocalCliConnector extends ServiceSupport
implements CliConnector, C
String action = root.getString("action");
if ("route".equals(action)) {
- // id is a pattern
- String[] patterns = root.getString("id").split(",");
- // find matching IDs
- List<String> ids = camelContext.getRoutes()
- .stream().map(Route::getRouteId)
- .filter(routeId -> {
- for (String p : patterns) {
- if (PatternHelper.matchPattern(routeId, p)) {
- return true;
- }
- }
- return false;
- })
- .toList();
- for (String id : ids) {
- try {
- String command = root.getString("command");
- if ("start".equals(command)) {
- if ("*".equals(id)) {
-
camelContext.getRouteController().startAllRoutes();
- } else {
-
camelContext.getRouteController().startRoute(id);
- }
- } else if ("stop".equals(command)) {
- if ("*".equals(id)) {
-
camelContext.getRouteController().stopAllRoutes();
- } else {
-
camelContext.getRouteController().stopRoute(id);
- }
- } else if ("suspend".equals(command)) {
- camelContext.getRouteController().suspendRoute(id);
- } else if ("resume".equals(command)) {
- camelContext.getRouteController().resumeRoute(id);
- }
- } catch (Exception e) {
- // ignore
- }
- }
+ doActionRouteTask(root);
} else if ("logger".equals(action)) {
- try {
- String command = root.getString("command");
- if ("set-logging-level".equals(command)) {
- String logger = root.getString("logger-name");
- String level = root.getString("logging-level");
- LoggerHelper.changeLoggingLevel(logger, level);
- }
- } catch (Exception e) {
- // ignore
- }
+ doActionLoggerTask(root);
} else if ("gc".equals(action)) {
System.gc();
} else if ("reload".equals(action)) {
- ContextReloadStrategy cr =
camelContext.hasService(ContextReloadStrategy.class);
- if (cr != null) {
- cr.onReload("Camel CLI");
- } else {
- ResourceReloadStrategy rr =
camelContext.hasService(ResourceReloadStrategy.class);
- if (rr != null) {
- rr.onReload("Camel CLI");
- }
- }
+ doActionReloadTask();
} else if ("debug".equals(action)) {
- DevConsole dc =
camelContext.getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class)
- .resolveById("debug");
- if (dc != null) {
- String cmd = root.getStringOrDefault("command", "");
- String bp = root.getStringOrDefault("breakpoint", "");
- String history = root.getStringOrDefault("history",
"false");
- JsonObject json = (JsonObject)
dc.call(DevConsole.MediaType.JSON,
- Map.of("command", cmd, "breakpoint", bp,
"history", history));
- LOG.trace("Updating output file: {}", outputFile);
- IOHelper.writeText(json.toJson(), outputFile);
- }
+ doActionDebugTask(root);
} else if ("reset-stats".equals(action)) {
- ManagedCamelContext mcc =
camelContext.getCamelContextExtension().getContextPlugin(ManagedCamelContext.class);
- if (mcc != null) {
- mcc.getManagedCamelContext().reset(true);
- }
+ doActionResetStatsTask();
} else if ("thread-dump".equals(action)) {
- DevConsole dc =
camelContext.getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class)
- .resolveById("thread");
- if (dc != null) {
- JsonObject json = (JsonObject)
dc.call(DevConsole.MediaType.JSON, Map.of("stackTrace", "true"));
- LOG.trace("Updating output file: {}", outputFile);
- IOHelper.writeText(json.toJson(), outputFile);
- }
+ doActionThreadDumpTask();
} else if ("top-processors".equals(action)) {
- DevConsole dc
- =
camelContext.getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class).resolveById("top");
- if (dc != null) {
- JsonObject json = (JsonObject)
dc.call(DevConsole.MediaType.JSON, Map.of(Exchange.HTTP_PATH, "/*"));
- LOG.trace("Updating output file: {}", outputFile);
- IOHelper.writeText(json.toJson(), outputFile);
- }
+ doActionTopProcessorsTask();
} else if ("source".equals(action)) {
- DevConsole dc =
camelContext.getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class)
- .resolveById("source");
- if (dc != null) {
- String filter = root.getString("filter");
- JsonObject json = (JsonObject)
dc.call(DevConsole.MediaType.JSON, Map.of("filter", filter));
- LOG.trace("Updating output file: {}", outputFile);
- IOHelper.writeText(json.toJson(), outputFile);
- }
+ doActionSourceTask(root);
} else if ("route-dump".equals(action)) {
- DevConsole dc =
camelContext.getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class)
- .resolveById("route-dump");
- if (dc != null) {
- String filter = root.getString("filter");
- String format = root.getString("format");
- String uriAsParameters = root.getString("uriAsParameters");
- JsonObject json
- = (JsonObject) dc.call(DevConsole.MediaType.JSON,
- Map.of("filter", filter, "format", format,
"uriAsParameters", uriAsParameters));
- LOG.trace("Updating output file: {}", outputFile);
- IOHelper.writeText(json.toJson(), outputFile);
- }
+ doActionRouteDumpTask(root);
} else if ("route-controller".equals(action)) {
- DevConsole dc =
camelContext.getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class)
- .resolveById("route-controller");
- if (dc != null) {
- String stacktrace = root.getString("stacktrace");
- JsonObject json = (JsonObject)
dc.call(DevConsole.MediaType.JSON, Map.of("stacktrace", stacktrace));
- LOG.trace("Updating output file: {}", outputFile);
- IOHelper.writeText(json.toJson(), outputFile);
- }
+ doActionRouteControllerTask(root);
} else if ("startup-recorder".equals(action)) {
- DevConsole dc =
camelContext.getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class)
- .resolveById("startup-recorder");
- if (dc != null) {
- JsonObject json = (JsonObject)
dc.call(DevConsole.MediaType.JSON);
- LOG.trace("Updating output file: {}", outputFile);
- IOHelper.writeText(json.toJson(), outputFile);
- }
+ doActionStartupRecorder();
} else if ("stub".equals(action)) {
- String filter = root.getString("filter");
- String limit = root.getString("limit");
- String browse = root.getString("browse");
-
- DevConsole dc =
camelContext.getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class)
- .resolveById("stub");
- if (dc != null) {
- JsonObject json = (JsonObject)
dc.call(DevConsole.MediaType.JSON,
- Map.of("filter", filter, "limit", limit, "browse",
browse));
- LOG.trace("Updating output file: {}", outputFile);
- IOHelper.writeText(json.toJson(), outputFile);
- }
+ doActionStubTask(root);
} else if ("send".equals(action)) {
- StopWatch watch = new StopWatch();
- long timestamp = System.currentTimeMillis();
- String endpoint = root.getString("endpoint");
- String body = root.getString("body");
- String exchangePattern = root.getString("exchangePattern");
- Collection<JsonObject> headers = root.getCollection("headers");
- if (body != null) {
- InputStream is = null;
- Object b = body;
- Map<String, Object> map = null;
- if (body.startsWith("file:")) {
- File file = new File(body.substring(5));
- is = new FileInputStream(file);
- b = is;
- }
- if (headers != null) {
- map = new HashMap<>();
- for (JsonObject jo : headers) {
- map.put(jo.getString("key"),
jo.getString("value"));
- }
+ doActionSendTask(root);
+ } else if ("transform".equals(action)) {
+ doActionTransformTask(root);
+ }
+
+ // action done so delete file
+ FileUtil.deleteFile(actionFile);
+
+ } catch (Exception e) {
+ // ignore
+ // TODO: reduce to debug
+ LOG.warn("Error executing action file: {} due to: {}. This
exception is ignored.", actionFile, e.getMessage(),
+ e);
+ }
+ }
+
+ private void doActionTransformTask(JsonObject root) throws Exception {
+ StopWatch watch = new StopWatch();
+ long timestamp = System.currentTimeMillis();
+ String source = root.getString("source");
+ String language = root.getString("language");
+ String template = Jsoner.unescape(root.getStringOrDefault("template",
""));
+ if (template.startsWith("file:")) {
+ template = "resource:" + template;
+ }
+ String body = Jsoner.unescape(root.getString("body"));
+ InputStream is = null;
+ Object b = body;
+ Map<String, Object> map = null;
+ if (body.startsWith("file:")) {
+ File file = new File(body.substring(5));
+ is = new FileInputStream(file);
+ b = IOHelper.loadText(is);
+ }
+ Collection<JsonObject> headers = root.getCollection("headers");
+ if (headers != null) {
+ map = new LinkedHashMap<>();
+ for (JsonObject jo : headers) {
+ map.put(jo.getString("key"), jo.getString("value"));
+ }
+ }
+ final Object inputBody = b;
+ final Map<String, Object> inputHeaders = map;
+ Exchange out =
camelContext.getCamelContextExtension().getExchangeFactory().create(false);
+ try {
+ if (source != null) {
+ Integer sourceLine =
LoggerHelper.extractSourceLocationLineNumber(source);
+ String sourceId = LoggerHelper.extractSourceLocationId(source);
+ source = LoggerHelper.stripSourceLocationLineNumber(source);
+ LOG.debug("Source: {} line: {} id: {}", source, sourceLine,
sourceId);
+
+ boolean update = true;
+ File f = new File(source);
+ if (f.isFile() && f.exists()) {
+ byte[] data = Files.readAllBytes(f.toPath());
+ if (Arrays.equals(lastSource, data)) {
+ LOG.debug("Source file: {} is not updated since last",
source);
+ update = false;
}
- final Object inputBody = b;
- final Map<String, Object> inputHeaders = map;
- Exchange out;
- Endpoint target = null;
- if (endpoint == null) {
- List<Route> routes = camelContext.getRoutes();
- if (!routes.isEmpty()) {
- // grab endpoint from 1st route
- target = routes.get(0).getEndpoint();
- }
+ lastSource = data;
+ }
+ if (update) {
+ if (sourceLine != null) {
+ LOG.info("Transforming from source: {}:{}", source,
sourceLine);
+ } else if (sourceId != null) {
+ LOG.info("Transforming from source: {}:{}", source,
sourceId);
} else {
- // is the endpoint a pattern or route id
- boolean scheme = endpoint.contains(":");
- boolean pattern = endpoint.endsWith("*");
- if (!scheme || pattern) {
- if (!scheme) {
- endpoint = endpoint + "*";
- }
- for (Route route : camelContext.getRoutes()) {
- Endpoint e = route.getEndpoint();
- if (EndpointHelper.matchEndpoint(camelContext,
e.getEndpointUri(), endpoint)) {
- target = e;
- break;
- }
- }
- if (target == null) {
- // okay it may refer to a route id
- for (Route route : camelContext.getRoutes()) {
- String id = route.getRouteId();
- Endpoint e = route.getEndpoint();
- if
(EndpointHelper.matchEndpoint(camelContext, id, endpoint)) {
- target = e;
- break;
- }
- }
- }
- } else {
- target = camelContext.getEndpoint(endpoint);
- }
+ LOG.info("Transforming from source: {}", source);
}
- if (target != null) {
- out = producer.send(target, new Processor() {
- @Override
- public void process(Exchange exchange) throws
Exception {
- exchange.getMessage().setBody(inputBody);
- if (inputHeaders != null) {
-
exchange.getMessage().setHeaders(inputHeaders);
+ // load route definition
+ if (!source.startsWith("file:")) {
+ source = "file:" + source;
+ }
+ // load the source via routes loader, and find the
builders, which we can use to get to the model
+ Resource res =
camelContext.getCamelContextExtension().getContextPlugin(ResourceLoader.class)
+ .resolveResource(source);
+ RoutesLoader loader =
camelContext.getCamelContextExtension().getContextPlugin(RoutesLoader.class);
+ Collection<RoutesBuilder> builders =
loader.findRoutesBuilders(res);
+ for (RoutesBuilder builder : builders) {
+ // use the model as we just want to find the EIP with
the inlined expression
+ ModelRoutesBuilder mrb = (ModelRoutesBuilder) builder;
+ // must prepare model before we can access them
+ mrb.prepareModel(camelContext);
+ // find the EIP with the inlined expression to use
+ ExpressionDefinition found = null;
+ for (RouteDefinition rd : mrb.getRoutes().getRoutes())
{
+ Collection<ProcessorDefinition> defs
+ =
ProcessorDefinitionHelper.filterTypeInOutputs(rd.getOutputs(),
+ ProcessorDefinition.class);
+ for (ProcessorDefinition p : defs) {
+ if (p instanceof HasExpressionType et) {
+ ExpressionDefinition def =
et.getExpressionType();
+ if (def != null) {
+ if (sourceLine != null) {
+ if (p.getLineNumber() == -1 ||
p.getLineNumber() <= sourceLine) {
+ found = def;
+ }
+ } else if (sourceId != null) {
+ if (sourceId.equals(p.getId()) ||
sourceId.equals(def.getId())) {
+ found = def;
+ }
+ } else {
+ found = def;
+ }
+ }
}
- exchange.setPattern(
- "InOut".equals(exchangePattern) ?
ExchangePattern.InOut : ExchangePattern.InOnly);
}
- });
- IOHelper.close(is);
- LOG.trace("Updating output file: {}", outputFile);
- if (out.getException() != null) {
- JsonObject jo = new JsonObject();
- jo.put("endpoint", target.getEndpointUri());
- jo.put("exchangeId", out.getExchangeId());
- jo.put("exchangePattern", exchangePattern);
- jo.put("timestamp", timestamp);
- jo.put("elapsed", watch.taken());
- jo.put("status", "failed");
- // avoid double wrap
- jo.put("exception",
-
MessageHelper.dumpExceptionAsJSonObject(out.getException()).getMap("exception"));
- IOHelper.writeText(jo.toJson(), outputFile);
- } else if ("InOut".equals(exchangePattern)) {
- JsonObject jo = new JsonObject();
- jo.put("endpoint", target.getEndpointUri());
- jo.put("exchangeId", out.getExchangeId());
- jo.put("exchangePattern", exchangePattern);
- jo.put("timestamp", timestamp);
- jo.put("elapsed", watch.taken());
- jo.put("status", "success");
- // avoid double wrap
- jo.put("message",
MessageHelper.dumpAsJSonObject(out.getMessage(), true, true, true, true, true,
- BODY_MAX_CHARS).getMap("message"));
- IOHelper.writeText(jo.toJson(), outputFile);
- } else {
- JsonObject jo = new JsonObject();
- jo.put("endpoint", target.getEndpointUri());
- jo.put("exchangeId", out.getExchangeId());
- jo.put("exchangePattern", exchangePattern);
- jo.put("timestamp", timestamp);
- jo.put("elapsed", watch.taken());
- jo.put("status", "success");
- IOHelper.writeText(jo.toJson(), outputFile);
+ if (found != null) {
+ lastSourceExpression = found;
+ }
}
- } else {
- // there is no valid endpoint
- JsonObject jo = new JsonObject();
- jo.put("endpoint", root.getString("endpoint"));
- jo.put("exchangeId", "");
- jo.put("exchangePattern", exchangePattern);
- jo.put("timestamp", timestamp);
- jo.put("elapsed", watch.taken());
- jo.put("status", "failed");
- // avoid double wrap
- jo.put("exception",
- MessageHelper.dumpExceptionAsJSonObject(new
NoSuchEndpointException(root.getString("endpoint")))
- .getMap("exception"));
- IOHelper.writeText(jo.toJson(), outputFile);
}
}
- } else if ("transform".equals(action)) {
- StopWatch watch = new StopWatch();
- long timestamp = System.currentTimeMillis();
- String language = root.getString("language");
- String template = Jsoner.unescape(root.getString("template"));
- if (template.startsWith("file:")) {
- template = "resource:" + template;
- }
- String body = Jsoner.unescape(root.getString("body"));
- InputStream is = null;
- Object b = body;
- Map<String, Object> map = null;
- if (body.startsWith("file:")) {
- File file = new File(body.substring(5));
- is = new FileInputStream(file);
- b = IOHelper.loadText(is);
- }
- Collection<JsonObject> headers = root.getCollection("headers");
- if (headers != null) {
- map = new LinkedHashMap<>();
- for (JsonObject jo : headers) {
- map.put(jo.getString("key"), jo.getString("value"));
- }
- }
- final Object inputBody = b;
- final Map<String, Object> inputHeaders = map;
- Exchange out =
camelContext.getCamelContextExtension().getExchangeFactory().create(false);
- try {
- Language lan = camelContext.resolveLanguage(language);
- Expression exp = lan.createExpression(template);
- exp.init(camelContext);
+ if (lastSourceExpression != null) {
// create dummy exchange with
out.setPattern(ExchangePattern.InOut);
out.getMessage().setBody(inputBody);
if (inputHeaders != null) {
out.getMessage().setHeaders(inputHeaders);
}
- String result = exp.evaluate(out, String.class);
+ String result = lastSourceExpression.evaluate(out,
String.class);
out.getMessage().setBody(result);
- IOHelper.close(is);
- } catch (Exception e) {
- out.setException(e);
}
+ } else {
+ // transform via language
+ Language lan = camelContext.resolveLanguage(language);
+ Expression exp = lan.createExpression(template);
+ exp.init(camelContext);
+ // create dummy exchange with
+ out.setPattern(ExchangePattern.InOut);
+ out.getMessage().setBody(inputBody);
+ if (inputHeaders != null) {
+ out.getMessage().setHeaders(inputHeaders);
+ }
+ String result = exp.evaluate(out, String.class);
+ out.getMessage().setBody(result);
+ }
+ IOHelper.close(is);
+ } catch (Exception e) {
+ out.setException(e);
+ }
+ LOG.trace("Updating output file: {}", outputFile);
+ if (out.getException() != null) {
+ JsonObject jo = new JsonObject();
+ if (language != null) {
+ jo.put("language", language);
+ }
+ if (source != null) {
+ jo.put("source", source);
+ }
+ jo.put("exchangeId", out.getExchangeId());
+ jo.put("timestamp", timestamp);
+ jo.put("elapsed", watch.taken());
+ jo.put("status", "failed");
+ // avoid double wrap
+ jo.put("exception",
+
MessageHelper.dumpExceptionAsJSonObject(out.getException()).getMap("exception"));
+ IOHelper.writeText(jo.toJson(), outputFile);
+ } else {
+ JsonObject jo = new JsonObject();
+ if (language != null) {
+ jo.put("language", language);
+ }
+ if (source != null) {
+ jo.put("source", source);
+ }
+ jo.put("exchangeId", out.getExchangeId());
+ jo.put("timestamp", timestamp);
+ jo.put("elapsed", watch.taken());
+ jo.put("status", "success");
+ // avoid double wrap
+ jo.put("message", MessageHelper.dumpAsJSonObject(out.getMessage(),
true, true, true, true, true,
+ BODY_MAX_CHARS).getMap("message"));
+ IOHelper.writeText(jo.toJson(), outputFile);
+ }
+
camelContext.getCamelContextExtension().getExchangeFactory().release(out);
+ }
+
+ private void doActionSendTask(JsonObject root) throws Exception {
+ StopWatch watch = new StopWatch();
+ long timestamp = System.currentTimeMillis();
+ String endpoint = root.getString("endpoint");
+ String body = root.getString("body");
+ String exchangePattern = root.getString("exchangePattern");
+ Collection<JsonObject> headers = root.getCollection("headers");
+ if (body != null) {
+ InputStream is = null;
+ Object b = body;
+ Map<String, Object> map = null;
+ if (body.startsWith("file:")) {
+ File file = new File(body.substring(5));
+ is = new FileInputStream(file);
+ b = is;
+ }
+ if (headers != null) {
+ map = new HashMap<>();
+ for (JsonObject jo : headers) {
+ map.put(jo.getString("key"), jo.getString("value"));
+ }
+ }
+ final Object inputBody = b;
+ final Map<String, Object> inputHeaders = map;
+ Exchange out;
+ Endpoint target = null;
+ if (endpoint == null) {
+ List<Route> routes = camelContext.getRoutes();
+ if (!routes.isEmpty()) {
+ // grab endpoint from 1st route
+ target = routes.get(0).getEndpoint();
+ }
+ } else {
+ // is the endpoint a pattern or route id
+ boolean scheme = endpoint.contains(":");
+ boolean pattern = endpoint.endsWith("*");
+ if (!scheme || pattern) {
+ if (!scheme) {
+ endpoint = endpoint + "*";
+ }
+ for (Route route : camelContext.getRoutes()) {
+ Endpoint e = route.getEndpoint();
+ if (EndpointHelper.matchEndpoint(camelContext,
e.getEndpointUri(), endpoint)) {
+ target = e;
+ break;
+ }
+ }
+ if (target == null) {
+ // okay it may refer to a route id
+ for (Route route : camelContext.getRoutes()) {
+ String id = route.getRouteId();
+ Endpoint e = route.getEndpoint();
+ if (EndpointHelper.matchEndpoint(camelContext, id,
endpoint)) {
+ target = e;
+ break;
+ }
+ }
+ }
+ } else {
+ target = camelContext.getEndpoint(endpoint);
+ }
+ }
+
+ if (target != null) {
+ out = producer.send(target, new Processor() {
+ @Override
+ public void process(Exchange exchange) throws Exception {
+ exchange.getMessage().setBody(inputBody);
+ if (inputHeaders != null) {
+ exchange.getMessage().setHeaders(inputHeaders);
+ }
+ exchange.setPattern(
+ "InOut".equals(exchangePattern) ?
ExchangePattern.InOut : ExchangePattern.InOnly);
+ }
+ });
+ IOHelper.close(is);
LOG.trace("Updating output file: {}", outputFile);
if (out.getException() != null) {
JsonObject jo = new JsonObject();
- jo.put("language", language);
+ jo.put("endpoint", target.getEndpointUri());
jo.put("exchangeId", out.getExchangeId());
+ jo.put("exchangePattern", exchangePattern);
jo.put("timestamp", timestamp);
jo.put("elapsed", watch.taken());
jo.put("status", "failed");
@@ -544,10 +525,11 @@ public class LocalCliConnector extends ServiceSupport
implements CliConnector, C
jo.put("exception",
MessageHelper.dumpExceptionAsJSonObject(out.getException()).getMap("exception"));
IOHelper.writeText(jo.toJson(), outputFile);
- } else {
+ } else if ("InOut".equals(exchangePattern)) {
JsonObject jo = new JsonObject();
- jo.put("language", language);
+ jo.put("endpoint", target.getEndpointUri());
jo.put("exchangeId", out.getExchangeId());
+ jo.put("exchangePattern", exchangePattern);
jo.put("timestamp", timestamp);
jo.put("elapsed", watch.taken());
jo.put("status", "success");
@@ -555,17 +537,200 @@ public class LocalCliConnector extends ServiceSupport
implements CliConnector, C
jo.put("message",
MessageHelper.dumpAsJSonObject(out.getMessage(), true, true, true, true, true,
BODY_MAX_CHARS).getMap("message"));
IOHelper.writeText(jo.toJson(), outputFile);
+ } else {
+ JsonObject jo = new JsonObject();
+ jo.put("endpoint", target.getEndpointUri());
+ jo.put("exchangeId", out.getExchangeId());
+ jo.put("exchangePattern", exchangePattern);
+ jo.put("timestamp", timestamp);
+ jo.put("elapsed", watch.taken());
+ jo.put("status", "success");
+ IOHelper.writeText(jo.toJson(), outputFile);
}
-
camelContext.getCamelContextExtension().getExchangeFactory().release(out);
+ } else {
+ // there is no valid endpoint
+ JsonObject jo = new JsonObject();
+ jo.put("endpoint", root.getString("endpoint"));
+ jo.put("exchangeId", "");
+ jo.put("exchangePattern", exchangePattern);
+ jo.put("timestamp", timestamp);
+ jo.put("elapsed", watch.taken());
+ jo.put("status", "failed");
+ // avoid double wrap
+ jo.put("exception",
+ MessageHelper.dumpExceptionAsJSonObject(new
NoSuchEndpointException(root.getString("endpoint")))
+ .getMap("exception"));
+ IOHelper.writeText(jo.toJson(), outputFile);
}
+ }
+ }
- // action done so delete file
- FileUtil.deleteFile(actionFile);
+ private void doActionStubTask(JsonObject root) throws Exception {
+ String filter = root.getString("filter");
+ String limit = root.getString("limit");
+ String browse = root.getString("browse");
+ DevConsole dc =
camelContext.getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class)
+ .resolveById("stub");
+ if (dc != null) {
+ JsonObject json = (JsonObject) dc.call(DevConsole.MediaType.JSON,
+ Map.of("filter", filter, "limit", limit, "browse",
browse));
+ LOG.trace("Updating output file: {}", outputFile);
+ IOHelper.writeText(json.toJson(), outputFile);
+ }
+ }
+
+ private void doActionStartupRecorder() throws Exception {
+ DevConsole dc =
camelContext.getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class)
+ .resolveById("startup-recorder");
+ if (dc != null) {
+ JsonObject json = (JsonObject) dc.call(DevConsole.MediaType.JSON);
+ LOG.trace("Updating output file: {}", outputFile);
+ IOHelper.writeText(json.toJson(), outputFile);
+ }
+ }
+
+ private void doActionRouteControllerTask(JsonObject root) throws Exception
{
+ DevConsole dc =
camelContext.getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class)
+ .resolveById("route-controller");
+ if (dc != null) {
+ String stacktrace = root.getString("stacktrace");
+ JsonObject json = (JsonObject) dc.call(DevConsole.MediaType.JSON,
Map.of("stacktrace", stacktrace));
+ LOG.trace("Updating output file: {}", outputFile);
+ IOHelper.writeText(json.toJson(), outputFile);
+ }
+ }
+
+ private void doActionRouteDumpTask(JsonObject root) throws Exception {
+ DevConsole dc =
camelContext.getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class)
+ .resolveById("route-dump");
+ if (dc != null) {
+ String filter = root.getString("filter");
+ String format = root.getString("format");
+ String uriAsParameters = root.getString("uriAsParameters");
+ JsonObject json
+ = (JsonObject) dc.call(DevConsole.MediaType.JSON,
+ Map.of("filter", filter, "format", format,
"uriAsParameters", uriAsParameters));
+ LOG.trace("Updating output file: {}", outputFile);
+ IOHelper.writeText(json.toJson(), outputFile);
+ }
+ }
+
+ private void doActionSourceTask(JsonObject root) throws Exception {
+ DevConsole dc =
camelContext.getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class)
+ .resolveById("source");
+ if (dc != null) {
+ String filter = root.getString("filter");
+ JsonObject json = (JsonObject) dc.call(DevConsole.MediaType.JSON,
Map.of("filter", filter));
+ LOG.trace("Updating output file: {}", outputFile);
+ IOHelper.writeText(json.toJson(), outputFile);
+ }
+ }
+
+ private void doActionTopProcessorsTask() throws IOException {
+ DevConsole dc
+ =
camelContext.getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class).resolveById("top");
+ if (dc != null) {
+ JsonObject json = (JsonObject) dc.call(DevConsole.MediaType.JSON,
Map.of(Exchange.HTTP_PATH, "/*"));
+ LOG.trace("Updating output file: {}", outputFile);
+ IOHelper.writeText(json.toJson(), outputFile);
+ }
+ }
+
+ private void doActionThreadDumpTask() throws IOException {
+ DevConsole dc =
camelContext.getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class)
+ .resolveById("thread");
+ if (dc != null) {
+ JsonObject json = (JsonObject) dc.call(DevConsole.MediaType.JSON,
Map.of("stackTrace", "true"));
+ LOG.trace("Updating output file: {}", outputFile);
+ IOHelper.writeText(json.toJson(), outputFile);
+ }
+ }
+
+ private void doActionResetStatsTask() throws Exception {
+ ManagedCamelContext mcc =
camelContext.getCamelContextExtension().getContextPlugin(ManagedCamelContext.class);
+ if (mcc != null) {
+ mcc.getManagedCamelContext().reset(true);
+ }
+ }
+
+ private void doActionDebugTask(JsonObject root) throws Exception {
+ DevConsole dc =
camelContext.getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class)
+ .resolveById("debug");
+ if (dc != null) {
+ String cmd = root.getStringOrDefault("command", "");
+ String bp = root.getStringOrDefault("breakpoint", "");
+ String history = root.getStringOrDefault("history", "false");
+ JsonObject json = (JsonObject) dc.call(DevConsole.MediaType.JSON,
+ Map.of("command", cmd, "breakpoint", bp, "history",
history));
+ LOG.trace("Updating output file: {}", outputFile);
+ IOHelper.writeText(json.toJson(), outputFile);
+ }
+ }
+
+ private void doActionReloadTask() {
+ ContextReloadStrategy cr =
camelContext.hasService(ContextReloadStrategy.class);
+ if (cr != null) {
+ cr.onReload("Camel CLI");
+ } else {
+ ResourceReloadStrategy rr =
camelContext.hasService(ResourceReloadStrategy.class);
+ if (rr != null) {
+ rr.onReload("Camel CLI");
+ }
+ }
+ }
+
+ private void doActionLoggerTask(JsonObject root) {
+ try {
+ String command = root.getString("command");
+ if ("set-logging-level".equals(command)) {
+ String logger = root.getString("logger-name");
+ String level = root.getString("logging-level");
+ LoggerHelper.changeLoggingLevel(logger, level);
+ }
} catch (Exception e) {
// ignore
- LOG.debug("Error executing action file: {} due to: {}. This
exception is ignored.", actionFile, e.getMessage(),
- e);
+ }
+ }
+
+ private void doActionRouteTask(JsonObject root) {
+ // id is a pattern
+ String[] patterns = root.getString("id").split(",");
+ // find matching IDs
+ List<String> ids = camelContext.getRoutes()
+ .stream().map(Route::getRouteId)
+ .filter(routeId -> {
+ for (String p : patterns) {
+ if (PatternHelper.matchPattern(routeId, p)) {
+ return true;
+ }
+ }
+ return false;
+ })
+ .toList();
+ for (String id : ids) {
+ try {
+ String command = root.getString("command");
+ if ("start".equals(command)) {
+ if ("*".equals(id)) {
+ camelContext.getRouteController().startAllRoutes();
+ } else {
+ camelContext.getRouteController().startRoute(id);
+ }
+ } else if ("stop".equals(command)) {
+ if ("*".equals(id)) {
+ camelContext.getRouteController().stopAllRoutes();
+ } else {
+ camelContext.getRouteController().stopRoute(id);
+ }
+ } else if ("suspend".equals(command)) {
+ camelContext.getRouteController().suspendRoute(id);
+ } else if ("resume".equals(command)) {
+ camelContext.getRouteController().resumeRoute(id);
+ }
+ } catch (Exception e) {
+ // ignore
+ }
}
}
diff --git
a/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/LoggerHelper.java
b/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/LoggerHelper.java
index 82e899238e3..aa01bae8b9b 100644
---
a/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/LoggerHelper.java
+++
b/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/LoggerHelper.java
@@ -23,6 +23,8 @@ import javax.management.Attribute;
import javax.management.MBeanServer;
import javax.management.ObjectName;
+import org.apache.camel.util.StringHelper;
+
/**
* Helper for logger action.
*
@@ -70,4 +72,39 @@ public final class LoggerHelper {
}
}
+ public static String stripSourceLocationLineNumber(String location) {
+ int cnt = StringHelper.countChar(location, ':');
+ if (cnt >= 1) {
+ int pos = location.lastIndexOf(':');
+ return location.substring(0, pos);
+ } else {
+ return location;
+ }
+ }
+
+ public static Integer extractSourceLocationLineNumber(String location) {
+ int cnt = StringHelper.countChar(location, ':');
+ if (cnt >= 1) {
+ int pos = location.lastIndexOf(':');
+ String num = location.substring(pos + 1);
+ try {
+ return Integer.valueOf(num);
+ } catch (Exception var5) {
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ public static String extractSourceLocationId(String location) {
+ int cnt = StringHelper.countChar(location, ':');
+ if (cnt >= 1) {
+ int pos = location.lastIndexOf(':');
+ return location.substring(pos + 1);
+ } else {
+ return null;
+ }
+ }
+
}
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
index 7876bd6ee2e..0afec4ba0ae 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
@@ -123,7 +123,7 @@ public class Run extends CamelCommand {
arity = "0..9", paramLabel = "<files>", parameterConsumer =
FilesConsumer.class)
Path[] filePaths; // Defined only for file path completion; the field
never used
- List<String> files = new ArrayList<>();
+ public List<String> files = new ArrayList<>();
@Option(names = { "--source-dir" },
description = "Source directory for dynamically loading Camel
file(s) to run. When using this, then files cannot be specified at the same
time.")
@@ -313,6 +313,7 @@ public class Run extends CamelCommand {
this.background = true;
this.camelVersion = camelVersion;
this.empty = true;
+ this.ignoreLoadingError = true;
this.name = "transform";
return run();
}
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/TransformMessageAction.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/TransformMessageAction.java
index b958329d31e..fd07c1c96d4 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/TransformMessageAction.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/TransformMessageAction.java
@@ -54,15 +54,18 @@ public class TransformMessageAction extends
ActionWatchCommand {
description = "Message header (key=value)")
List<String> headers;
+ @CommandLine.Option(names = {
+ "--source" },
+ description = "Instead of using external template file
then refer to an existing Camel route source with inlined Camel language
expression in a route. (use :line-number or :id to refer to the exact location
of the EIP to use)")
+ private String source;
+
@CommandLine.Option(names = {
"--language" },
- required = true,
description = "The language to use for message
transformation")
private String language;
@CommandLine.Option(names = {
"--template" },
- required = true,
description = "The template to use for message
transformation (prefix with file: to refer to loading message body from file)")
private String template;
@@ -108,6 +111,16 @@ public class TransformMessageAction extends
ActionWatchCommand {
@Override
public Integer doCall() throws Exception {
+ // either source or language/template is required
+ if (source == null && template == null && language == null) {
+ System.err.println("Either source or template and language must be
configured");
+ return -1;
+ }
+ if (source == null && (template == null || language == null)) {
+ System.err.println("Both template and language must be
configured");
+ return -1;
+ }
+
Integer exit;
try {
// start a new empty camel in the background
@@ -147,8 +160,15 @@ public class TransformMessageAction extends
ActionWatchCommand {
JsonObject root = new JsonObject();
root.put("action", "transform");
- root.put("language", language);
- root.put("template", Jsoner.escape(template));
+ if (source != null) {
+ root.put("source", source);
+ }
+ if (language != null) {
+ root.put("language", language);
+ }
+ if (template != null) {
+ root.put("template", Jsoner.escape(template));
+ }
root.put("body", Jsoner.escape(body));
if (headers != null) {
JsonArray arr = new JsonArray();