SSH component example
diff --git a/examples/camel-example-ssh/README.adoc b/examples/camel-example-ssh/README.adoc
new file mode 100644
index 0000000..7ef6173
--- /dev/null
+++ b/examples/camel-example-ssh/README.adoc
@@ -0,0 +1,29 @@
+== Camel SSH Example
+
+This example shows how to use Camel SSH component. The Main application will create an embedded SSH server (you can connect to a real one instead).
+
+=== Run the Camel integration (producer)
+
+You can run a producer by executing:
+
+    mvn camel:run -Dexec.args="producer"
+
+It will create a route that periodically SSH to the server and execute there a command.
+
+=== Run the Camel integration (consumer)
+
+You can run a consumer by executing:
+
+    mvn camel:run -Dexec.args="consumer"
+
+It will create a route that consume from calling a `date` command to an SSH session.
+
+=== Help and contributions
+
+If you hit any problem using Camel or have some feedback, then please
+https://camel.apache.org/support.html[let us know].
+
+We also love contributors, so
+https://camel.apache.org/contributing.html[get involved] :-)
+
+The Camel riders!
diff --git a/examples/camel-example-ssh/pom.xml b/examples/camel-example-ssh/pom.xml
new file mode 100644
index 0000000..9b9a0b6
--- /dev/null
+++ b/examples/camel-example-ssh/pom.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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.example</groupId>
+    <artifactId>examples</artifactId>
+    <version>3.5.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>camel-example-ssh</artifactId>
+  <name>Camel :: Example :: SSH</name>
+  <description>An example that uses Camel SSH component</description>
+  <packaging>jar</packaging>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <category>Beginner</category>
+  </properties>
+
+  <dependencyManagement>
+    <dependencies>
+      <!-- Add Camel BOM -->
+      <dependency>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>camel-bom</artifactId>
+        <version>${camel.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+
+  <dependencies>
+
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-main</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-ssh</artifactId>
+    </dependency>
+
+    <!-- logging -->
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-slf4j-impl</artifactId>
+      <scope>runtime</scope>
+      <version>${log4j2-version}</version>
+    </dependency>
+
+    <!-- testing -->
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-test</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <!-- Allows the example to be run via 'mvn camel:run' -->
+      <plugin>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>camel-maven-plugin</artifactId>
+        <version>${camel.version}</version>
+        <configuration>
+          <logClasspath>true</logClasspath>
+          <mainClass>org.apache.camel.ssh.examples.MainApp</mainClass>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/examples/camel-example-ssh/src/main/java/org/apache/camel/ssh/examples/DatePollerRouteBuilder.java b/examples/camel-example-ssh/src/main/java/org/apache/camel/ssh/examples/DatePollerRouteBuilder.java
new file mode 100644
index 0000000..0de6d2c
--- /dev/null
+++ b/examples/camel-example-ssh/src/main/java/org/apache/camel/ssh/examples/DatePollerRouteBuilder.java
@@ -0,0 +1,32 @@
+package org.apache.camel.ssh.examples;
+
+import org.apache.camel.builder.RouteBuilder;
+
+public class DatePollerRouteBuilder extends RouteBuilder {
+
+    private static final String USER = "test";
+    private static final String PASSWORD = "p455w0rd";
+    private static final String POLL_COMMAND = "date";
+    private static final int POLL_DELAY = 10000;
+
+    String sshHost;
+    int sshPort;
+
+    public DatePollerRouteBuilder(String sshHost, int sshPort) {
+        this.sshHost = sshHost;
+        this.sshPort = sshPort;
+    }
+
+    public void configure() {
+        from(String.format("ssh:%s:%s?username=%s&password=%s&pollCommand=%s&delay=%d",
+                sshHost,
+                sshPort,
+                USER,
+                PASSWORD,
+                POLL_COMMAND,
+                POLL_DELAY))
+                .transform(bodyAs(String.class))
+                .log("${body}");
+    }
+
+}
diff --git a/examples/camel-example-ssh/src/main/java/org/apache/camel/ssh/examples/FileProducerRouteBuilder.java b/examples/camel-example-ssh/src/main/java/org/apache/camel/ssh/examples/FileProducerRouteBuilder.java
new file mode 100644
index 0000000..eb88adb
--- /dev/null
+++ b/examples/camel-example-ssh/src/main/java/org/apache/camel/ssh/examples/FileProducerRouteBuilder.java
@@ -0,0 +1,29 @@
+package org.apache.camel.ssh.examples;
+
+import org.apache.camel.builder.RouteBuilder;
+
+public class FileProducerRouteBuilder extends RouteBuilder {
+
+    private static final String USER = "test";
+    private static final String PASSWORD = "p455w0rd";
+
+    String sshHost;
+    int sshPort;
+
+    public FileProducerRouteBuilder(String sshHost, int sshPort) {
+        this.sshHost = sshHost;
+        this.sshPort = sshPort;
+    }
+
+    public void configure() {
+        from("timer:timer?period=10000")
+                .setBody(constant("sh;ssh/command.sh"))
+                .to(String.format("ssh:%s:%s?username=%s&password=%s",
+                        sshHost,
+                        sshPort,
+                        USER,
+                        PASSWORD))
+                .log("${body}");
+    }
+
+}
diff --git a/examples/camel-example-ssh/src/main/java/org/apache/camel/ssh/examples/MainApp.java b/examples/camel-example-ssh/src/main/java/org/apache/camel/ssh/examples/MainApp.java
new file mode 100644
index 0000000..80d8d6b
--- /dev/null
+++ b/examples/camel-example-ssh/src/main/java/org/apache/camel/ssh/examples/MainApp.java
@@ -0,0 +1,75 @@
+package org.apache.camel.ssh.examples;
+
+import java.nio.file.Paths;
+import java.security.PublicKey;
+
+import org.apache.camel.main.Main;
+import org.apache.camel.test.AvailablePortFinder;
+import org.apache.sshd.server.SshServer;
+import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
+import org.apache.sshd.server.shell.ProcessShellFactory;
+
+public class MainApp {
+
+    public static void main(String... args) throws Exception {
+        String mainArgumentExpected = getArgumentOrShowSyntax(args);
+
+        SshServer sshServer = setupSshServer();
+        sshServer.start();
+
+        Main main = new Main();
+        switch (mainArgumentExpected) {
+            case "consumer":
+                configureDatePollerRoute(main, sshServer);
+                break;
+            case "producer":
+                configureFileProducerRoute(main, sshServer);
+                break;
+            default:
+                throw new IllegalArgumentException("You must provide either consumer or producer argument!");
+        }
+        main.run();
+    }
+
+    private static String getArgumentOrShowSyntax(String[] args) {
+        if (args.length == 0){
+            System.out.println("Please provide either consumer or producer argument to run this application!");
+            System.exit(-1);
+        }
+        return args[0];
+    }
+
+    private static void configureFileProducerRoute(Main main, SshServer sshServer) {
+        main.configure().addRoutesBuilder(new FileProducerRouteBuilder(
+                sshServer.getHost() == null ? "localhost" : sshServer.getHost(), sshServer.getPort())
+        );
+    }
+
+    private static void configureDatePollerRoute(Main main, SshServer sshServer) {
+        main.configure().addRoutesBuilder(new DatePollerRouteBuilder(
+                sshServer.getHost() == null ? "localhost" : sshServer.getHost(), sshServer.getPort())
+        );
+    }
+
+    private static SshServer setupSshServer() {
+        int port = AvailablePortFinder.getNextAvailable();
+        SshServer sshServer = SshServer.setUpDefaultServer();
+        sshServer.setPort(port);
+
+        sshServer.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(Paths.get("target/generatedkey.pem")));
+        sshServer.setCommandFactory(command -> new ProcessShellFactory(command.split(";")).create());
+        sshServer.setPasswordAuthenticator((user, password, session) -> validateUser(user, password));
+        sshServer.setPublickeyAuthenticator((user, publicKey, session) -> validatePublicKey(user, publicKey));
+        return sshServer;
+    }
+
+    private static boolean validatePublicKey(String user, PublicKey publicKey) {
+        return "test".equals(user);
+    }
+
+    private static boolean validateUser(String user, String password) {
+        return "test".equals(user) && "p455w0rd".equals(password);
+    }
+
+}
+
diff --git a/examples/camel-example-ssh/src/main/resources/log4j2.properties b/examples/camel-example-ssh/src/main/resources/log4j2.properties
new file mode 100644
index 0000000..328db35
--- /dev/null
+++ b/examples/camel-example-ssh/src/main/resources/log4j2.properties
@@ -0,0 +1,7 @@
+
+appender.out.type = Console
+appender.out.name = out
+appender.out.layout.type = PatternLayout
+appender.out.layout.pattern = [%30.30t] %-30.30c{1} %-5p %m%n
+rootLogger.level = INFO
+rootLogger.appenderRef.out.ref = out
diff --git a/examples/camel-example-ssh/ssh/command.sh b/examples/camel-example-ssh/ssh/command.sh
new file mode 100644
index 0000000..eaaa1ee
--- /dev/null
+++ b/examples/camel-example-ssh/ssh/command.sh
@@ -0,0 +1,2 @@
+# Append the date and show the whole dates journal
+date >> ssh/journal.dat && cat ssh/journal.dat
diff --git a/examples/camel-example-ssh/ssh/journal.dat b/examples/camel-example-ssh/ssh/journal.dat
new file mode 100644
index 0000000..b5ca294
--- /dev/null
+++ b/examples/camel-example-ssh/ssh/journal.dat
@@ -0,0 +1 @@
+# Used to log activities from FileProducerRouteBuilder routes
diff --git a/examples/pom.xml b/examples/pom.xml
index 17ffbc6..a631f2b 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -98,6 +98,7 @@
         <module>camel-example-fhir</module>
         <module>camel-example-cdi-kubernetes</module>
         <module>camel-example-cdi-metrics</module>
+        <module>camel-example-cdi-minio</module>
         <module>camel-example-cdi-properties</module>
         <module>camel-example-cdi-rest-servlet</module>
         <module>camel-example-cdi-test</module>
@@ -145,6 +146,7 @@
         <module>camel-example-spring-ws</module>
         <module>camel-example-spring-xquery</module>
         <module>camel-example-spring-security</module>
+        <module>camel-example-ssh</module>
         <module>camel-example-swagger-cdi</module>
         <module>camel-example-openapi-cdi</module>
         <module>camel-example-telegram</module>
@@ -154,7 +156,6 @@
         <module>camel-example-widget-gadget-cdi</module>
         <module>camel-example-widget-gadget-java</module>
         <module>camel-example-widget-gadget-xml</module>
-      <module>camel-example-cdi-minio</module>
   </modules>
 
     <properties>