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 7dc57acec714 CAMEL-23683: add camel-shell component
7dc57acec714 is described below
commit 7dc57acec714591511044c2bcde3ae0efccd3e79
Author: John Poth <[email protected]>
AuthorDate: Wed Jun 10 14:35:21 2026 +0200
CAMEL-23683: add camel-shell component
New component that provides an interactive shell/prompt consumer,
allowing users to type messages that are routed to other Camel
endpoints. Useful for interactive CLI workflows, e.g. routing user
input to AI models or messaging systems.
---
bom/camel-bom/pom.xml | 5 +
catalog/camel-allcomponents/pom.xml | 5 +
.../org/apache/camel/catalog/components.properties | 1 +
.../org/apache/camel/catalog/components/shell.json | 39 ++++
components/camel-shell/pom.xml | 52 +++++
.../component/shell/ShellComponentConfigurer.java | 69 ++++++
.../component/shell/ShellEndpointConfigurer.java | 66 ++++++
.../component/shell/ShellEndpointUriFactory.java | 81 +++++++
.../org/apache/camel/component/shell/shell.json | 39 ++++
.../services/org/apache/camel/component.properties | 7 +
.../services/org/apache/camel/component/shell | 2 +
.../org/apache/camel/configurer/shell-component | 2 +
.../org/apache/camel/configurer/shell-endpoint | 2 +
.../org/apache/camel/urifactory/shell-endpoint | 2 +
.../camel-shell/src/main/docs/shell-component.adoc | 89 ++++++++
.../camel/component/shell/ShellComponent.java | 157 +++++++++++++
.../camel/component/shell/ShellConsumer.java | 147 +++++++++++++
.../camel/component/shell/ShellEndpoint.java | 87 ++++++++
.../src/main/resources/camel-shell-banner.txt | 6 +
.../camel/component/shell/ShellComponentTest.java | 68 ++++++
.../component/shell/ShellConsumerColorTest.java | 82 +++++++
.../camel/component/shell/ShellEndpointTest.java | 78 +++++++
components/pom.xml | 1 +
.../org/apache/camel/main/components.properties | 1 +
.../modules/ROOT/examples/json/shell.json | 1 +
docs/components/modules/ROOT/nav.adoc | 1 +
.../modules/ROOT/pages/shell-component.adoc | 1 +
.../component/ComponentsBuilderFactory.java | 13 ++
.../dsl/ShellComponentBuilderFactory.java | 159 ++++++++++++++
.../builder/endpoint/EndpointBuilderFactory.java | 1 +
.../camel/builder/endpoint/EndpointBuilders.java | 1 +
.../builder/endpoint/StaticEndpointBuilders.java | 40 ++++
.../endpoint/dsl/ShellEndpointBuilderFactory.java | 244 +++++++++++++++++++++
.../camel-component-known-dependencies.properties | 1 +
parent/pom.xml | 5 +
35 files changed, 1555 insertions(+)
diff --git a/bom/camel-bom/pom.xml b/bom/camel-bom/pom.xml
index 5bbbc6d942ef..f58c1f690ef4 100644
--- a/bom/camel-bom/pom.xml
+++ b/bom/camel-bom/pom.xml
@@ -2107,6 +2107,11 @@
<artifactId>camel-servlet</artifactId>
<version>4.21.0-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-shell</artifactId>
+ <version>4.21.0-SNAPSHOT</version>
+ </dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-shiro</artifactId>
diff --git a/catalog/camel-allcomponents/pom.xml
b/catalog/camel-allcomponents/pom.xml
index 287d4123e9bf..71ce0a779dd2 100644
--- a/catalog/camel-allcomponents/pom.xml
+++ b/catalog/camel-allcomponents/pom.xml
@@ -1887,6 +1887,11 @@
<artifactId>camel-servlet</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-shell</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-shiro</artifactId>
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties
index 624daab24279..047a990058d6 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties
@@ -323,6 +323,7 @@ seda
servicenow
servlet
sftp
+shell
sjms
sjms2
slack
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/shell.json
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/shell.json
new file mode 100644
index 000000000000..d79754deb6ae
--- /dev/null
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/shell.json
@@ -0,0 +1,39 @@
+{
+ "component": {
+ "kind": "component",
+ "name": "shell",
+ "title": "Shell",
+ "description": "Camel Shell component",
+ "deprecated": false,
+ "firstVersion": "4.21.0",
+ "label": "api",
+ "javaType": "org.apache.camel.component.shell.ShellComponent",
+ "supportLevel": "Preview",
+ "groupId": "org.apache.camel",
+ "artifactId": "camel-shell",
+ "version": "4.21.0-SNAPSHOT",
+ "scheme": "shell",
+ "extendsScheme": "",
+ "syntax": "shell:prompt",
+ "async": false,
+ "api": false,
+ "consumerOnly": true,
+ "producerOnly": false,
+ "lenientProperties": false,
+ "browsable": false,
+ "remote": false
+ },
+ "componentProperties": {
+ "bridgeErrorHandler": { "index": 0, "kind": "property", "displayName":
"Bridge Error Handler", "group": "consumer", "label": "consumer", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": false, "description":
"Allows for bridging the consumer to the Camel routing Error Handler, which
mean any exceptions (if possible) occurred while the Camel consumer is trying
to pickup incoming messages, or the like [...]
+ "autowiredEnabled": { "index": 1, "kind": "property", "displayName":
"Autowired Enabled", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": true, "description":
"Whether autowiring is enabled. This is used for automatic autowiring options
(the option must be marked as autowired) by looking up in the registry to find
if there is a single instance of matching t [...]
+ "bannerResource": { "index": 2, "kind": "property", "displayName": "Banner
Resource", "group": "advanced", "label": "advanced", "required": false, "type":
"string", "javaType": "java.lang.String", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": "camel-shell-banner.txt",
"description": "Classpath resource path to a custom banner text file" },
+ "showBanner": { "index": 3, "kind": "property", "displayName": "Show
Banner", "group": "advanced", "label": "advanced", "required": false, "type":
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": true, "description": "Whether to print the
Camel banner on startup" }
+ },
+ "properties": {
+ "prompt": { "index": 0, "kind": "path", "displayName": "Prompt", "group":
"consumer", "label": "", "required": true, "type": "string", "javaType":
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Shell prompt" },
+ "color": { "index": 1, "kind": "parameter", "displayName": "Color",
"group": "consumer", "label": "consumer", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": "cyan", "description": "Prompt color: black,
red, green, yellow, blue, magenta, cyan, white" },
+ "bridgeErrorHandler": { "index": 2, "kind": "parameter", "displayName":
"Bridge Error Handler", "group": "consumer (advanced)", "label":
"consumer,advanced", "required": false, "type": "boolean", "javaType":
"boolean", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": false, "description": "Allows for bridging the consumer to the
Camel routing Error Handler, which mean any exceptions (if possible) occurred
while the Camel consumer is trying to pickup incoming [...]
+ "exceptionHandler": { "index": 3, "kind": "parameter", "displayName":
"Exception Handler", "group": "consumer (advanced)", "label":
"consumer,advanced", "required": false, "type": "object", "javaType":
"org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.",
"deprecated": false, "autowired": false, "secret": false, "description": "To
let the consumer use a custom ExceptionHandler. Notice if the option
bridgeErrorHandler is enabled then this option is not in use. By def [...]
+ "exchangePattern": { "index": 4, "kind": "parameter", "displayName":
"Exchange Pattern", "group": "consumer (advanced)", "label":
"consumer,advanced", "required": false, "type": "enum", "javaType":
"org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ],
"deprecated": false, "autowired": false, "secret": false, "description": "Sets
the exchange pattern when the consumer creates an exchange." }
+ }
+}
diff --git a/components/camel-shell/pom.xml b/components/camel-shell/pom.xml
new file mode 100644
index 000000000000..215458b8caed
--- /dev/null
+++ b/components/camel-shell/pom.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>components</artifactId>
+ <version>4.21.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>camel-shell</artifactId>
+ <packaging>jar</packaging>
+ <name>Camel :: Shell</name>
+ <description>Camel Shell component</description>
+
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-support</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jline</groupId>
+ <artifactId>jline</artifactId>
+ <version>${jline-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-test-junit5</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git
a/components/camel-shell/src/generated/java/org/apache/camel/component/shell/ShellComponentConfigurer.java
b/components/camel-shell/src/generated/java/org/apache/camel/component/shell/ShellComponentConfigurer.java
new file mode 100644
index 000000000000..eee3e0906960
--- /dev/null
+++
b/components/camel-shell/src/generated/java/org/apache/camel/component/shell/ShellComponentConfigurer.java
@@ -0,0 +1,69 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.shell;
+
+import javax.annotation.processing.Generated;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.ExtendedPropertyConfigurerGetter;
+import org.apache.camel.spi.PropertyConfigurerGetter;
+import org.apache.camel.spi.ConfigurerStrategy;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.util.CaseInsensitiveMap;
+import org.apache.camel.support.component.PropertyConfigurerSupport;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.EndpointSchemaGeneratorMojo")
+@SuppressWarnings("unchecked")
+public class ShellComponentConfigurer extends PropertyConfigurerSupport
implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+ @Override
+ public boolean configure(CamelContext camelContext, Object obj, String
name, Object value, boolean ignoreCase) {
+ ShellComponent target = (ShellComponent) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "autowiredenabled":
+ case "autowiredEnabled":
target.setAutowiredEnabled(property(camelContext, boolean.class, value));
return true;
+ case "bannerresource":
+ case "bannerResource": target.setBannerResource(property(camelContext,
java.lang.String.class, value)); return true;
+ case "bridgeerrorhandler":
+ case "bridgeErrorHandler":
target.setBridgeErrorHandler(property(camelContext, boolean.class, value));
return true;
+ case "showbanner":
+ case "showBanner": target.setShowBanner(property(camelContext,
boolean.class, value)); return true;
+ default: return false;
+ }
+ }
+
+ @Override
+ public Class<?> getOptionType(String name, boolean ignoreCase) {
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "autowiredenabled":
+ case "autowiredEnabled": return boolean.class;
+ case "bannerresource":
+ case "bannerResource": return java.lang.String.class;
+ case "bridgeerrorhandler":
+ case "bridgeErrorHandler": return boolean.class;
+ case "showbanner":
+ case "showBanner": return boolean.class;
+ default: return null;
+ }
+ }
+
+ @Override
+ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+ ShellComponent target = (ShellComponent) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "autowiredenabled":
+ case "autowiredEnabled": return target.isAutowiredEnabled();
+ case "bannerresource":
+ case "bannerResource": return target.getBannerResource();
+ case "bridgeerrorhandler":
+ case "bridgeErrorHandler": return target.isBridgeErrorHandler();
+ case "showbanner":
+ case "showBanner": return target.isShowBanner();
+ default: return null;
+ }
+ }
+}
+
diff --git
a/components/camel-shell/src/generated/java/org/apache/camel/component/shell/ShellEndpointConfigurer.java
b/components/camel-shell/src/generated/java/org/apache/camel/component/shell/ShellEndpointConfigurer.java
new file mode 100644
index 000000000000..e8b735901d71
--- /dev/null
+++
b/components/camel-shell/src/generated/java/org/apache/camel/component/shell/ShellEndpointConfigurer.java
@@ -0,0 +1,66 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.shell;
+
+import javax.annotation.processing.Generated;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.ExtendedPropertyConfigurerGetter;
+import org.apache.camel.spi.PropertyConfigurerGetter;
+import org.apache.camel.spi.ConfigurerStrategy;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.util.CaseInsensitiveMap;
+import org.apache.camel.support.component.PropertyConfigurerSupport;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.EndpointSchemaGeneratorMojo")
+@SuppressWarnings("unchecked")
+public class ShellEndpointConfigurer extends PropertyConfigurerSupport
implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+ @Override
+ public boolean configure(CamelContext camelContext, Object obj, String
name, Object value, boolean ignoreCase) {
+ ShellEndpoint target = (ShellEndpoint) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "bridgeerrorhandler":
+ case "bridgeErrorHandler":
target.setBridgeErrorHandler(property(camelContext, boolean.class, value));
return true;
+ case "color": target.setColor(property(camelContext,
java.lang.String.class, value)); return true;
+ case "exceptionhandler":
+ case "exceptionHandler":
target.setExceptionHandler(property(camelContext,
org.apache.camel.spi.ExceptionHandler.class, value)); return true;
+ case "exchangepattern":
+ case "exchangePattern":
target.setExchangePattern(property(camelContext,
org.apache.camel.ExchangePattern.class, value)); return true;
+ default: return false;
+ }
+ }
+
+ @Override
+ public Class<?> getOptionType(String name, boolean ignoreCase) {
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "bridgeerrorhandler":
+ case "bridgeErrorHandler": return boolean.class;
+ case "color": return java.lang.String.class;
+ case "exceptionhandler":
+ case "exceptionHandler": return
org.apache.camel.spi.ExceptionHandler.class;
+ case "exchangepattern":
+ case "exchangePattern": return org.apache.camel.ExchangePattern.class;
+ default: return null;
+ }
+ }
+
+ @Override
+ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+ ShellEndpoint target = (ShellEndpoint) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "bridgeerrorhandler":
+ case "bridgeErrorHandler": return target.isBridgeErrorHandler();
+ case "color": return target.getColor();
+ case "exceptionhandler":
+ case "exceptionHandler": return target.getExceptionHandler();
+ case "exchangepattern":
+ case "exchangePattern": return target.getExchangePattern();
+ default: return null;
+ }
+ }
+}
+
diff --git
a/components/camel-shell/src/generated/java/org/apache/camel/component/shell/ShellEndpointUriFactory.java
b/components/camel-shell/src/generated/java/org/apache/camel/component/shell/ShellEndpointUriFactory.java
new file mode 100644
index 000000000000..ff36c6e6aecb
--- /dev/null
+++
b/components/camel-shell/src/generated/java/org/apache/camel/component/shell/ShellEndpointUriFactory.java
@@ -0,0 +1,81 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.shell;
+
+import javax.annotation.processing.Generated;
+import java.net.URISyntaxException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.camel.spi.EndpointUriFactory;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.GenerateEndpointUriFactoryMojo")
+public class ShellEndpointUriFactory extends
org.apache.camel.support.component.EndpointUriFactorySupport implements
EndpointUriFactory {
+
+ private static final String BASE = ":prompt";
+
+ private static final Set<String> PROPERTY_NAMES;
+ private static final Set<String> SECRET_PROPERTY_NAMES;
+ private static final Set<String> ENDPOINT_IDENTITY_PROPERTY_NAMES;
+ private static final Map<String, String> MULTI_VALUE_PREFIXES;
+ static {
+ Set<String> props = new HashSet<>(5);
+ props.add("bridgeErrorHandler");
+ props.add("color");
+ props.add("exceptionHandler");
+ props.add("exchangePattern");
+ props.add("prompt");
+ PROPERTY_NAMES = Collections.unmodifiableSet(props);
+ SECRET_PROPERTY_NAMES = Collections.emptySet();
+ ENDPOINT_IDENTITY_PROPERTY_NAMES = Collections.emptySet();
+ MULTI_VALUE_PREFIXES = Collections.emptyMap();
+ }
+
+ @Override
+ public boolean isEnabled(String scheme) {
+ return "shell".equals(scheme);
+ }
+
+ @Override
+ public String buildUri(String scheme, Map<String, Object> properties,
boolean encode) throws URISyntaxException {
+ String syntax = scheme + BASE;
+ String uri = syntax;
+
+ Map<String, Object> copy = new HashMap<>(properties);
+
+ uri = buildPathParameter(syntax, uri, "prompt", null, true, copy);
+ uri = buildQueryParameters(uri, copy, encode);
+ return uri;
+ }
+
+ @Override
+ public Set<String> propertyNames() {
+ return PROPERTY_NAMES;
+ }
+
+ @Override
+ public Set<String> secretPropertyNames() {
+ return SECRET_PROPERTY_NAMES;
+ }
+
+ @Override
+ public Set<String> endpointIdentityPropertyNames() {
+ return ENDPOINT_IDENTITY_PROPERTY_NAMES;
+ }
+
+ @Override
+ public Map<String, String> multiValuePrefixes() {
+ return MULTI_VALUE_PREFIXES;
+ }
+
+ @Override
+ public boolean isLenientProperties() {
+ return false;
+ }
+}
+
diff --git
a/components/camel-shell/src/generated/resources/META-INF/org/apache/camel/component/shell/shell.json
b/components/camel-shell/src/generated/resources/META-INF/org/apache/camel/component/shell/shell.json
new file mode 100644
index 000000000000..d79754deb6ae
--- /dev/null
+++
b/components/camel-shell/src/generated/resources/META-INF/org/apache/camel/component/shell/shell.json
@@ -0,0 +1,39 @@
+{
+ "component": {
+ "kind": "component",
+ "name": "shell",
+ "title": "Shell",
+ "description": "Camel Shell component",
+ "deprecated": false,
+ "firstVersion": "4.21.0",
+ "label": "api",
+ "javaType": "org.apache.camel.component.shell.ShellComponent",
+ "supportLevel": "Preview",
+ "groupId": "org.apache.camel",
+ "artifactId": "camel-shell",
+ "version": "4.21.0-SNAPSHOT",
+ "scheme": "shell",
+ "extendsScheme": "",
+ "syntax": "shell:prompt",
+ "async": false,
+ "api": false,
+ "consumerOnly": true,
+ "producerOnly": false,
+ "lenientProperties": false,
+ "browsable": false,
+ "remote": false
+ },
+ "componentProperties": {
+ "bridgeErrorHandler": { "index": 0, "kind": "property", "displayName":
"Bridge Error Handler", "group": "consumer", "label": "consumer", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": false, "description":
"Allows for bridging the consumer to the Camel routing Error Handler, which
mean any exceptions (if possible) occurred while the Camel consumer is trying
to pickup incoming messages, or the like [...]
+ "autowiredEnabled": { "index": 1, "kind": "property", "displayName":
"Autowired Enabled", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": true, "description":
"Whether autowiring is enabled. This is used for automatic autowiring options
(the option must be marked as autowired) by looking up in the registry to find
if there is a single instance of matching t [...]
+ "bannerResource": { "index": 2, "kind": "property", "displayName": "Banner
Resource", "group": "advanced", "label": "advanced", "required": false, "type":
"string", "javaType": "java.lang.String", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": "camel-shell-banner.txt",
"description": "Classpath resource path to a custom banner text file" },
+ "showBanner": { "index": 3, "kind": "property", "displayName": "Show
Banner", "group": "advanced", "label": "advanced", "required": false, "type":
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": true, "description": "Whether to print the
Camel banner on startup" }
+ },
+ "properties": {
+ "prompt": { "index": 0, "kind": "path", "displayName": "Prompt", "group":
"consumer", "label": "", "required": true, "type": "string", "javaType":
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Shell prompt" },
+ "color": { "index": 1, "kind": "parameter", "displayName": "Color",
"group": "consumer", "label": "consumer", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": "cyan", "description": "Prompt color: black,
red, green, yellow, blue, magenta, cyan, white" },
+ "bridgeErrorHandler": { "index": 2, "kind": "parameter", "displayName":
"Bridge Error Handler", "group": "consumer (advanced)", "label":
"consumer,advanced", "required": false, "type": "boolean", "javaType":
"boolean", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": false, "description": "Allows for bridging the consumer to the
Camel routing Error Handler, which mean any exceptions (if possible) occurred
while the Camel consumer is trying to pickup incoming [...]
+ "exceptionHandler": { "index": 3, "kind": "parameter", "displayName":
"Exception Handler", "group": "consumer (advanced)", "label":
"consumer,advanced", "required": false, "type": "object", "javaType":
"org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.",
"deprecated": false, "autowired": false, "secret": false, "description": "To
let the consumer use a custom ExceptionHandler. Notice if the option
bridgeErrorHandler is enabled then this option is not in use. By def [...]
+ "exchangePattern": { "index": 4, "kind": "parameter", "displayName":
"Exchange Pattern", "group": "consumer (advanced)", "label":
"consumer,advanced", "required": false, "type": "enum", "javaType":
"org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ],
"deprecated": false, "autowired": false, "secret": false, "description": "Sets
the exchange pattern when the consumer creates an exchange." }
+ }
+}
diff --git
a/components/camel-shell/src/generated/resources/META-INF/services/org/apache/camel/component.properties
b/components/camel-shell/src/generated/resources/META-INF/services/org/apache/camel/component.properties
new file mode 100644
index 000000000000..03e0d9af2d55
--- /dev/null
+++
b/components/camel-shell/src/generated/resources/META-INF/services/org/apache/camel/component.properties
@@ -0,0 +1,7 @@
+# Generated by camel build tools - do NOT edit this file!
+components=shell
+groupId=org.apache.camel
+artifactId=camel-shell
+version=4.21.0-SNAPSHOT
+projectName=Camel :: Shell
+projectDescription=Camel Shell component
diff --git
a/components/camel-shell/src/generated/resources/META-INF/services/org/apache/camel/component/shell
b/components/camel-shell/src/generated/resources/META-INF/services/org/apache/camel/component/shell
new file mode 100644
index 000000000000..c5c828554b5f
--- /dev/null
+++
b/components/camel-shell/src/generated/resources/META-INF/services/org/apache/camel/component/shell
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.shell.ShellComponent
diff --git
a/components/camel-shell/src/generated/resources/META-INF/services/org/apache/camel/configurer/shell-component
b/components/camel-shell/src/generated/resources/META-INF/services/org/apache/camel/configurer/shell-component
new file mode 100644
index 000000000000..176d74b5871f
--- /dev/null
+++
b/components/camel-shell/src/generated/resources/META-INF/services/org/apache/camel/configurer/shell-component
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.shell.ShellComponentConfigurer
diff --git
a/components/camel-shell/src/generated/resources/META-INF/services/org/apache/camel/configurer/shell-endpoint
b/components/camel-shell/src/generated/resources/META-INF/services/org/apache/camel/configurer/shell-endpoint
new file mode 100644
index 000000000000..2783d432f167
--- /dev/null
+++
b/components/camel-shell/src/generated/resources/META-INF/services/org/apache/camel/configurer/shell-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.shell.ShellEndpointConfigurer
diff --git
a/components/camel-shell/src/generated/resources/META-INF/services/org/apache/camel/urifactory/shell-endpoint
b/components/camel-shell/src/generated/resources/META-INF/services/org/apache/camel/urifactory/shell-endpoint
new file mode 100644
index 000000000000..7455a1233587
--- /dev/null
+++
b/components/camel-shell/src/generated/resources/META-INF/services/org/apache/camel/urifactory/shell-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.shell.ShellEndpointUriFactory
diff --git a/components/camel-shell/src/main/docs/shell-component.adoc
b/components/camel-shell/src/main/docs/shell-component.adoc
new file mode 100644
index 000000000000..186f14a2e7d8
--- /dev/null
+++ b/components/camel-shell/src/main/docs/shell-component.adoc
@@ -0,0 +1,89 @@
+= Shell Component
+:doctitle: Shell
+:shortname: shell
+:artifactid: camel-shell
+:description: Camel Shell component
+:since: 4.21
+:supportlevel: Preview
+:tabs-sync-option:
+:component-header: Only consumer is supported
+
+*Since Camel {since}*
+
+*{component-header}*
+
+The Shell component provides an interactive terminal prompt using
https://github.com/jline/jline3[JLine].
+It allows Camel routes to read user input line-by-line (consumer) and write
output back to the terminal.
+
+Each line typed by the user becomes the body of a Camel `Exchange` that is
routed normally.
+The response (exchange body after routing) is printed back to the terminal.
+Typing `exit` or sending EOF (Ctrl+D) shuts down the Camel context.
+
+== Dependencies
+
+Maven users need to add the following dependency to their `pom.xml`:
+
+[source,xml]
+----
+<dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-shell</artifactId>
+ <version>${camel-version}</version>
+ <!-- use the same version as your Camel core version -->
+</dependency>
+----
+
+== URI format
+
+[source]
+----
+shell:prompt[?options]
+----
+
+Where `prompt` is the label displayed before the `>` cursor.
+For example, `shell:myapp` displays `myapp> `.
+
+// component options: START
+include::partial$component-configure-options.adoc[]
+include::partial$component-endpoint-options.adoc[]
+include::partial$component-endpoint-headers.adoc[]
+// component options: END
+
+== Usage
+
+=== Consumer
+
+The shell consumer starts an interactive terminal session.
+Each line typed by the user is set as the body of a new `Exchange` and sent
through the route.
+The route result body is then printed back to the terminal.
+
+Errors occurring in the route are displayed in red.
+
+== Examples
+
+=== Chat with an LLM
+
+[source,java]
+----
+from("shell:myapp?color=green")
+ .to("huggingface:chat?modelId=Qwen/Qwen2.5-3B-Instruct");
+----
+
+=== Call a REST API
+
+[source,java]
+----
+from("shell:myapp")
+ .toD("http://api.example.com/chat?query=${body}");
+----
+
+=== Route to JMS (fire-and-forget)
+
+[source,java]
+----
+from("shell:myapp")
+ .setProperty("input", body())
+ .to(ExchangePattern.InOnly, "activemq:queue:myqueue")
+ .setBody(simple("Sent '${exchangeProperty.input}' to queue"));
+----
+
diff --git
a/components/camel-shell/src/main/java/org/apache/camel/component/shell/ShellComponent.java
b/components/camel-shell/src/main/java/org/apache/camel/component/shell/ShellComponent.java
new file mode 100644
index 000000000000..0f6919553d92
--- /dev/null
+++
b/components/camel-shell/src/main/java/org/apache/camel/component/shell/ShellComponent.java
@@ -0,0 +1,157 @@
+/*
+ * 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.component.shell;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import org.apache.camel.Endpoint;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.annotations.Component;
+import org.apache.camel.support.DefaultComponent;
+import org.jline.reader.Highlighter;
+import org.jline.reader.LineReader;
+import org.jline.reader.LineReaderBuilder;
+import org.jline.terminal.Terminal;
+import org.jline.terminal.TerminalBuilder;
+import org.jline.utils.AttributedString;
+import org.jline.utils.AttributedStringBuilder;
+import org.jline.utils.AttributedStyle;
+import org.jline.utils.InfoCmp;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component("shell")
+public class ShellComponent extends DefaultComponent {
+
+ private static final Logger LOG =
LoggerFactory.getLogger(ShellComponent.class);
+
+ @Metadata(label = "advanced", defaultValue = "true", description =
"Whether to print the Camel banner on startup")
+ private boolean showBanner = true;
+
+ @Metadata(label = "advanced", defaultValue = "camel-shell-banner.txt",
+ description = "Classpath resource path to a custom banner text
file")
+ private String bannerResource = "camel-shell-banner.txt";
+
+ private Terminal terminal;
+ private LineReader lineReader;
+
+ @Override
+ protected void doStart() throws Exception {
+ super.doStart();
+ try {
+ terminal = TerminalBuilder.builder().system(true).build();
+ terminal.puts(InfoCmp.Capability.clear_screen);
+ terminal.flush();
+ if (showBanner) {
+ String banner = loadBanner();
+ if (banner != null) {
+ String colored = new AttributedStringBuilder()
+
.style(AttributedStyle.DEFAULT.foreground(AttributedStyle.YELLOW).bold())
+ .append(banner)
+ .style(AttributedStyle.DEFAULT)
+ .toAnsi(terminal);
+ terminal.writer().println(colored);
+ terminal.writer().flush();
+ }
+ }
+ lineReader = LineReaderBuilder.builder()
+ .terminal(terminal)
+ .highlighter(new Highlighter() {
+ @Override
+ public AttributedString highlight(LineReader reader,
String buffer) {
+ return new AttributedStringBuilder()
+ .style(AttributedStyle.BOLD)
+ .append(buffer)
+ .toAttributedString();
+ }
+
+ @Override
+ public void setErrorPattern(Pattern errorPattern) {
+ }
+
+ @Override
+ public void setErrorIndex(int errorIndex) {
+ }
+ })
+ .build();
+ } catch (IOException e) {
+ LOG.error("Failed to create JLine terminal.", e);
+ throw e;
+ }
+ }
+
+ @Override
+ protected void doStop() throws Exception {
+ super.doStop();
+ if (terminal != null) {
+ try {
+ terminal.close();
+ } catch (IOException e) {
+ LOG.warn("Error closing JLine terminal", e);
+ }
+ }
+ }
+
+ @Override
+ protected Endpoint createEndpoint(String uri, String remaining,
Map<String, Object> parameters) throws Exception {
+ ShellEndpoint endpoint = new ShellEndpoint(uri, this);
+ endpoint.setPrompt(remaining);
+ setProperties(endpoint, parameters);
+ return endpoint;
+ }
+
+ private String loadBanner() {
+ try (InputStream is =
getClass().getClassLoader().getResourceAsStream(bannerResource)) {
+ if (is == null) {
+ LOG.warn("Banner resource not found: {}", bannerResource);
+ return null;
+ }
+ return new String(is.readAllBytes(), StandardCharsets.UTF_8);
+ } catch (IOException e) {
+ LOG.warn("Failed to load banner resource: {}", bannerResource, e);
+ return null;
+ }
+ }
+
+ public boolean isShowBanner() {
+ return showBanner;
+ }
+
+ public void setShowBanner(boolean showBanner) {
+ this.showBanner = showBanner;
+ }
+
+ public String getBannerResource() {
+ return bannerResource;
+ }
+
+ public void setBannerResource(String bannerResource) {
+ this.bannerResource = bannerResource;
+ }
+
+ public Terminal getTerminal() {
+ return terminal;
+ }
+
+ public LineReader getLineReader() {
+ return lineReader;
+ }
+}
diff --git
a/components/camel-shell/src/main/java/org/apache/camel/component/shell/ShellConsumer.java
b/components/camel-shell/src/main/java/org/apache/camel/component/shell/ShellConsumer.java
new file mode 100644
index 000000000000..29414dd79d82
--- /dev/null
+++
b/components/camel-shell/src/main/java/org/apache/camel/component/shell/ShellConsumer.java
@@ -0,0 +1,147 @@
+/*
+ * 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.component.shell;
+
+import java.util.concurrent.ExecutorService;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.support.DefaultConsumer;
+import org.jline.reader.LineReader;
+import org.jline.terminal.Terminal;
+import org.jline.utils.AttributedStringBuilder;
+import org.jline.utils.AttributedStyle;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ShellConsumer extends DefaultConsumer {
+
+ private static final Logger LOG =
LoggerFactory.getLogger(ShellConsumer.class);
+
+ private ExecutorService executorService;
+
+ public ShellConsumer(ShellEndpoint endpoint, Processor processor) {
+ super(endpoint, processor);
+ }
+
+ @Override
+ public ShellEndpoint getEndpoint() {
+ return (ShellEndpoint) super.getEndpoint();
+ }
+
+ @Override
+ protected void doStart() throws Exception {
+ super.doStart();
+ executorService
+ =
getEndpoint().getCamelContext().getExecutorServiceManager().newSingleThreadExecutor(this,
"ShellConsumer");
+ executorService.submit(this::run);
+ }
+
+ @Override
+ protected void doStop() throws Exception {
+ super.doStop();
+ if (executorService != null) {
+
getEndpoint().getCamelContext().getExecutorServiceManager().shutdown(executorService);
+ }
+ }
+
+ private void run() {
+ try {
+ LineReader lineReader = getEndpoint().getLineReader();
+ Terminal terminal = getEndpoint().getTerminal();
+ int color = resolveColor(getEndpoint().getColor());
+
+ while (isRunAllowed()) {
+ String promptText = (getEndpoint().getPrompt() == null ? "" :
getEndpoint().getPrompt()) + "> ";
+ String coloredPrompt = new AttributedStringBuilder()
+
.style(AttributedStyle.DEFAULT.foreground(color).bold())
+ .append(promptText)
+ .style(AttributedStyle.DEFAULT)
+ .toAnsi(terminal);
+
+ String line;
+ try {
+ line = lineReader.readLine(coloredPrompt);
+ } catch (Exception e) {
+ LOG.error("Error reading line from shell", e);
+ break;
+ }
+
+ if (line == null) {
+ LOG.info("Shell consumer received EOF (null line), exiting
loop.");
+ break;
+ }
+
+ if ("exit".equalsIgnoreCase(line.trim())) {
+ LOG.info("Shell consumer received exit command, exiting
loop.");
+ break;
+ }
+
+ Exchange exchange = getEndpoint().createExchange();
+ exchange.getIn().setBody(line);
+ try {
+ getProcessor().process(exchange);
+ Exception routeException = exchange.getException();
+ if (routeException != null) {
+ printError(terminal, "[ERROR] " +
routeException.getMessage());
+ } else {
+ String output =
exchange.getMessage().getBody(String.class);
+ if (output != null) {
+ terminal.writer().println(output);
+ }
+ }
+ terminal.writer().flush();
+ } catch (Exception e) {
+ getExceptionHandler().handleException(e);
+ } finally {
+ releaseExchange(exchange, false);
+ }
+ }
+ } catch (Exception e) {
+ getExceptionHandler().handleException(e);
+ } finally {
+ LOG.info("Shell consumer loop finished.");
+ getEndpoint().getCamelContext().stop();
+ }
+ }
+
+ private static void printError(Terminal terminal, String message) {
+ String errorLine = new AttributedStringBuilder()
+
.style(AttributedStyle.DEFAULT.foreground(AttributedStyle.RED).bold())
+ .append(message)
+ .style(AttributedStyle.DEFAULT)
+ .toAnsi(terminal);
+ terminal.writer().println(errorLine);
+ terminal.writer().flush();
+ }
+
+ static int resolveColor(String name) {
+ if (name == null) {
+ return AttributedStyle.CYAN;
+ }
+ return switch (name.toLowerCase()) {
+ case "black" -> AttributedStyle.BLACK;
+ case "red" -> AttributedStyle.RED;
+ case "green" -> AttributedStyle.GREEN;
+ case "yellow" -> AttributedStyle.YELLOW;
+ case "blue" -> AttributedStyle.BLUE;
+ case "magenta" -> AttributedStyle.MAGENTA;
+ case "white" -> AttributedStyle.WHITE;
+ default -> AttributedStyle.CYAN;
+ };
+ }
+}
diff --git
a/components/camel-shell/src/main/java/org/apache/camel/component/shell/ShellEndpoint.java
b/components/camel-shell/src/main/java/org/apache/camel/component/shell/ShellEndpoint.java
new file mode 100644
index 000000000000..9748a36be6ad
--- /dev/null
+++
b/components/camel-shell/src/main/java/org/apache/camel/component/shell/ShellEndpoint.java
@@ -0,0 +1,87 @@
+/*
+ * 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.component.shell;
+
+import org.apache.camel.Category;
+import org.apache.camel.Consumer;
+import org.apache.camel.Processor;
+import org.apache.camel.Producer;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.UriEndpoint;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.spi.UriPath;
+import org.apache.camel.support.DefaultEndpoint;
+import org.jline.reader.LineReader;
+import org.jline.terminal.Terminal;
+
+@UriEndpoint(firstVersion = "4.21.0", category = { Category.API }, scheme =
"shell", title = "Shell",
+ syntax = "shell:prompt", consumerOnly = true, remote = false)
+public class ShellEndpoint extends DefaultEndpoint {
+
+ @UriPath
+ @Metadata(required = true, description = "Shell prompt")
+ private String prompt;
+
+ @UriParam(label = "consumer", defaultValue = "cyan",
+ description = "Prompt color: black, red, green, yellow, blue,
magenta, cyan, white")
+ private String color = "cyan";
+
+ public ShellEndpoint(String uri, ShellComponent component) {
+ super(uri, component);
+ }
+
+ @Override
+ public ShellComponent getComponent() {
+ return (ShellComponent) super.getComponent();
+ }
+
+ @Override
+ public Producer createProducer() throws Exception {
+ throw new UnsupportedOperationException("The shell component does not
support a producer.");
+ }
+
+ @Override
+ public Consumer createConsumer(Processor processor) throws Exception {
+ ShellConsumer consumer = new ShellConsumer(this, processor);
+ configureConsumer(consumer);
+ return consumer;
+ }
+
+ public String getPrompt() {
+ return prompt;
+ }
+
+ public void setPrompt(String prompt) {
+ this.prompt = prompt;
+ }
+
+ public String getColor() {
+ return color;
+ }
+
+ public void setColor(String color) {
+ this.color = color;
+ }
+
+ public Terminal getTerminal() {
+ return getComponent().getTerminal();
+ }
+
+ public LineReader getLineReader() {
+ return getComponent().getLineReader();
+ }
+}
diff --git a/components/camel-shell/src/main/resources/camel-shell-banner.txt
b/components/camel-shell/src/main/resources/camel-shell-banner.txt
new file mode 100644
index 000000000000..11db5a058306
--- /dev/null
+++ b/components/camel-shell/src/main/resources/camel-shell-banner.txt
@@ -0,0 +1,6 @@
+ ____ __
+ / ___|__ _ _ __ ___ ___| |
+ / / / _` | '_ ` _ \ / _ \ |
+/ /___| (_| | | | | | | __/ |
+\____|\ __,_|_| |_| |_|\___|_|
+ Apache Camel Shell
diff --git
a/components/camel-shell/src/test/java/org/apache/camel/component/shell/ShellComponentTest.java
b/components/camel-shell/src/test/java/org/apache/camel/component/shell/ShellComponentTest.java
new file mode 100644
index 000000000000..92cb1bd8afc1
--- /dev/null
+++
b/components/camel-shell/src/test/java/org/apache/camel/component/shell/ShellComponentTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.component.shell;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class ShellComponentTest {
+
+ private CamelContext context;
+
+ @BeforeEach
+ void setUp() {
+ context = new DefaultCamelContext();
+ }
+
+ @AfterEach
+ void tearDown() throws Exception {
+ context.stop();
+ }
+
+ @Test
+ void testComponentIsRegistered() {
+ ShellComponent component = context.getComponent("shell",
ShellComponent.class);
+ assertNotNull(component);
+ }
+
+ @Test
+ void testComponentDefaultBannerEnabled() {
+ ShellComponent component = context.getComponent("shell",
ShellComponent.class);
+ assertTrue(component.isShowBanner());
+ }
+
+ @Test
+ void testComponentDefaultBannerResource() {
+ ShellComponent component = context.getComponent("shell",
ShellComponent.class);
+ assertEquals("camel-shell-banner.txt", component.getBannerResource());
+ }
+
+ @Test
+ void testEndpointCreatedWithCorrectScheme() throws Exception {
+ ShellComponent component = context.getComponent("shell",
ShellComponent.class);
+ ShellEndpoint endpoint = (ShellEndpoint)
component.createEndpoint("shell:myapp", "myapp", new java.util.HashMap<>());
+ assertNotNull(endpoint);
+ assertEquals("myapp", endpoint.getPrompt());
+ }
+}
diff --git
a/components/camel-shell/src/test/java/org/apache/camel/component/shell/ShellConsumerColorTest.java
b/components/camel-shell/src/test/java/org/apache/camel/component/shell/ShellConsumerColorTest.java
new file mode 100644
index 000000000000..84e6319db936
--- /dev/null
+++
b/components/camel-shell/src/test/java/org/apache/camel/component/shell/ShellConsumerColorTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.component.shell;
+
+import org.jline.utils.AttributedStyle;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ShellConsumerColorTest {
+
+ @Test
+ void testResolveColorNull() {
+ assertEquals(AttributedStyle.CYAN, ShellConsumer.resolveColor(null));
+ }
+
+ @Test
+ void testResolveColorUnknown() {
+ assertEquals(AttributedStyle.CYAN,
ShellConsumer.resolveColor("purple"));
+ }
+
+ @Test
+ void testResolveColorBlack() {
+ assertEquals(AttributedStyle.BLACK,
ShellConsumer.resolveColor("black"));
+ }
+
+ @Test
+ void testResolveColorRed() {
+ assertEquals(AttributedStyle.RED, ShellConsumer.resolveColor("red"));
+ }
+
+ @Test
+ void testResolveColorGreen() {
+ assertEquals(AttributedStyle.GREEN,
ShellConsumer.resolveColor("green"));
+ }
+
+ @Test
+ void testResolveColorYellow() {
+ assertEquals(AttributedStyle.YELLOW,
ShellConsumer.resolveColor("yellow"));
+ }
+
+ @Test
+ void testResolveColorBlue() {
+ assertEquals(AttributedStyle.BLUE, ShellConsumer.resolveColor("blue"));
+ }
+
+ @Test
+ void testResolveColorMagenta() {
+ assertEquals(AttributedStyle.MAGENTA,
ShellConsumer.resolveColor("magenta"));
+ }
+
+ @Test
+ void testResolveColorCyan() {
+ assertEquals(AttributedStyle.CYAN, ShellConsumer.resolveColor("cyan"));
+ }
+
+ @Test
+ void testResolveColorWhite() {
+ assertEquals(AttributedStyle.WHITE,
ShellConsumer.resolveColor("white"));
+ }
+
+ @Test
+ void testResolveColorCaseInsensitive() {
+ assertEquals(AttributedStyle.GREEN,
ShellConsumer.resolveColor("GREEN"));
+ assertEquals(AttributedStyle.RED, ShellConsumer.resolveColor("Red"));
+ assertEquals(AttributedStyle.BLUE, ShellConsumer.resolveColor("BLUE"));
+ }
+}
diff --git
a/components/camel-shell/src/test/java/org/apache/camel/component/shell/ShellEndpointTest.java
b/components/camel-shell/src/test/java/org/apache/camel/component/shell/ShellEndpointTest.java
new file mode 100644
index 000000000000..56c759e32936
--- /dev/null
+++
b/components/camel-shell/src/test/java/org/apache/camel/component/shell/ShellEndpointTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.component.shell;
+
+import java.util.HashMap;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class ShellEndpointTest {
+
+ private CamelContext context;
+ private ShellComponent component;
+
+ @BeforeEach
+ void setUp() {
+ context = new DefaultCamelContext();
+ component = context.getComponent("shell", ShellComponent.class);
+ }
+
+ @AfterEach
+ void tearDown() throws Exception {
+ context.stop();
+ }
+
+ @Test
+ void testPromptSetFromUri() throws Exception {
+ ShellEndpoint endpoint = (ShellEndpoint)
component.createEndpoint("shell:myapp", "myapp", new HashMap<>());
+ assertEquals("myapp", endpoint.getPrompt());
+ }
+
+ @Test
+ void testDefaultColor() throws Exception {
+ ShellEndpoint endpoint = (ShellEndpoint)
component.createEndpoint("shell:camel", "camel", new HashMap<>());
+ assertEquals("cyan", endpoint.getColor());
+ }
+
+ @Test
+ void testColorCanBeOverridden() throws Exception {
+ HashMap<String, Object> params = new HashMap<>();
+ params.put("color", "green");
+ ShellEndpoint endpoint = (ShellEndpoint)
component.createEndpoint("shell:camel?color=green", "camel", params);
+ assertEquals("green", endpoint.getColor());
+ }
+
+ @Test
+ void testCreateProducerThrowsUnsupportedOperation() throws Exception {
+ ShellEndpoint endpoint = (ShellEndpoint)
component.createEndpoint("shell:camel", "camel", new HashMap<>());
+ assertThrows(UnsupportedOperationException.class,
endpoint::createProducer);
+ }
+
+ @Test
+ void testEndpointIsNotNull() throws Exception {
+ ShellEndpoint endpoint = (ShellEndpoint)
component.createEndpoint("shell:camel", "camel", new HashMap<>());
+ assertNotNull(endpoint);
+ }
+}
diff --git a/components/pom.xml b/components/pom.xml
index 2df71eed5d5f..4b400f28858b 100644
--- a/components/pom.xml
+++ b/components/pom.xml
@@ -291,6 +291,7 @@
<module>camel-schematron</module>
<module>camel-servicenow</module>
<module>camel-servlet</module>
+ <module>camel-shell</module>
<module>camel-shiro</module>
<module>camel-sjms2</module>
<module>camel-sjms</module>
diff --git
a/core/camel-main/src/generated/resources/org/apache/camel/main/components.properties
b/core/camel-main/src/generated/resources/org/apache/camel/main/components.properties
index 624daab24279..047a990058d6 100644
---
a/core/camel-main/src/generated/resources/org/apache/camel/main/components.properties
+++
b/core/camel-main/src/generated/resources/org/apache/camel/main/components.properties
@@ -323,6 +323,7 @@ seda
servicenow
servlet
sftp
+shell
sjms
sjms2
slack
diff --git a/docs/components/modules/ROOT/examples/json/shell.json
b/docs/components/modules/ROOT/examples/json/shell.json
new file mode 120000
index 000000000000..327adb2eece2
--- /dev/null
+++ b/docs/components/modules/ROOT/examples/json/shell.json
@@ -0,0 +1 @@
+../../../../../../components/camel-shell/src/generated/resources/META-INF/org/apache/camel/component/shell/shell.json
\ No newline at end of file
diff --git a/docs/components/modules/ROOT/nav.adoc
b/docs/components/modules/ROOT/nav.adoc
index 45f5676428bd..12007157bd32 100644
--- a/docs/components/modules/ROOT/nav.adoc
+++ b/docs/components/modules/ROOT/nav.adoc
@@ -340,6 +340,7 @@
** xref:servicenow-component.adoc[ServiceNow]
** xref:servlet-component.adoc[Servlet]
** xref:sftp-component.adoc[SFTP]
+** xref:shell-component.adoc[Shell]
** xref:sjms-component.adoc[Simple JMS]
** xref:sjms2-component.adoc[Simple JMS2]
** xref:slack-component.adoc[Slack]
diff --git a/docs/components/modules/ROOT/pages/shell-component.adoc
b/docs/components/modules/ROOT/pages/shell-component.adoc
new file mode 120000
index 000000000000..307e1f8e387b
--- /dev/null
+++ b/docs/components/modules/ROOT/pages/shell-component.adoc
@@ -0,0 +1 @@
+../../../../../components/camel-shell/src/main/docs/shell-component.adoc
\ No newline at end of file
diff --git
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java
index 44790c7c3af9..c215f22f0c1a 100644
---
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java
+++
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java
@@ -4366,6 +4366,19 @@ public interface ComponentsBuilderFactory {
static SftpComponentBuilderFactory.SftpComponentBuilder sftp() {
return SftpComponentBuilderFactory.sftp();
}
+ /**
+ * Shell (camel-shell)
+ * Camel Shell component
+ *
+ * Category: api
+ * Since: 4.21
+ * Maven coordinates: org.apache.camel:camel-shell
+ *
+ * @return the dsl builder
+ */
+ static ShellComponentBuilderFactory.ShellComponentBuilder shell() {
+ return ShellComponentBuilderFactory.shell();
+ }
/**
* Simple JMS (camel-sjms)
* Send and receive messages to/from a JMS Queue or Topic using plain JMS
diff --git
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/ShellComponentBuilderFactory.java
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/ShellComponentBuilderFactory.java
new file mode 100644
index 000000000000..d45442c72ba3
--- /dev/null
+++
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/ShellComponentBuilderFactory.java
@@ -0,0 +1,159 @@
+/* Generated by camel build tools - do NOT edit this file! */
+/*
+ * 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.component.dsl;
+
+import javax.annotation.processing.Generated;
+import org.apache.camel.Component;
+import org.apache.camel.builder.component.AbstractComponentBuilder;
+import org.apache.camel.builder.component.ComponentBuilder;
+import org.apache.camel.component.shell.ShellComponent;
+
+/**
+ * Camel Shell component
+ *
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.ComponentDslMojo")
+public interface ShellComponentBuilderFactory {
+
+ /**
+ * Shell (camel-shell)
+ * Camel Shell component
+ *
+ * Category: api
+ * Since: 4.21
+ * Maven coordinates: org.apache.camel:camel-shell
+ *
+ * @return the dsl builder
+ */
+ static ShellComponentBuilder shell() {
+ return new ShellComponentBuilderImpl();
+ }
+
+ /**
+ * Builder for the Shell component.
+ */
+ interface ShellComponentBuilder extends ComponentBuilder<ShellComponent> {
+
+
+ /**
+ * Allows for bridging the consumer to the Camel routing Error Handler,
+ * which mean any exceptions (if possible) occurred while the Camel
+ * consumer is trying to pickup incoming messages, or the likes, will
+ * now be processed as a message and handled by the routing Error
+ * Handler. Important: This is only possible if the 3rd party component
+ * allows Camel to be alerted if an exception was thrown. Some
+ * components handle this internally only, and therefore
+ * bridgeErrorHandler is not possible. In other situations we may
+ * improve the Camel component to hook into the 3rd party component and
+ * make this possible for future releases. By default the consumer will
+ * use the org.apache.camel.spi.ExceptionHandler to deal with
+ * exceptions, that will be logged at WARN or ERROR level and ignored.
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: consumer
+ *
+ * @param bridgeErrorHandler the value to set
+ * @return the dsl builder
+ */
+ default ShellComponentBuilder bridgeErrorHandler(boolean
bridgeErrorHandler) {
+ doSetProperty("bridgeErrorHandler", bridgeErrorHandler);
+ return this;
+ }
+
+
+ /**
+ * Whether autowiring is enabled. This is used for automatic autowiring
+ * options (the option must be marked as autowired) by looking up in
the
+ * registry to find if there is a single instance of matching type,
+ * which then gets configured on the component. This can be used for
+ * automatic configuring JDBC data sources, JMS connection factories,
+ * AWS Clients, etc.
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: true
+ * Group: advanced
+ *
+ * @param autowiredEnabled the value to set
+ * @return the dsl builder
+ */
+ default ShellComponentBuilder autowiredEnabled(boolean
autowiredEnabled) {
+ doSetProperty("autowiredEnabled", autowiredEnabled);
+ return this;
+ }
+
+
+ /**
+ * Classpath resource path to a custom banner text file.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Default: camel-shell-banner.txt
+ * Group: advanced
+ *
+ * @param bannerResource the value to set
+ * @return the dsl builder
+ */
+ default ShellComponentBuilder bannerResource(java.lang.String
bannerResource) {
+ doSetProperty("bannerResource", bannerResource);
+ return this;
+ }
+
+
+ /**
+ * Whether to print the Camel banner on startup.
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: true
+ * Group: advanced
+ *
+ * @param showBanner the value to set
+ * @return the dsl builder
+ */
+ default ShellComponentBuilder showBanner(boolean showBanner) {
+ doSetProperty("showBanner", showBanner);
+ return this;
+ }
+ }
+
+ class ShellComponentBuilderImpl
+ extends AbstractComponentBuilder<ShellComponent>
+ implements ShellComponentBuilder {
+ @Override
+ protected ShellComponent buildConcreteComponent() {
+ return new ShellComponent();
+ }
+ @Override
+ protected boolean setPropertyOnComponent(
+ Component component,
+ String name,
+ Object value) {
+ switch (name) {
+ case "bridgeErrorHandler": ((ShellComponent)
component).setBridgeErrorHandler((boolean) value); return true;
+ case "autowiredEnabled": ((ShellComponent)
component).setAutowiredEnabled((boolean) value); return true;
+ case "bannerResource": ((ShellComponent)
component).setBannerResource((java.lang.String) value); return true;
+ case "showBanner": ((ShellComponent)
component).setShowBanner((boolean) value); return true;
+ default: return false;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java
index b397888b4d9a..6b6e938c05d5 100644
---
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java
+++
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java
@@ -332,6 +332,7 @@ public interface EndpointBuilderFactory
org.apache.camel.builder.endpoint.dsl.ServletEndpointBuilderFactory.ServletBuilders,
org.apache.camel.builder.endpoint.dsl.Ses2EndpointBuilderFactory.Ses2Builders,
org.apache.camel.builder.endpoint.dsl.SftpEndpointBuilderFactory.SftpBuilders,
+
org.apache.camel.builder.endpoint.dsl.ShellEndpointBuilderFactory.ShellBuilders,
org.apache.camel.builder.endpoint.dsl.SimpleNotificationEndpointBuilderFactory.SimpleNotificationBuilders,
org.apache.camel.builder.endpoint.dsl.Sjms2EndpointBuilderFactory.Sjms2Builders,
org.apache.camel.builder.endpoint.dsl.SjmsEndpointBuilderFactory.SjmsBuilders,
diff --git
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilders.java
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilders.java
index 91b90651cb8a..5e55289671b3 100644
---
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilders.java
+++
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilders.java
@@ -329,6 +329,7 @@ public interface EndpointBuilders
org.apache.camel.builder.endpoint.dsl.ServletEndpointBuilderFactory,
org.apache.camel.builder.endpoint.dsl.Ses2EndpointBuilderFactory,
org.apache.camel.builder.endpoint.dsl.SftpEndpointBuilderFactory,
+ org.apache.camel.builder.endpoint.dsl.ShellEndpointBuilderFactory,
org.apache.camel.builder.endpoint.dsl.SimpleNotificationEndpointBuilderFactory,
org.apache.camel.builder.endpoint.dsl.Sjms2EndpointBuilderFactory,
org.apache.camel.builder.endpoint.dsl.SjmsEndpointBuilderFactory,
diff --git
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
index 2a61a14eac6f..2c47227b5c22 100644
---
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
+++
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
@@ -14614,6 +14614,46 @@ public class StaticEndpointBuilders {
public static SftpEndpointBuilderFactory.SftpEndpointBuilder sftp(String
componentName, String path) {
return SftpEndpointBuilderFactory.endpointBuilder(componentName, path);
}
+ /**
+ * Shell (camel-shell)
+ * Camel Shell component
+ *
+ * Category: api
+ * Since: 4.21
+ * Maven coordinates: org.apache.camel:camel-shell
+ *
+ * Syntax: <code>shell:prompt</code>
+ *
+ * Path parameter: prompt (required)
+ * Shell prompt
+ *
+ * @param path prompt
+ * @return the dsl builder
+ */
+ public static ShellEndpointBuilderFactory.ShellEndpointBuilder
shell(String path) {
+ return shell("shell", path);
+ }
+ /**
+ * Shell (camel-shell)
+ * Camel Shell component
+ *
+ * Category: api
+ * Since: 4.21
+ * Maven coordinates: org.apache.camel:camel-shell
+ *
+ * Syntax: <code>shell:prompt</code>
+ *
+ * Path parameter: prompt (required)
+ * Shell prompt
+ *
+ * @param componentName to use a custom component name for the endpoint
+ * instead of the default name
+ * @param path prompt
+ * @return the dsl builder
+ */
+ public static ShellEndpointBuilderFactory.ShellEndpointBuilder
shell(String componentName, String path) {
+ return ShellEndpointBuilderFactory.endpointBuilder(componentName,
path);
+ }
/**
* Simple JMS (camel-sjms)
* Send and receive messages to/from a JMS Queue or Topic using plain JMS
diff --git
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/ShellEndpointBuilderFactory.java
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/ShellEndpointBuilderFactory.java
new file mode 100644
index 000000000000..e299aca0e928
--- /dev/null
+++
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/ShellEndpointBuilderFactory.java
@@ -0,0 +1,244 @@
+/* Generated by camel build tools - do NOT edit this file! */
+/*
+ * 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.endpoint.dsl;
+
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.function.*;
+import java.util.stream.*;
+import javax.annotation.processing.Generated;
+import org.apache.camel.builder.EndpointConsumerBuilder;
+import org.apache.camel.builder.EndpointProducerBuilder;
+import org.apache.camel.builder.endpoint.AbstractEndpointBuilder;
+
+/**
+ * Camel Shell component
+ *
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.EndpointDslMojo")
+public interface ShellEndpointBuilderFactory {
+
+ /**
+ * Builder for endpoint for the Shell component.
+ */
+ public interface ShellEndpointBuilder
+ extends
+ EndpointConsumerBuilder {
+ default AdvancedShellEndpointBuilder advanced() {
+ return (AdvancedShellEndpointBuilder) this;
+ }
+
+ /**
+ * Prompt color: black, red, green, yellow, blue, magenta, cyan, white.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Default: cyan
+ * Group: consumer
+ *
+ * @param color the value to set
+ * @return the dsl builder
+ */
+ default ShellEndpointBuilder color(String color) {
+ doSetProperty("color", color);
+ return this;
+ }
+ }
+
+ /**
+ * Advanced builder for endpoint for the Shell component.
+ */
+ public interface AdvancedShellEndpointBuilder
+ extends
+ EndpointConsumerBuilder {
+ default ShellEndpointBuilder basic() {
+ return (ShellEndpointBuilder) this;
+ }
+
+ /**
+ * Allows for bridging the consumer to the Camel routing Error Handler,
+ * which mean any exceptions (if possible) occurred while the Camel
+ * consumer is trying to pickup incoming messages, or the likes, will
+ * now be processed as a message and handled by the routing Error
+ * Handler. Important: This is only possible if the 3rd party component
+ * allows Camel to be alerted if an exception was thrown. Some
+ * components handle this internally only, and therefore
+ * bridgeErrorHandler is not possible. In other situations we may
+ * improve the Camel component to hook into the 3rd party component and
+ * make this possible for future releases. By default the consumer will
+ * use the org.apache.camel.spi.ExceptionHandler to deal with
+ * exceptions, that will be logged at WARN or ERROR level and ignored.
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: consumer (advanced)
+ *
+ * @param bridgeErrorHandler the value to set
+ * @return the dsl builder
+ */
+ default AdvancedShellEndpointBuilder bridgeErrorHandler(boolean
bridgeErrorHandler) {
+ doSetProperty("bridgeErrorHandler", bridgeErrorHandler);
+ return this;
+ }
+ /**
+ * Allows for bridging the consumer to the Camel routing Error Handler,
+ * which mean any exceptions (if possible) occurred while the Camel
+ * consumer is trying to pickup incoming messages, or the likes, will
+ * now be processed as a message and handled by the routing Error
+ * Handler. Important: This is only possible if the 3rd party component
+ * allows Camel to be alerted if an exception was thrown. Some
+ * components handle this internally only, and therefore
+ * bridgeErrorHandler is not possible. In other situations we may
+ * improve the Camel component to hook into the 3rd party component and
+ * make this possible for future releases. By default the consumer will
+ * use the org.apache.camel.spi.ExceptionHandler to deal with
+ * exceptions, that will be logged at WARN or ERROR level and ignored.
+ *
+ * The option will be converted to a <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: consumer (advanced)
+ *
+ * @param bridgeErrorHandler the value to set
+ * @return the dsl builder
+ */
+ default AdvancedShellEndpointBuilder bridgeErrorHandler(String
bridgeErrorHandler) {
+ doSetProperty("bridgeErrorHandler", bridgeErrorHandler);
+ return this;
+ }
+ /**
+ * To let the consumer use a custom ExceptionHandler. Notice if the
+ * option bridgeErrorHandler is enabled then this option is not in use.
+ * By default the consumer will deal with exceptions, that will be
+ * logged at WARN or ERROR level and ignored.
+ *
+ * The option is a: <code>org.apache.camel.spi.ExceptionHandler</code>
+ * type.
+ *
+ * Group: consumer (advanced)
+ *
+ * @param exceptionHandler the value to set
+ * @return the dsl builder
+ */
+ default AdvancedShellEndpointBuilder
exceptionHandler(org.apache.camel.spi.ExceptionHandler exceptionHandler) {
+ doSetProperty("exceptionHandler", exceptionHandler);
+ return this;
+ }
+ /**
+ * To let the consumer use a custom ExceptionHandler. Notice if the
+ * option bridgeErrorHandler is enabled then this option is not in use.
+ * By default the consumer will deal with exceptions, that will be
+ * logged at WARN or ERROR level and ignored.
+ *
+ * The option will be converted to a
+ * <code>org.apache.camel.spi.ExceptionHandler</code> type.
+ *
+ * Group: consumer (advanced)
+ *
+ * @param exceptionHandler the value to set
+ * @return the dsl builder
+ */
+ default AdvancedShellEndpointBuilder exceptionHandler(String
exceptionHandler) {
+ doSetProperty("exceptionHandler", exceptionHandler);
+ return this;
+ }
+ /**
+ * Sets the exchange pattern when the consumer creates an exchange.
+ *
+ * The option is a: <code>org.apache.camel.ExchangePattern</code> type.
+ *
+ * Group: consumer (advanced)
+ *
+ * @param exchangePattern the value to set
+ * @return the dsl builder
+ */
+ default AdvancedShellEndpointBuilder
exchangePattern(org.apache.camel.ExchangePattern exchangePattern) {
+ doSetProperty("exchangePattern", exchangePattern);
+ return this;
+ }
+ /**
+ * Sets the exchange pattern when the consumer creates an exchange.
+ *
+ * The option will be converted to a
+ * <code>org.apache.camel.ExchangePattern</code> type.
+ *
+ * Group: consumer (advanced)
+ *
+ * @param exchangePattern the value to set
+ * @return the dsl builder
+ */
+ default AdvancedShellEndpointBuilder exchangePattern(String
exchangePattern) {
+ doSetProperty("exchangePattern", exchangePattern);
+ return this;
+ }
+ }
+
+ public interface ShellBuilders {
+ /**
+ * Shell (camel-shell)
+ * Camel Shell component
+ *
+ * Category: api
+ * Since: 4.21
+ * Maven coordinates: org.apache.camel:camel-shell
+ *
+ * Syntax: <code>shell:prompt</code>
+ *
+ * Path parameter: prompt (required)
+ * Shell prompt
+ *
+ * @param path prompt
+ * @return the dsl builder
+ */
+ default ShellEndpointBuilder shell(String path) {
+ return ShellEndpointBuilderFactory.endpointBuilder("shell", path);
+ }
+ /**
+ * Shell (camel-shell)
+ * Camel Shell component
+ *
+ * Category: api
+ * Since: 4.21
+ * Maven coordinates: org.apache.camel:camel-shell
+ *
+ * Syntax: <code>shell:prompt</code>
+ *
+ * Path parameter: prompt (required)
+ * Shell prompt
+ *
+ * @param componentName to use a custom component name for the endpoint
+ * instead of the default name
+ * @param path prompt
+ * @return the dsl builder
+ */
+ default ShellEndpointBuilder shell(String componentName, String path) {
+ return ShellEndpointBuilderFactory.endpointBuilder(componentName,
path);
+ }
+
+ }
+ static ShellEndpointBuilder endpointBuilder(String componentName, String
path) {
+ class ShellEndpointBuilderImpl extends AbstractEndpointBuilder
implements ShellEndpointBuilder, AdvancedShellEndpointBuilder {
+ public ShellEndpointBuilderImpl(String path) {
+ super(componentName, path);
+ }
+ }
+ return new ShellEndpointBuilderImpl(path);
+ }
+}
\ No newline at end of file
diff --git
a/dsl/camel-kamelet-main/src/generated/resources/camel-component-known-dependencies.properties
b/dsl/camel-kamelet-main/src/generated/resources/camel-component-known-dependencies.properties
index 3ceba251d89b..dbd333f1cc22 100644
---
a/dsl/camel-kamelet-main/src/generated/resources/camel-component-known-dependencies.properties
+++
b/dsl/camel-kamelet-main/src/generated/resources/camel-component-known-dependencies.properties
@@ -332,6 +332,7 @@ org.apache.camel.component.scp.ScpComponent=camel:jsch
org.apache.camel.component.seda.SedaComponent=camel:seda
org.apache.camel.component.servicenow.ServiceNowComponent=camel:servicenow
org.apache.camel.component.servlet.ServletComponent=camel:servlet
+org.apache.camel.component.shell.ShellComponent=camel:shell
org.apache.camel.component.sjms.SjmsComponent=camel:sjms
org.apache.camel.component.sjms2.Sjms2Component=camel:sjms2
org.apache.camel.component.slack.SlackComponent=camel:slack
diff --git a/parent/pom.xml b/parent/pom.xml
index 4f2e3b22b67d..53b07261f248 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -2536,6 +2536,11 @@
<artifactId>camel-servlet</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-shell</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-shiro</artifactId>