This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch cjmamo-CAMEL-19985
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 621e7043693613d66ff1c8cfb4c281e10411a0ab
Author: cjmamo <[email protected]>
AuthorDate: Thu May 30 17:05:40 2024 +0200

    feat: add Smooks component
    
    Refs: https://github.com/smooks/smooks-camel-cartridge/issues/211
---
 bom/camel-bom/pom.xml                              |   5 +
 catalog/camel-allcomponents/pom.xml                |   5 +
 .../org/apache/camel/catalog/components.properties |   1 +
 components/camel-smooks/pom.xml                    | 103 +++++++
 .../smooks/SmooksComponentConfigurer.java          |  63 ++++
 .../component/smooks/SmooksEndpointConfigurer.java | 165 +++++++++++
 .../component/smooks/SmooksEndpointUriFactory.java |  92 ++++++
 .../smooks/converter/ResultConverterLoader.java    |  73 +++++
 .../smooks/converter/SourceConverterLoader.java    |  62 ++++
 .../org/apache/camel/component/smooks/smooks.json  |  53 ++++
 .../services/org/apache/camel/TypeConverterLoader  |   3 +
 .../services/org/apache/camel/component.properties |   7 +
 .../services/org/apache/camel/component/smooks     |   2 +
 .../org/apache/camel/configurer/smooks-component   |   2 +
 .../org/apache/camel/configurer/smooks-endpoint    |   2 +
 .../org/apache/camel/urifactory/smooks-endpoint    |   2 +
 .../src/main/docs/smooks-component.adoc            |  48 +++
 .../camel/component/smooks/SmooksComponent.java    |  51 ++++
 .../camel/component/smooks/SmooksEndpoint.java     |  61 ++++
 .../camel/component/smooks/SmooksProcessor.java    | 291 +++++++++++++++++++
 .../smooks/converter/ResultConverter.java          | 133 +++++++++
 .../smooks/converter/SourceConverter.java          |  67 +++++
 .../apache/camel/component/smooks/Coordinate.java  |  81 ++++++
 .../component/smooks/SmooksComponentTest.java      |  72 +++++
 .../component/smooks/SmooksProcessorTest.java      | 322 +++++++++++++++++++++
 .../smooks/converter/ResultConverterTest.java      |  64 ++++
 .../smooks/converter/SourceConverterTest.java      |  54 ++++
 .../src/test/resources/EBCDIC-input-message.txt    |   1 +
 .../camel-smooks/src/test/resources/data/order.txt |   4 +
 .../src/test/resources/edi-mapping-model.dfdl.xsd  |  79 +++++
 .../test/resources/edi-to-xml-smooks-config.xml    |  35 +++
 .../src/test/resources/xml/expected-order.xml      |  51 ++++
 components/pom.xml                                 |   1 +
 .../org/apache/camel/main/components.properties    |   1 +
 docs/components/modules/ROOT/nav.adoc              |   1 +
 .../component/ComponentsBuilderFactory.java        |  14 +
 .../builder/endpoint/EndpointBuilderFactory.java   |   1 +
 .../camel/builder/endpoint/EndpointBuilders.java   |   1 +
 .../builder/endpoint/StaticEndpointBuilders.java   |  42 +++
 .../camel-component-known-dependencies.properties  |   1 +
 parent/pom.xml                                     |   5 +
 41 files changed, 2121 insertions(+)

diff --git a/bom/camel-bom/pom.xml b/bom/camel-bom/pom.xml
index a250592fbbd..5bfbac4377a 100644
--- a/bom/camel-bom/pom.xml
+++ b/bom/camel-bom/pom.xml
@@ -1812,6 +1812,11 @@
         <artifactId>camel-smb</artifactId>
         <version>4.7.0-SNAPSHOT</version>
       </dependency>
+      <dependency>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>camel-smooks</artifactId>
+        <version>4.7.0-SNAPSHOT</version>
+      </dependency>
       <dependency>
         <groupId>org.apache.camel</groupId>
         <artifactId>camel-smpp</artifactId>
diff --git a/catalog/camel-allcomponents/pom.xml 
b/catalog/camel-allcomponents/pom.xml
index daf1adf8836..96f648880e9 100644
--- a/catalog/camel-allcomponents/pom.xml
+++ b/catalog/camel-allcomponents/pom.xml
@@ -1592,6 +1592,11 @@
             <artifactId>camel-smb</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-smooks</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-smpp</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 eda05e1c4c1..e321b253135 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
@@ -285,6 +285,7 @@ sjms
 sjms2
 slack
 smb
+smooks
 smpp
 smpps
 smtp
diff --git a/components/camel-smooks/pom.xml b/components/camel-smooks/pom.xml
new file mode 100644
index 00000000000..4128c93c996
--- /dev/null
+++ b/components/camel-smooks/pom.xml
@@ -0,0 +1,103 @@
+<?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.7.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>camel-smooks</artifactId>
+    <packaging>jar</packaging>
+
+    <name>Camel :: Smooks :: Parent</name>
+    <description>Camel Smooks Component</description>
+
+    <properties>
+        <smooks.version>2.0.0-RC4</smooks.version>
+    </properties>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.smooks</groupId>
+                <artifactId>smooks-bom</artifactId>
+                <version>${smooks.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.smooks</groupId>
+            <artifactId>smooks-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-file</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-attachments</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-support</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.smooks.cartridges.edi</groupId>
+            <artifactId>smooks-edi-cartridge</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.smooks.cartridges</groupId>
+            <artifactId>smooks-javabean-cartridge</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test-junit5</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.xmlunit</groupId>
+            <artifactId>xmlunit-core</artifactId>
+            <version>2.9.1</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <version>${mockito-version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest</artifactId>
+            <version>${hamcrest-version}</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git 
a/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/SmooksComponentConfigurer.java
 
b/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/SmooksComponentConfigurer.java
new file mode 100644
index 00000000000..dcc652ca67c
--- /dev/null
+++ 
b/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/SmooksComponentConfigurer.java
@@ -0,0 +1,63 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.smooks;
+
+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 SmooksComponentConfigurer extends PropertyConfigurerSupport 
implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+    @Override
+    public boolean configure(CamelContext camelContext, Object obj, String 
name, Object value, boolean ignoreCase) {
+        SmooksComponent target = (SmooksComponent) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "autowiredenabled":
+        case "autowiredEnabled": 
target.setAutowiredEnabled(property(camelContext, boolean.class, value)); 
return true;
+        case "bridgeerrorhandler":
+        case "bridgeErrorHandler": 
target.setBridgeErrorHandler(property(camelContext, boolean.class, value)); 
return true;
+        case "lazystartproducer":
+        case "lazyStartProducer": 
target.setLazyStartProducer(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 "bridgeerrorhandler":
+        case "bridgeErrorHandler": return boolean.class;
+        case "lazystartproducer":
+        case "lazyStartProducer": return boolean.class;
+        default: return null;
+        }
+    }
+
+    @Override
+    public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+        SmooksComponent target = (SmooksComponent) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "autowiredenabled":
+        case "autowiredEnabled": return target.isAutowiredEnabled();
+        case "bridgeerrorhandler":
+        case "bridgeErrorHandler": return target.isBridgeErrorHandler();
+        case "lazystartproducer":
+        case "lazyStartProducer": return target.isLazyStartProducer();
+        default: return null;
+        }
+    }
+}
+
diff --git 
a/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/SmooksEndpointConfigurer.java
 
b/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/SmooksEndpointConfigurer.java
new file mode 100644
index 00000000000..09fb353e905
--- /dev/null
+++ 
b/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/SmooksEndpointConfigurer.java
@@ -0,0 +1,165 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.smooks;
+
+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 SmooksEndpointConfigurer extends PropertyConfigurerSupport 
implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+    @Override
+    public boolean configure(CamelContext camelContext, Object obj, String 
name, Object value, boolean ignoreCase) {
+        SmooksEndpoint target = (SmooksEndpoint) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "backofferrorthreshold":
+        case "backoffErrorThreshold": 
target.setBackoffErrorThreshold(property(camelContext, int.class, value)); 
return true;
+        case "backoffidlethreshold":
+        case "backoffIdleThreshold": 
target.setBackoffIdleThreshold(property(camelContext, int.class, value)); 
return true;
+        case "backoffmultiplier":
+        case "backoffMultiplier": 
target.setBackoffMultiplier(property(camelContext, int.class, value)); return 
true;
+        case "bridgeerrorhandler":
+        case "bridgeErrorHandler": 
target.setBridgeErrorHandler(property(camelContext, boolean.class, value)); 
return true;
+        case "delay": target.setDelay(property(camelContext, long.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;
+        case "greedy": target.setGreedy(property(camelContext, boolean.class, 
value)); return true;
+        case "initialdelay":
+        case "initialDelay": target.setInitialDelay(property(camelContext, 
long.class, value)); return true;
+        case "lazystartproducer":
+        case "lazyStartProducer": 
target.setLazyStartProducer(property(camelContext, boolean.class, value)); 
return true;
+        case "pollstrategy":
+        case "pollStrategy": target.setPollStrategy(property(camelContext, 
org.apache.camel.spi.PollingConsumerPollStrategy.class, value)); return true;
+        case "repeatcount":
+        case "repeatCount": target.setRepeatCount(property(camelContext, 
long.class, value)); return true;
+        case "runlogginglevel":
+        case "runLoggingLevel": 
target.setRunLoggingLevel(property(camelContext, 
org.apache.camel.LoggingLevel.class, value)); return true;
+        case "scheduledexecutorservice":
+        case "scheduledExecutorService": 
target.setScheduledExecutorService(property(camelContext, 
java.util.concurrent.ScheduledExecutorService.class, value)); return true;
+        case "scheduler": target.setScheduler(property(camelContext, 
java.lang.Object.class, value)); return true;
+        case "schedulerproperties":
+        case "schedulerProperties": 
target.setSchedulerProperties(property(camelContext, java.util.Map.class, 
value)); return true;
+        case "sendemptymessagewhenidle":
+        case "sendEmptyMessageWhenIdle": 
target.setSendEmptyMessageWhenIdle(property(camelContext, boolean.class, 
value)); return true;
+        case "startscheduler":
+        case "startScheduler": target.setStartScheduler(property(camelContext, 
boolean.class, value)); return true;
+        case "timeunit":
+        case "timeUnit": target.setTimeUnit(property(camelContext, 
java.util.concurrent.TimeUnit.class, value)); return true;
+        case "usefixeddelay":
+        case "useFixedDelay": target.setUseFixedDelay(property(camelContext, 
boolean.class, value)); return true;
+        default: return false;
+        }
+    }
+
+    @Override
+    public Class<?> getOptionType(String name, boolean ignoreCase) {
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "backofferrorthreshold":
+        case "backoffErrorThreshold": return int.class;
+        case "backoffidlethreshold":
+        case "backoffIdleThreshold": return int.class;
+        case "backoffmultiplier":
+        case "backoffMultiplier": return int.class;
+        case "bridgeerrorhandler":
+        case "bridgeErrorHandler": return boolean.class;
+        case "delay": return long.class;
+        case "exceptionhandler":
+        case "exceptionHandler": return 
org.apache.camel.spi.ExceptionHandler.class;
+        case "exchangepattern":
+        case "exchangePattern": return org.apache.camel.ExchangePattern.class;
+        case "greedy": return boolean.class;
+        case "initialdelay":
+        case "initialDelay": return long.class;
+        case "lazystartproducer":
+        case "lazyStartProducer": return boolean.class;
+        case "pollstrategy":
+        case "pollStrategy": return 
org.apache.camel.spi.PollingConsumerPollStrategy.class;
+        case "repeatcount":
+        case "repeatCount": return long.class;
+        case "runlogginglevel":
+        case "runLoggingLevel": return org.apache.camel.LoggingLevel.class;
+        case "scheduledexecutorservice":
+        case "scheduledExecutorService": return 
java.util.concurrent.ScheduledExecutorService.class;
+        case "scheduler": return java.lang.Object.class;
+        case "schedulerproperties":
+        case "schedulerProperties": return java.util.Map.class;
+        case "sendemptymessagewhenidle":
+        case "sendEmptyMessageWhenIdle": return boolean.class;
+        case "startscheduler":
+        case "startScheduler": return boolean.class;
+        case "timeunit":
+        case "timeUnit": return java.util.concurrent.TimeUnit.class;
+        case "usefixeddelay":
+        case "useFixedDelay": return boolean.class;
+        default: return null;
+        }
+    }
+
+    @Override
+    public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+        SmooksEndpoint target = (SmooksEndpoint) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "backofferrorthreshold":
+        case "backoffErrorThreshold": return target.getBackoffErrorThreshold();
+        case "backoffidlethreshold":
+        case "backoffIdleThreshold": return target.getBackoffIdleThreshold();
+        case "backoffmultiplier":
+        case "backoffMultiplier": return target.getBackoffMultiplier();
+        case "bridgeerrorhandler":
+        case "bridgeErrorHandler": return target.isBridgeErrorHandler();
+        case "delay": return target.getDelay();
+        case "exceptionhandler":
+        case "exceptionHandler": return target.getExceptionHandler();
+        case "exchangepattern":
+        case "exchangePattern": return target.getExchangePattern();
+        case "greedy": return target.isGreedy();
+        case "initialdelay":
+        case "initialDelay": return target.getInitialDelay();
+        case "lazystartproducer":
+        case "lazyStartProducer": return target.isLazyStartProducer();
+        case "pollstrategy":
+        case "pollStrategy": return target.getPollStrategy();
+        case "repeatcount":
+        case "repeatCount": return target.getRepeatCount();
+        case "runlogginglevel":
+        case "runLoggingLevel": return target.getRunLoggingLevel();
+        case "scheduledexecutorservice":
+        case "scheduledExecutorService": return 
target.getScheduledExecutorService();
+        case "scheduler": return target.getScheduler();
+        case "schedulerproperties":
+        case "schedulerProperties": return target.getSchedulerProperties();
+        case "sendemptymessagewhenidle":
+        case "sendEmptyMessageWhenIdle": return 
target.isSendEmptyMessageWhenIdle();
+        case "startscheduler":
+        case "startScheduler": return target.isStartScheduler();
+        case "timeunit":
+        case "timeUnit": return target.getTimeUnit();
+        case "usefixeddelay":
+        case "useFixedDelay": return target.isUseFixedDelay();
+        default: return null;
+        }
+    }
+
+    @Override
+    public Object getCollectionValueType(Object target, String name, boolean 
ignoreCase) {
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "schedulerproperties":
+        case "schedulerProperties": return java.lang.Object.class;
+        default: return null;
+        }
+    }
+}
+
diff --git 
a/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/SmooksEndpointUriFactory.java
 
b/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/SmooksEndpointUriFactory.java
new file mode 100644
index 00000000000..a7552824dd9
--- /dev/null
+++ 
b/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/SmooksEndpointUriFactory.java
@@ -0,0 +1,92 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.smooks;
+
+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 SmooksEndpointUriFactory extends 
org.apache.camel.support.component.EndpointUriFactorySupport implements 
EndpointUriFactory {
+
+    private static final String BASE = "://smooks-config-path";
+
+    private static final Set<String> PROPERTY_NAMES;
+    private static final Set<String> SECRET_PROPERTY_NAMES;
+    private static final Set<String> MULTI_VALUE_PREFIXES;
+    static {
+        Set<String> props = new HashSet<>(21);
+        props.add("backoffErrorThreshold");
+        props.add("backoffIdleThreshold");
+        props.add("backoffMultiplier");
+        props.add("bridgeErrorHandler");
+        props.add("database");
+        props.add("delay");
+        props.add("exceptionHandler");
+        props.add("exchangePattern");
+        props.add("greedy");
+        props.add("initialDelay");
+        props.add("lazyStartProducer");
+        props.add("pollStrategy");
+        props.add("repeatCount");
+        props.add("runLoggingLevel");
+        props.add("scheduledExecutorService");
+        props.add("scheduler");
+        props.add("schedulerProperties");
+        props.add("sendEmptyMessageWhenIdle");
+        props.add("startScheduler");
+        props.add("timeUnit");
+        props.add("useFixedDelay");
+        PROPERTY_NAMES = Collections.unmodifiableSet(props);
+        SECRET_PROPERTY_NAMES = Collections.emptySet();
+        Set<String> prefixes = new HashSet<>(1);
+        prefixes.add("scheduler.");
+        MULTI_VALUE_PREFIXES = Collections.unmodifiableSet(prefixes);
+    }
+
+    @Override
+    public boolean isEnabled(String scheme) {
+        return "smooks".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, "database", 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> multiValuePrefixes() {
+        return MULTI_VALUE_PREFIXES;
+    }
+
+    @Override
+    public boolean isLenientProperties() {
+        return false;
+    }
+}
+
diff --git 
a/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/converter/ResultConverterLoader.java
 
b/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/converter/ResultConverterLoader.java
new file mode 100644
index 00000000000..2280a868479
--- /dev/null
+++ 
b/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/converter/ResultConverterLoader.java
@@ -0,0 +1,73 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.smooks.converter;
+
+import javax.annotation.processing.Generated;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.DeferredContextBinding;
+import org.apache.camel.Exchange;
+import org.apache.camel.TypeConversionException;
+import org.apache.camel.TypeConverterLoaderException;
+import org.apache.camel.spi.TypeConverterLoader;
+import org.apache.camel.spi.TypeConverterRegistry;
+import org.apache.camel.support.SimpleTypeConverter;
+import org.apache.camel.support.TypeConverterSupport;
+import org.apache.camel.util.DoubleMap;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.TypeConverterLoaderGeneratorMojo")
+@SuppressWarnings("unchecked")
+@DeferredContextBinding
+public final class ResultConverterLoader implements TypeConverterLoader, 
CamelContextAware {
+
+    private CamelContext camelContext;
+
+    public ResultConverterLoader() {
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void load(TypeConverterRegistry registry) throws 
TypeConverterLoaderException {
+        registerConverters(registry);
+        registerFallbackConverters(registry);
+    }
+
+    private void registerConverters(TypeConverterRegistry registry) {
+        addTypeConverter(registry, java.lang.Double.class, 
org.smooks.io.payload.JavaResult.ResultMap.class, false,
+            (type, exchange, value) -> 
org.apache.camel.component.smooks.converter.ResultConverter.toDouble((org.smooks.io.payload.JavaResult.ResultMap)
 value));
+        addTypeConverter(registry, java.lang.Integer.class, 
org.smooks.io.payload.JavaResult.ResultMap.class, false,
+            (type, exchange, value) -> 
org.apache.camel.component.smooks.converter.ResultConverter.toInteger((org.smooks.io.payload.JavaResult.ResultMap)
 value));
+        addTypeConverter(registry, java.lang.String.class, 
org.smooks.io.payload.StringResult.class, false,
+            (type, exchange, value) -> 
org.apache.camel.component.smooks.converter.ResultConverter.toString((org.smooks.io.payload.StringResult)
 value));
+        addTypeConverter(registry, java.util.List.class, 
org.smooks.io.payload.JavaResult.ResultMap.class, false,
+            (type, exchange, value) -> 
org.apache.camel.component.smooks.converter.ResultConverter.toList((org.smooks.io.payload.JavaResult.ResultMap)
 value, exchange));
+        addTypeConverter(registry, 
javax.xml.transform.stream.StreamSource.class, 
org.smooks.io.payload.StringResult.class, false,
+            (type, exchange, value) -> 
org.apache.camel.component.smooks.converter.ResultConverter.toStreamSource((org.smooks.io.payload.StringResult)
 value));
+        addTypeConverter(registry, org.w3c.dom.Node.class, 
javax.xml.transform.dom.DOMResult.class, false,
+            (type, exchange, value) -> 
org.apache.camel.component.smooks.converter.ResultConverter.toDocument((javax.xml.transform.dom.DOMResult)
 value));
+    }
+
+    private static void addTypeConverter(TypeConverterRegistry registry, 
Class<?> toType, Class<?> fromType, boolean allowNull, 
SimpleTypeConverter.ConversionMethod method) {
+        registry.addTypeConverter(toType, fromType, new 
SimpleTypeConverter(allowNull, method));
+    }
+
+    private void registerFallbackConverters(TypeConverterRegistry registry) {
+        addFallbackTypeConverter(registry, false, false, (type, exchange, 
value) -> 
org.apache.camel.component.smooks.converter.ResultConverter.convertTo(type, 
exchange, value, registry));
+    }
+
+    private static void addFallbackTypeConverter(TypeConverterRegistry 
registry, boolean allowNull, boolean canPromote, 
SimpleTypeConverter.ConversionMethod method) {
+        registry.addFallbackTypeConverter(new SimpleTypeConverter(allowNull, 
method), canPromote);
+    }
+}
diff --git 
a/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/converter/SourceConverterLoader.java
 
b/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/converter/SourceConverterLoader.java
new file mode 100644
index 00000000000..72cbcb7b288
--- /dev/null
+++ 
b/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/converter/SourceConverterLoader.java
@@ -0,0 +1,62 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.smooks.converter;
+
+import javax.annotation.processing.Generated;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.DeferredContextBinding;
+import org.apache.camel.Exchange;
+import org.apache.camel.TypeConversionException;
+import org.apache.camel.TypeConverterLoaderException;
+import org.apache.camel.spi.TypeConverterLoader;
+import org.apache.camel.spi.TypeConverterRegistry;
+import org.apache.camel.support.SimpleTypeConverter;
+import org.apache.camel.support.TypeConverterSupport;
+import org.apache.camel.util.DoubleMap;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.TypeConverterLoaderGeneratorMojo")
+@SuppressWarnings("unchecked")
+@DeferredContextBinding
+public final class SourceConverterLoader implements TypeConverterLoader, 
CamelContextAware {
+
+    private CamelContext camelContext;
+
+    public SourceConverterLoader() {
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void load(TypeConverterRegistry registry) throws 
TypeConverterLoaderException {
+        registerConverters(registry);
+    }
+
+    private void registerConverters(TypeConverterRegistry registry) {
+        addTypeConverter(registry, javax.xml.transform.Source.class, 
java.io.InputStream.class, false,
+            (type, exchange, value) -> 
org.apache.camel.component.smooks.converter.SourceConverter.toStreamSource((java.io.InputStream)
 value));
+        addTypeConverter(registry, javax.xml.transform.Source.class, 
org.apache.camel.component.file.GenericFile.class, false,
+            (type, exchange, value) -> 
org.apache.camel.component.smooks.converter.SourceConverter.toStreamSource((org.apache.camel.component.file.GenericFile)
 value));
+        addTypeConverter(registry, org.smooks.io.payload.JavaSource.class, 
java.lang.Object.class, false,
+            (type, exchange, value) -> 
org.apache.camel.component.smooks.converter.SourceConverter.toJavaSource(value));
+        addTypeConverter(registry, org.smooks.io.payload.JavaSource.class, 
org.smooks.io.payload.JavaResult.class, false,
+            (type, exchange, value) -> 
org.apache.camel.component.smooks.converter.SourceConverter.toJavaSource((org.smooks.io.payload.JavaResult)
 value));
+        addTypeConverter(registry, 
org.smooks.io.payload.JavaSourceWithoutEventStream.class, 
java.lang.Object.class, false,
+            (type, exchange, value) -> 
org.apache.camel.component.smooks.converter.SourceConverter.toJavaSourceWithoutEventStream(value));
+    }
+
+    private static void addTypeConverter(TypeConverterRegistry registry, 
Class<?> toType, Class<?> fromType, boolean allowNull, 
SimpleTypeConverter.ConversionMethod method) {
+        registry.addTypeConverter(toType, fromType, new 
SimpleTypeConverter(allowNull, method));
+    }
+}
diff --git 
a/components/camel-smooks/src/generated/resources/META-INF/org/apache/camel/component/smooks/smooks.json
 
b/components/camel-smooks/src/generated/resources/META-INF/org/apache/camel/component/smooks/smooks.json
new file mode 100644
index 00000000000..cb677a24991
--- /dev/null
+++ 
b/components/camel-smooks/src/generated/resources/META-INF/org/apache/camel/component/smooks/smooks.json
@@ -0,0 +1,53 @@
+{
+  "component": {
+    "kind": "component",
+    "name": "smooks",
+    "title": "Smooks",
+    "description": "Applies fragment-based processing in Smooks to perform a 
variety of operations like transformation.",
+    "deprecated": false,
+    "firstVersion": "4.7.0",
+    "label": "file",
+    "javaType": "org.apache.camel.component.smooks.SmooksComponent",
+    "supportLevel": "Preview",
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-smooks",
+    "version": "4.7.0-SNAPSHOT",
+    "scheme": "smooks",
+    "extendsScheme": "",
+    "syntax": "smooks:\/\/smooks-config-path",
+    "async": false,
+    "api": false,
+    "consumerOnly": false,
+    "producerOnly": false,
+    "lenientProperties": false,
+    "remote": true
+  },
+  "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 [...]
+    "lazyStartProducer": { "index": 1, "kind": "property", "displayName": 
"Lazy Start Producer", "group": "producer", "label": "producer", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": false, "description": 
"Whether the producer should be started lazy (on the first message). By 
starting lazy you can use this to allow CamelContext and routes to startup in 
situations where a producer may otherwise fail [...]
+    "autowiredEnabled": { "index": 2, "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 [...]
+  },
+  "properties": {
+    "database": { "index": 0, "kind": "path", "displayName": "Database", 
"group": "common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "database name" },
+    "sendEmptyMessageWhenIdle": { "index": 1, "kind": "parameter", 
"displayName": "Send Empty Message When Idle", "group": "consumer", "label": 
"consumer", "required": false, "type": "boolean", "javaType": "boolean", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": 
false, "description": "If the polling consumer did not poll any files, you can 
enable this option to send an empty message (no body) instead." },
+    "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": "object", "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." },
+    "pollStrategy": { "index": 5, "kind": "parameter", "displayName": "Poll 
Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", 
"required": false, "type": "object", "javaType": 
"org.apache.camel.spi.PollingConsumerPollStrategy", "deprecated": false, 
"autowired": false, "secret": false, "description": "A pluggable 
org.apache.camel.PollingConsumerPollingStrategy allowing you to provide your 
custom implementation to control error handling usually occurred during the pol 
[...]
+    "lazyStartProducer": { "index": 6, "kind": "parameter", "displayName": 
"Lazy Start Producer", "group": "producer (advanced)", "label": 
"producer,advanced", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": false, "description": "Whether the producer should be started 
lazy (on the first message). By starting lazy you can use this to allow 
CamelContext and routes to startup in situations where a produc [...]
+    "backoffErrorThreshold": { "index": 7, "kind": "parameter", "displayName": 
"Backoff Error Threshold", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "integer", "javaType": "int", "deprecated": false, 
"autowired": false, "secret": false, "description": "The number of subsequent 
error polls (failed due some error) that should happen before the 
backoffMultipler should kick-in." },
+    "backoffIdleThreshold": { "index": 8, "kind": "parameter", "displayName": 
"Backoff Idle Threshold", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "integer", "javaType": "int", "deprecated": false, 
"autowired": false, "secret": false, "description": "The number of subsequent 
idle polls that should happen before the backoffMultipler should kick-in." },
+    "backoffMultiplier": { "index": 9, "kind": "parameter", "displayName": 
"Backoff Multiplier", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "integer", "javaType": "int", "deprecated": false, 
"autowired": false, "secret": false, "description": "To let the scheduled 
polling consumer backoff if there has been a number of subsequent idles\/errors 
in a row. The multiplier is then the number of polls that will be skipped 
before the next actual attempt is ha [...]
+    "delay": { "index": 10, "kind": "parameter", "displayName": "Delay", 
"group": "scheduler", "label": "consumer,scheduler", "required": false, "type": 
"integer", "javaType": "long", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": 500, "description": "Milliseconds before the 
next poll." },
+    "greedy": { "index": 11, "kind": "parameter", "displayName": "Greedy", 
"group": "scheduler", "label": "consumer,scheduler", "required": false, "type": 
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": false, "description": "If greedy is enabled, 
then the ScheduledPollConsumer will run immediately again, if the previous run 
polled 1 or more messages." },
+    "initialDelay": { "index": 12, "kind": "parameter", "displayName": 
"Initial Delay", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "integer", "javaType": "long", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": 1000, "description": 
"Milliseconds before the first poll starts." },
+    "repeatCount": { "index": 13, "kind": "parameter", "displayName": "Repeat 
Count", "group": "scheduler", "label": "consumer,scheduler", "required": false, 
"type": "integer", "javaType": "long", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": 0, "description": "Specifies a maximum limit 
of number of fires. So if you set it to 1, the scheduler will only fire once. 
If you set it to 5, it will only fire five times. A value of zero or negative 
means fire forever." },
+    "runLoggingLevel": { "index": 14, "kind": "parameter", "displayName": "Run 
Logging Level", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "object", "javaType": 
"org.apache.camel.LoggingLevel", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", 
"ERROR", "OFF" ], "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": "TRACE", "description": "The consumer logs a start\/complete 
log line when it polls. This option allows you to configure the l [...]
+    "scheduledExecutorService": { "index": 15, "kind": "parameter", 
"displayName": "Scheduled Executor Service", "group": "scheduler", "label": 
"consumer,scheduler", "required": false, "type": "object", "javaType": 
"java.util.concurrent.ScheduledExecutorService", "deprecated": false, 
"autowired": false, "secret": false, "description": "Allows for configuring a 
custom\/shared thread pool to use for the consumer. By default each consumer 
has its own single threaded thread pool." },
+    "scheduler": { "index": 16, "kind": "parameter", "displayName": 
"Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": 
false, "type": "object", "javaType": "java.lang.Object", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": "none", "description": "To 
use a cron scheduler from either camel-spring or camel-quartz component. Use 
value spring or quartz for built in scheduler" },
+    "schedulerProperties": { "index": 17, "kind": "parameter", "displayName": 
"Scheduler Properties", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "object", "javaType": 
"java.util.Map<java.lang.String, java.lang.Object>", "prefix": "scheduler.", 
"multiValue": true, "deprecated": false, "autowired": false, "secret": false, 
"description": "To configure additional properties when using a custom 
scheduler or any of the Quartz, Spring based scheduler." },
+    "startScheduler": { "index": 18, "kind": "parameter", "displayName": 
"Start Scheduler", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "boolean", "javaType": "boolean", "deprecated": 
false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Whether the scheduler should be auto started." },
+    "timeUnit": { "index": 19, "kind": "parameter", "displayName": "Time 
Unit", "group": "scheduler", "label": "consumer,scheduler", "required": false, 
"type": "object", "javaType": "java.util.concurrent.TimeUnit", "enum": [ 
"NANOSECONDS", "MICROSECONDS", "MILLISECONDS", "SECONDS", "MINUTES", "HOURS", 
"DAYS" ], "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": "MILLISECONDS", "description": "Time unit for initialDelay and 
delay options." },
+    "useFixedDelay": { "index": 20, "kind": "parameter", "displayName": "Use 
Fixed Delay", "group": "scheduler", "label": "consumer,scheduler", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in 
JDK for details." }
+  }
+}
diff --git 
a/components/camel-smooks/src/generated/resources/META-INF/services/org/apache/camel/TypeConverterLoader
 
b/components/camel-smooks/src/generated/resources/META-INF/services/org/apache/camel/TypeConverterLoader
new file mode 100644
index 00000000000..5b76f723f6b
--- /dev/null
+++ 
b/components/camel-smooks/src/generated/resources/META-INF/services/org/apache/camel/TypeConverterLoader
@@ -0,0 +1,3 @@
+# Generated by camel build tools - do NOT edit this file!
+org.apache.camel.component.smooks.converter.ResultConverterLoader
+org.apache.camel.component.smooks.converter.SourceConverterLoader
diff --git 
a/components/camel-smooks/src/generated/resources/META-INF/services/org/apache/camel/component.properties
 
b/components/camel-smooks/src/generated/resources/META-INF/services/org/apache/camel/component.properties
new file mode 100644
index 00000000000..4f818d51d25
--- /dev/null
+++ 
b/components/camel-smooks/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=smooks
+groupId=org.apache.camel
+artifactId=camel-smooks
+version=4.7.0-SNAPSHOT
+projectName=Camel :: Smooks :: Parent
+projectDescription=Camel Smooks Component
diff --git 
a/components/camel-smooks/src/generated/resources/META-INF/services/org/apache/camel/component/smooks
 
b/components/camel-smooks/src/generated/resources/META-INF/services/org/apache/camel/component/smooks
new file mode 100644
index 00000000000..94f3d034fed
--- /dev/null
+++ 
b/components/camel-smooks/src/generated/resources/META-INF/services/org/apache/camel/component/smooks
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.smooks.SmooksComponent
diff --git 
a/components/camel-smooks/src/generated/resources/META-INF/services/org/apache/camel/configurer/smooks-component
 
b/components/camel-smooks/src/generated/resources/META-INF/services/org/apache/camel/configurer/smooks-component
new file mode 100644
index 00000000000..ad88c91d6a2
--- /dev/null
+++ 
b/components/camel-smooks/src/generated/resources/META-INF/services/org/apache/camel/configurer/smooks-component
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.smooks.SmooksComponentConfigurer
diff --git 
a/components/camel-smooks/src/generated/resources/META-INF/services/org/apache/camel/configurer/smooks-endpoint
 
b/components/camel-smooks/src/generated/resources/META-INF/services/org/apache/camel/configurer/smooks-endpoint
new file mode 100644
index 00000000000..27edabac926
--- /dev/null
+++ 
b/components/camel-smooks/src/generated/resources/META-INF/services/org/apache/camel/configurer/smooks-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.smooks.SmooksEndpointConfigurer
diff --git 
a/components/camel-smooks/src/generated/resources/META-INF/services/org/apache/camel/urifactory/smooks-endpoint
 
b/components/camel-smooks/src/generated/resources/META-INF/services/org/apache/camel/urifactory/smooks-endpoint
new file mode 100644
index 00000000000..e371a6ef04e
--- /dev/null
+++ 
b/components/camel-smooks/src/generated/resources/META-INF/services/org/apache/camel/urifactory/smooks-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.smooks.SmooksEndpointUriFactory
diff --git a/components/camel-smooks/src/main/docs/smooks-component.adoc 
b/components/camel-smooks/src/main/docs/smooks-component.adoc
new file mode 100644
index 00000000000..d5d1a1056af
--- /dev/null
+++ b/components/camel-smooks/src/main/docs/smooks-component.adoc
@@ -0,0 +1,48 @@
+= Smooks Component
+:doctitle: Smooks
+:shortname: smooks
+:artifactid: camel-smooks
+:description: Applies fragment-based processing in Smooks to perform a variety 
of operations like transformation.
+:since: 4.7
+:supportlevel: Preview
+:tabs-sync-option:
+:component-header: Both producer and consumer are supported
+
+*Since Camel {since}*
+
+*{component-header}*
+
+The Camel Smooks component uses https://www.smooks.org/[Smooks] to break up 
the structured data (EDI, CSV, POJO, etc...) of a Camel message body into 
fragments. These fragments can be processed independently of one another from 
within Smooks.
+
+Common applications of Smooks include transformation (e.g., EDI to CSV, POJO 
to EDI, POJO to XML), routing (e.g., split, transform, and route fragments to 
destinations such as JMS queues, file systems, and databases), and enrichment 
(e.g., enriching a fragment with data from a database).
+
+Maven users will need to add the following dependency to their `+pom.xml+`.
+
+[source,xml]
+----
+<dependency>
+    <groupId>org.apache.camel</groupId>
+    <artifactId>camel-smooks</artifactId>
+    <version>x.x.x</version>
+    <!-- use the same version as your Camel core version -->
+</dependency>
+----
+
+== URI Format
+
+....
+smooks://smooks-config-path[?options]
+....
+
+// component-configure options: START
+
+// component-configure options: END
+
+// component options: START
+include::partial$component-configure-options.adoc[]
+include::partial$component-endpoint-options.adoc[]
+// component options: END
+
+// endpoint options: START
+
+// endpoint options: END
diff --git 
a/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksComponent.java
 
b/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksComponent.java
new file mode 100644
index 00000000000..42bcf7cf613
--- /dev/null
+++ 
b/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksComponent.java
@@ -0,0 +1,51 @@
+/*
+ * 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.smooks;
+
+import java.util.Map;
+
+import org.apache.camel.Endpoint;
+import org.apache.camel.spi.annotations.Component;
+import org.apache.camel.support.DefaultComponent;
+
+/**
+ * Smook Camel Component.
+ * <p/>
+ * <p>
+ * Example usage:
+ *
+ * <pre>
+ * 
from(&quot;direct:a&quot;).to(&quot;smooks://edi-to-xml-smooks-config.xml&quot;)
+ * </pre>
+ *
+ * @author Christian Mueller
+ * @author Daniel Bevenius
+ */
+@Component("smooks")
+public class SmooksComponent extends DefaultComponent {
+    protected Endpoint createEndpoint(String uri, String remaining, 
Map<String, Object> parameters) throws Exception {
+        SmooksProcessor smooksProcessor = new SmooksProcessor(remaining, 
getCamelContext());
+        configureSmooksProcessor(smooksProcessor, uri, remaining, parameters);
+        return new SmooksEndpoint(uri, this, smooksProcessor);
+    }
+
+    protected void configureSmooksProcessor(SmooksProcessor smooksProcessor, 
String uri, String remaining,
+                                            Map<String, Object> parameters) 
throws Exception {
+        setProperties(smooksProcessor, parameters);
+    }
+
+}
diff --git 
a/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksEndpoint.java
 
b/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksEndpoint.java
new file mode 100644
index 00000000000..641d58f3d10
--- /dev/null
+++ 
b/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksEndpoint.java
@@ -0,0 +1,61 @@
+/*
+ * 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.smooks;
+
+import org.apache.camel.Category;
+import org.apache.camel.Component;
+import org.apache.camel.Service;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.UriEndpoint;
+import org.apache.camel.spi.UriPath;
+import org.apache.camel.support.ProcessorEndpoint;
+import org.smooks.api.SmooksException;
+
+/**
+ * Applies fragment-based processing in Smooks to perform a variety of 
operations like transformation.
+ */
+@UriEndpoint(firstVersion = "4.7.0", scheme = "smooks", title = "Smooks", 
syntax = "smooks://smooks-config-path", category = { Category.FILE })
+public class SmooksEndpoint extends ProcessorEndpoint implements Service {
+
+    @UriPath(description = "database name")
+    @Metadata(required = true)
+    private String database;
+
+    private final SmooksProcessor smooksProcessor;
+
+    public SmooksEndpoint(String endpointUri, Component component, 
SmooksProcessor processor) {
+        super(endpointUri, component, processor);
+        this.smooksProcessor = processor;
+    }
+
+    public void start() {
+        try {
+            smooksProcessor.start();
+        } catch (Exception e) {
+            throw new SmooksException(e.getMessage(), e);
+        }
+    }
+
+    public void stop() {
+        try {
+            smooksProcessor.stop();
+        } catch (Exception e) {
+            throw new SmooksException(e.getMessage(), e);
+        }
+    }
+
+}
diff --git 
a/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksProcessor.java
 
b/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksProcessor.java
new file mode 100644
index 00000000000..3636f2f86a3
--- /dev/null
+++ 
b/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksProcessor.java
@@ -0,0 +1,291 @@
+/*
+ * 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.smooks;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.*;
+import java.util.Map.Entry;
+
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stream.StreamSource;
+
+import org.w3c.dom.Node;
+
+import org.xml.sax.SAXException;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.Processor;
+import org.apache.camel.Service;
+import org.apache.camel.WrappedFile;
+import org.apache.camel.attachment.Attachment;
+import org.apache.camel.attachment.AttachmentMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.smooks.Smooks;
+import org.smooks.SmooksFactory;
+import org.smooks.api.ExecutionContext;
+import org.smooks.api.SmooksException;
+import org.smooks.api.TypedKey;
+import org.smooks.api.delivery.VisitorAppender;
+import org.smooks.api.resource.visitor.Visitor;
+import org.smooks.engine.lookup.ExportsLookup;
+import org.smooks.engine.report.HtmlReportGenerator;
+import org.smooks.io.payload.Exports;
+
+/**
+ * Smooks {@link Processor} for Camel.
+ *
+ * @author Christian Mueller
+ * @author Daniel Bevenius
+ */
+public class SmooksProcessor implements Processor, Service, CamelContextAware {
+    public static final String SMOOKS_EXECUTION_CONTEXT = 
"CamelSmooksExecutionContext";
+    public static final String CAMEL_CHARACTER_ENCODING = "CamelCharsetName";
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(SmooksProcessor.class);
+    public static final TypedKey<Exchange> EXCHANGE_TYPED_KEY = TypedKey.of();
+
+    private Smooks smooks;
+    private String configUri;
+    private String reportPath;
+
+    private Set<VisitorAppender> visitorAppenders = new HashSet<>();
+    private Map<String, Visitor> selectorVisitorMap = new HashMap<>();
+    private CamelContext camelContext;
+    private boolean attachmentsSupported = false;
+
+    public SmooksProcessor(final CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    public SmooksProcessor(final Smooks smooks, final CamelContext 
camelContext) {
+        this(camelContext);
+        this.smooks = smooks;
+    }
+
+    public SmooksProcessor(final String configUri, final CamelContext 
camelContext) throws IOException, SAXException {
+        this(camelContext);
+        this.configUri = configUri;
+    }
+
+    public void process(final Exchange exchange) {
+        //forward headers
+        exchange.getMessage().setHeaders(exchange.getIn().getHeaders());
+
+        if (attachmentsSupported) {
+            //forward attachments
+            if (exchange.getIn(AttachmentMessage.class).hasAttachments()) {
+                for (Entry<String, Attachment> attachmentObject : 
exchange.getIn(AttachmentMessage.class).getAttachmentObjects().entrySet()) {
+                    
exchange.getMessage(AttachmentMessage.class).addAttachmentObject(attachmentObject.getKey(),
 attachmentObject.getValue());
+                }
+            }
+        }
+
+        final ExecutionContext executionContext = 
smooks.createExecutionContext();
+        executionContext.put(EXCHANGE_TYPED_KEY, exchange);
+        String charsetName = (String) 
exchange.getProperty(CAMEL_CHARACTER_ENCODING);
+        if (charsetName != null) //if provided use the came character encoding
+        {
+            executionContext.setContentEncoding(charsetName);
+        }
+        exchange.getIn().setHeader(SMOOKS_EXECUTION_CONTEXT, executionContext);
+        setupSmooksReporting(executionContext);
+
+        final Exports exports = 
smooks.getApplicationContext().getRegistry().lookup(new ExportsLookup());
+        if (exports.hasExports()) {
+            final Result[] results = exports.createResults();
+            smooks.filterSource(executionContext, getSource(exchange), 
results);
+            setResultOnBody(exports, results, exchange);
+        } else {
+            smooks.filterSource(executionContext, getSource(exchange));
+        }
+
+        executionContext.remove(EXCHANGE_TYPED_KEY);
+    }
+
+    protected void setResultOnBody(final Exports exports, final Result[] 
results, final Exchange exchange) {
+        final Message message = exchange.getMessage();
+        final List<Object> objects = Exports.extractResults(results, exports);
+        if (objects.size() == 1) {
+            Object value = objects.get(0);
+            message.setBody(value);
+        } else {
+            message.setBody(objects);
+        }
+    }
+
+    private void setupSmooksReporting(final ExecutionContext executionContext) 
{
+        if (reportPath != null) {
+            try {
+                
executionContext.getContentDeliveryRuntime().addExecutionEventListener(new 
HtmlReportGenerator(reportPath, executionContext.getApplicationContext()));
+            } catch (final IOException e) {
+                LOGGER.info("Could not generate Smooks Report. The reportPath 
specified was [" + reportPath + "].", e);
+            }
+        }
+    }
+
+    private Source getSource(final Exchange exchange) {
+        Object payload = exchange.getIn().getBody();
+
+
+        if (payload instanceof SAXSource) {
+            return new StreamSource((Reader) ((SAXSource) 
payload).getXMLReader());
+        }
+
+        if (payload instanceof Source) {
+            return (Source) payload;
+        }
+
+        if (payload instanceof Node) {
+            return new DOMSource((Node) payload);
+        }
+
+        if (payload instanceof InputStream) {
+            return new StreamSource((InputStream) payload);
+        }
+
+        if (payload instanceof Reader) {
+            return new StreamSource((Reader) payload);
+        }
+
+        if (payload instanceof WrappedFile) {
+            return new StreamSource((File) 
exchange.getIn().getBody(WrappedFile.class).getFile());
+        }
+
+        return exchange.getIn().getBody(Source.class);
+    }
+
+    public String getSmooksConfig() {
+        return configUri;
+    }
+
+    public void setSmooksConfig(final String smooksConfig) {
+        this.configUri = smooksConfig;
+    }
+
+    /**
+     * Add a visitor instance.
+     *
+     * @param visitor        The visitor implementation.
+     * @param targetSelector The message fragment target selector.
+     * @return This instance.
+     */
+    public SmooksProcessor addVisitor(Visitor visitor, String targetSelector) {
+        selectorVisitorMap.put(targetSelector, visitor);
+        return this;
+    }
+
+    /**
+     * Add a visitor instance to <code>this</code> Smooks instance via a
+     * {@link VisitorAppender}.
+     *
+     * @param appender The visitor appender.
+     * @return This instance.
+     */
+    public SmooksProcessor addVisitor(VisitorAppender appender) {
+        visitorAppenders.add(appender);
+        return this;
+    }
+
+    public void setReportPath(String reportPath) {
+        this.reportPath = reportPath;
+    }
+
+    @Override
+    public void start() {
+        try {
+            if (smooks == null) {
+                smooks = createSmooks();
+                if (configUri != null) {
+                    smooks.addResourceConfigs(configUri);
+                }
+                
smooks.getApplicationContext().getRegistry().registerObject(CamelContext.class, 
camelContext);
+            }
+
+            addAppenders(smooks, visitorAppenders);
+            addVisitors(smooks, selectorVisitorMap);
+
+            InputStream inputStream = null;
+            try {
+                inputStream = 
camelContext.getClassResolver().loadResourceAsStream("META-INF/services/org/apache/camel/other.properties");
+                if (inputStream != null) {
+                    final Properties properties = new Properties();
+                    properties.load(inputStream);
+                    if (properties.getProperty("name") != null && 
properties.getProperty("name").equals("attachments")) {
+                        attachmentsSupported = true;
+                    }
+                }
+            } finally {
+                if (!attachmentsSupported) {
+                    LOGGER.warn("Attachments module could not be found: 
attachments will not be propagated");
+                }
+                if (inputStream != null) {
+                    inputStream.close();
+                }
+            }
+
+            LOGGER.info(this + " Started");
+        } catch (SAXException | IOException e) {
+            throw new SmooksException(e.getMessage(), e);
+        }
+    }
+
+    private Smooks createSmooks() {
+        final SmooksFactory smooksFactory = (SmooksFactory) 
camelContext.getRegistry().lookupByName(SmooksFactory.class.getName());
+        return smooksFactory != null ? smooksFactory.createInstance() : new 
Smooks();
+    }
+
+    private void addAppenders(Smooks smooks, Set<VisitorAppender> 
visitorAppenders) {
+        for (VisitorAppender appender : visitorAppenders)
+            smooks.addVisitors(appender);
+    }
+
+    private void addVisitors(Smooks smooks, Map<String, Visitor> 
selectorVisitorMap) {
+        for (Entry<String, Visitor> entry : selectorVisitorMap.entrySet())
+            smooks.addVisitor(entry.getValue(), entry.getKey());
+    }
+
+    public void stop() {
+        if (smooks != null) {
+            smooks.close();
+            smooks = null;
+        }
+        LOGGER.info(this + " Stopped");
+    }
+
+    @Override
+    public String toString() {
+        return "SmooksProcessor [configUri=" + configUri + "]";
+    }
+
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+}
diff --git 
a/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/converter/ResultConverter.java
 
b/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/converter/ResultConverter.java
new file mode 100644
index 00000000000..74d6d41376b
--- /dev/null
+++ 
b/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/converter/ResultConverter.java
@@ -0,0 +1,133 @@
+/*
+ * 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.smooks.converter;
+
+import java.io.StringReader;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.xml.transform.Result;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.w3c.dom.Node;
+
+import org.apache.camel.Converter;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.spi.TypeConverterRegistry;
+import org.smooks.io.payload.JavaResult;
+import org.smooks.io.payload.StringResult;
+
+/**
+ * ResultConverter converts from different {@link Result} types.
+ *
+ * @author Daniel Bevenius
+ */
+@Converter(generateLoader = true)
+public class ResultConverter {
+    public static final String SMOOKS_RESULT_KEY = "SmooksResultKeys";
+
+    private ResultConverter() {
+    }
+
+    @Converter
+    public static Node toDocument(DOMResult domResult) {
+        return domResult.getNode();
+    }
+
+    @SuppressWarnings("rawtypes")
+    @Converter
+    public static List toList(JavaResult.ResultMap javaResult, Exchange 
exchange) {
+        String resultKey = (String) exchange.getProperty(SMOOKS_RESULT_KEY);
+        if (resultKey != null) {
+            return (List) getResultsFromJavaResult(javaResult, resultKey);
+        } else {
+            return (List) getSingleObjectFromJavaResult(javaResult);
+        }
+    }
+
+    @SuppressWarnings("rawtypes")
+    @Converter
+    public static Integer toInteger(JavaResult.ResultMap result) {
+        return (Integer) getSingleObjectFromJavaResult(result);
+    }
+
+    @SuppressWarnings("rawtypes")
+    @Converter
+    public static Double toDouble(JavaResult.ResultMap result) {
+        return (Double) getSingleObjectFromJavaResult(result);
+    }
+
+    @Converter
+    public static String toString(StringResult result) {
+        return result.getResult();
+    }
+
+
+    @SuppressWarnings("rawtypes")
+    public static Map toMap(JavaResult.ResultMap resultBeans, Exchange 
exchange) {
+        Message outMessage = exchange.getOut();
+        outMessage.setBody(resultBeans);
+
+        @SuppressWarnings("unchecked")
+        Set<Entry<String, Object>> entrySet = resultBeans.entrySet();
+        for (Entry<String, Object> entry : entrySet) {
+            outMessage.setBody(entry.getValue(), entry.getValue().getClass());
+        }
+        return resultBeans;
+    }
+
+    @SuppressWarnings("rawtypes")
+    private static Object getResultsFromJavaResult(JavaResult.ResultMap 
resultMap, String resultKey) {
+        return resultMap.get(resultKey);
+    }
+
+    private static Object 
getSingleObjectFromJavaResult(@SuppressWarnings("rawtypes") 
JavaResult.ResultMap resultMap) {
+        if (resultMap.size() == 1) {
+            return resultMap.values().iterator().next();
+        }
+        return null;
+    }
+
+    @Converter
+    public static StreamSource toStreamSource(StringResult stringResult) {
+        String result = stringResult.getResult();
+        if (result != null) {
+            StringReader stringReader = new StringReader(result);
+            return new StreamSource(stringReader);
+        }
+
+        return null;
+    }
+
+    @SuppressWarnings("rawtypes")
+    @Converter(fallback = true)
+    public static <T> T convertTo(Class<T> type, Exchange exchange, Object 
value, TypeConverterRegistry registry) {
+        if (value instanceof JavaResult.ResultMap) {
+            for (Object mapValue : ((Map) value).values()) {
+                if (type.isInstance(mapValue)) {
+                    return type.cast(mapValue);
+                }
+            }
+        }
+
+        return null;
+    }
+}
diff --git 
a/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/converter/SourceConverter.java
 
b/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/converter/SourceConverter.java
new file mode 100644
index 00000000000..994d249fc3e
--- /dev/null
+++ 
b/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/converter/SourceConverter.java
@@ -0,0 +1,67 @@
+/*
+ * 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.smooks.converter;
+
+import java.io.File;
+import java.io.InputStream;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.camel.Converter;
+import org.apache.camel.component.file.GenericFile;
+import org.smooks.io.payload.JavaResult;
+import org.smooks.io.payload.JavaSource;
+import org.smooks.io.payload.JavaSourceWithoutEventStream;
+
+/**
+ * SourceConverter is a Camel {@link Converter} that converts from different
+ * formats to {@link Source} instances. </p>
+ *
+ * @author Daniel Bevenius
+ */
+@Converter(generateLoader = true)
+public class SourceConverter {
+    private SourceConverter() {
+    }
+
+    @Converter
+    public static JavaSourceWithoutEventStream 
toJavaSourceWithoutEventStream(Object payload) {
+        return new JavaSourceWithoutEventStream(payload);
+    }
+
+    @Converter
+    public static JavaSource toJavaSource(Object payload) {
+        return new JavaSource(payload);
+    }
+
+    @Converter
+    public static Source toStreamSource(InputStream in) {
+        return new StreamSource(in);
+    }
+
+    @Converter
+    public static JavaSource toJavaSource(JavaResult result) {
+        return new JavaSource(result.getResultMap().values());
+    }
+
+    @Converter
+    public static Source toStreamSource(GenericFile<File> genericFile) {
+        return new StreamSource((File) genericFile.getBody());
+    }
+
+}
diff --git 
a/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/Coordinate.java
 
b/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/Coordinate.java
new file mode 100644
index 00000000000..742e96adc33
--- /dev/null
+++ 
b/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/Coordinate.java
@@ -0,0 +1,81 @@
+/*
+ * 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.smooks;
+
+/**
+ * @author <a href="mailto:[email protected]";>[email protected]</a>
+ */
+public class Coordinate {
+
+    private Integer x;
+    private Integer y;
+
+    public Coordinate() {
+    }
+
+    public Coordinate(final int x, final int y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    public Integer getX() {
+        return x;
+    }
+
+    public void setX(Integer x) {
+        this.x = x;
+    }
+
+    public Integer getY() {
+        return y;
+    }
+
+    public void setY(Integer y) {
+        this.y = y;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + x;
+        result = prime * result + y;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        Coordinate other = (Coordinate) obj;
+        if (!x.equals(other.x))
+            return false;
+        if (!y.equals(other.y))
+            return false;
+        return true;
+    }
+
+    public String toString() {
+        return "Coordinate [x=" + x + ", y=" + y + "]";
+    }
+
+
+}
diff --git 
a/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/SmooksComponentTest.java
 
b/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/SmooksComponentTest.java
new file mode 100644
index 00000000000..ed87219c5c2
--- /dev/null
+++ 
b/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/SmooksComponentTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.smooks;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+import org.smooks.support.StreamUtils;
+import org.xmlunit.builder.DiffBuilder;
+
+import static org.apache.camel.component.mock.MockEndpoint.assertIsSatisfied;
+import static org.apache.camel.test.junit5.TestSupport.assertIsInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+/**
+ * Unit test for {@link SmooksComponent}.
+ *
+ * @author Christian Mueller
+ * @author Daniel Bevenius
+ */
+public class SmooksComponentTest extends CamelTestSupport {
+    @EndpointInject(value = "mock:result")
+    private MockEndpoint mockEndpoint;
+
+    @Test
+    public void unmarshalEdi() throws Exception {
+        mockEndpoint.expectedMessageCount(1);
+        assertIsSatisfied(mockEndpoint);
+
+        Exchange exchange = mockEndpoint.assertExchangeReceived(0);
+
+        assertIsInstanceOf(Document.class, exchange.getIn().getBody());
+        
assertFalse(DiffBuilder.compare(StreamUtils.readStreamAsString(getClass().getResourceAsStream("/xml/expected-order.xml"),
 "UTF-8")).
+                withTest(exchange.getIn().getBody(String.class)).
+                ignoreComments().
+                ignoreWhitespace().
+                build().
+                hasDifferences());
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            public void configure() {
+                from("file://src/test/resources/data?noop=true")
+                        .to("smooks://edi-to-xml-smooks-config.xml")
+                        .convertBodyTo(Node.class).to("mock:result");
+            }
+        };
+    }
+}
+
diff --git 
a/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/SmooksProcessorTest.java
 
b/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/SmooksProcessorTest.java
new file mode 100644
index 00000000000..5cf61198854
--- /dev/null
+++ 
b/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/SmooksProcessorTest.java
@@ -0,0 +1,322 @@
+/*
+ * 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.smooks;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.util.Map;
+
+import jakarta.activation.DataHandler;
+import jakarta.activation.DataSource;
+
+import javax.xml.transform.stream.StreamSource;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.attachment.AttachmentMessage;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.support.DefaultExchange;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+import org.smooks.Smooks;
+import org.smooks.cartridges.javabean.Bean;
+import org.smooks.cartridges.javabean.Value;
+import org.smooks.io.payload.Exports;
+import org.smooks.io.payload.JavaResult;
+import org.smooks.io.payload.StringResult;
+import org.smooks.io.payload.StringSource;
+import org.smooks.support.StreamUtils;
+import org.xmlunit.builder.DiffBuilder;
+
+import static org.apache.camel.component.mock.MockEndpoint.assertIsSatisfied;
+import static org.apache.camel.test.junit5.TestSupport.assertIsInstanceOf;
+import static org.apache.camel.test.junit5.TestSupport.deleteDirectory;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Unit test for {@link SmooksProcessor}.
+ *
+ * @author Christian Mueller
+ * @author Daniel Bevenius
+ */
+public class SmooksProcessorTest extends CamelTestSupport {
+    @EndpointInject(value = "mock:result")
+    private MockEndpoint result;
+
+    @Override
+    protected boolean useJmx() {
+        return true;
+    }
+
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+    private void assertOneProcessedMessage() throws Exception {
+        result.expectedMessageCount(1);
+        template.sendBody("direct://input", getOrderEdi());
+
+        assertIsSatisfied();
+
+        Exchange exchange = result.assertExchangeReceived(0);
+        assertIsInstanceOf(Document.class, exchange.getIn().getBody());
+        
assertFalse(DiffBuilder.compare(getExpectedOrderXml()).withTest(exchange.getIn().getBody(String.class)).
+                ignoreComments().
+                ignoreWhitespace().
+                build().
+                hasDifferences());
+    }
+
+    @Test
+    public void testProcess() throws Exception {
+        context.addRoutes(createEdiToXmlRouteBuilder());
+        context.start();
+        assertOneProcessedMessage();
+    }
+
+    @Test
+    public void testProcessGivenAttachment() throws Exception {
+        context.addRoutes(createEdiToXmlRouteBuilder());
+        context.start();
+        final DefaultExchange exchange = new DefaultExchange(context);
+        final String attachmentContent = "A dummy attachment";
+        final String attachmentId = "testAttachment";
+        addAttachment(attachmentContent, attachmentId, exchange);
+        exchange.getIn().setBody(getOrderEdi());
+
+        template.send("direct://input", exchange);
+
+        final DataHandler datahandler = 
result.assertExchangeReceived(0).getIn(AttachmentMessage.class).getAttachment(attachmentId);
+        assertThat(datahandler, is(notNullValue()));
+        assertThat(datahandler.getContent(), 
is(instanceOf(ByteArrayInputStream.class)));
+
+        final String actualAttachmentContent = 
getAttachmentContent(datahandler);
+        assertThat(actualAttachmentContent, is(equalTo(attachmentContent)));
+    }
+
+    @Test
+    public void testProcessCreatesSmooksReport() throws Exception {
+        context.addRoutes(createEdiToXmlRouteBuilder());
+        context.start();
+        assertOneProcessedMessage();
+
+        File report = new File("target/smooks-report.html");
+        report.deleteOnExit();
+        assertTrue(report.exists(), "Smooks report was not generated.");
+    }
+
+    @Test
+    public void testProcessGivenCamelCharsetNameProperty() throws Exception {
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() {
+                Smooks smooks = new Smooks().setExports(new 
Exports(JavaResult.class));
+                from("direct:a")
+                        .process(new SmooksProcessor(smooks, context)
+                                .addVisitor(new Value("customer", 
"/order/header/customer", String.class, 
smooks.getApplicationContext().getRegistry())));
+            }
+
+        });
+        enableJMX();
+        context.start();
+        Exchange response = template.request("direct:a", new Processor() {
+            public void process(Exchange exchange) {
+                InputStream in = 
this.getClass().getResourceAsStream("/EBCDIC-input-message.txt");
+                exchange.getIn().setBody(new StreamSource(in));
+                exchange.setProperty("CamelCharsetName", "Cp1047");
+            }
+        });
+        assertEquals("Joe", response.getMessage().getBody(String.class));
+    }
+
+    @Test
+    public void testProcessGivenFileWhenSmooksExportIsStringResult() throws 
Exception {
+        deleteDirectory("target/smooks");
+        context.addRoutes(new RouteBuilder() {
+            public void configure() {
+                from("file://target/smooks").
+                        process(new SmooksProcessor(new 
Smooks().setExports(new Exports(StringResult.class)), context)).
+                        to("mock:a");
+            }
+        });
+        context.start();
+        template.sendBody("file://target/smooks", "<blah />");
+
+        MockEndpoint mockEndpoint = getMockEndpoint("mock:a");
+        mockEndpoint.expectedMessageCount(1);
+
+        assertIsSatisfied(mockEndpoint);
+
+        assertEquals("<blah/>", 
mockEndpoint.getExchanges().get(0).getIn().getBody(String.class));
+    }
+
+    @Test
+    public void 
testProcessWhenSmooksExportIsJavaResultAndBodyIsVisitedByJavaBeanValue() throws 
Exception {
+        Smooks smooks = new Smooks().setExports(new Exports(JavaResult.class));
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:a")
+                        .process(new SmooksProcessor(smooks, context)
+                                .addVisitor(new Value("x", "/coord/@x", 
Integer.class, smooks.getApplicationContext().getRegistry())));
+            }
+        });
+        enableJMX();
+        context.start();
+        Exchange response = template.request("direct:a", exchange -> 
exchange.getIn().setBody(new StringSource("<coord x='1234' />")));
+        assertEquals(1234, response.getMessage().getBody(Integer.class));
+    }
+
+    @Test
+    public void 
testProcessWhenSmooksExportIsJavaResultAndBodyIsVisitedByMultipleJavaBeanValues()
 throws Exception {
+        Smooks smooks = new Smooks().setExports(new Exports(JavaResult.class));
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:b").process(new SmooksProcessor(smooks, context).
+                        addVisitor(new Value("x", "/coord/@x", Integer.class, 
smooks.getApplicationContext().getRegistry())).
+                        addVisitor(new Value("y", "/coord/@y", Double.class, 
smooks.getApplicationContext().getRegistry())));
+            }
+        });
+        context.start();
+        Exchange response = template.request("direct:b", exchange -> 
exchange.getIn().setBody(new StringSource("<coord x='1234' y='98765.76' />")));
+        Map javaResult = response.getOut().getBody(Map.class);
+        Integer x = (Integer) javaResult.get("x");
+        assertEquals(1234, (int) x);
+        Double y = (Double) javaResult.get("y");
+        assertEquals(98765.76D, y, 0.01D);
+    }
+
+    @Test
+    public void 
testProcessWhenSmooksExportIsJavaResultAndBodyIsVisitedByBean() throws 
Exception {
+        Smooks smooks = new Smooks().setExports(new Exports(JavaResult.class));
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:c").process(new SmooksProcessor(smooks, context).
+                        addVisitor(new Bean(Coordinate.class, "coordinate", 
smooks.getApplicationContext().getRegistry()).
+                                bindTo("x", "/coord/@x").
+                                bindTo("y", "/coord/@y")));
+            }
+        });
+        context.start();
+        Exchange response = template.request("direct:c", exchange -> 
exchange.getIn().setBody(new StringSource("<coord x='111' y='222' />")));
+
+        Coordinate coord = response.getMessage().getBody(Coordinate.class);
+
+        assertEquals((Integer) 111, coord.getX());
+        assertEquals((Integer) 222, coord.getY());
+    }
+
+    @Test
+    public void testProcessWhenSmooksExportIsStringResult() throws Exception {
+        context.addRoutes(new RouteBuilder() {
+            public void configure() {
+                from("direct:a")
+                        .process(new SmooksProcessor(new 
Smooks().setExports(new Exports(StringResult.class)), context))
+                        .to("direct:b");
+
+                from("direct:b").convertBodyTo(String.class).process(new 
DirectBProcessor());
+            }
+        });
+        context.start();
+        template.request("direct:a", exchange -> exchange.getIn().setBody(new 
StringSource("<x/>")));
+
+        assertEquals("<x/>", DirectBProcessor.inMessage);
+    }
+
+    private static class DirectBProcessor implements Processor {
+        private static String inMessage;
+
+        public void process(Exchange exchange) {
+            inMessage = (String) exchange.getIn().getBody();
+        }
+    }
+
+    private void addAttachment(final String attachment, final String id, final 
Exchange exchange) {
+        final DataSource ds = new StringDataSource(attachment);
+        final DataHandler dataHandler = new DataHandler(ds);
+        exchange.getIn(AttachmentMessage.class).addAttachment(id, dataHandler);
+    }
+
+    private String getAttachmentContent(final DataHandler datahandler) throws 
IOException {
+        final ByteArrayInputStream bs = (ByteArrayInputStream) 
datahandler.getContent();
+        return new String(StreamUtils.readStream(bs));
+    }
+
+    protected RouteBuilder createEdiToXmlRouteBuilder() {
+        return new RouteBuilder() {
+            public void configure() throws Exception {
+                SmooksProcessor processor = new 
SmooksProcessor("edi-to-xml-smooks-config.xml", context);
+                processor.setReportPath("target/smooks-report.html");
+
+                
from("direct:input").process(processor).convertBodyTo(Node.class).to("mock:result");
+            }
+        };
+    }
+
+    private String getExpectedOrderXml() throws IOException {
+        return StreamUtils.readStream(new 
InputStreamReader(getClass().getResourceAsStream("/xml/expected-order.xml")));
+    }
+
+    private String getOrderEdi() throws IOException {
+        return StreamUtils.readStream(new 
InputStreamReader(getClass().getResourceAsStream("/data/order.txt")));
+    }
+
+    private static class StringDataSource implements DataSource {
+        private final String string;
+
+        private StringDataSource(final String string) {
+            this.string = string;
+
+        }
+
+        public String getContentType() {
+            return "text/plain";
+        }
+
+        public InputStream getInputStream() throws IOException {
+            return new ByteArrayInputStream(string.getBytes());
+        }
+
+        public String getName() {
+            return "StringDataSource";
+        }
+
+        public OutputStream getOutputStream() throws IOException {
+            throw new IOException("Method 'getOutputStream' is not 
implemented");
+        }
+
+    }
+}
diff --git 
a/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/converter/ResultConverterTest.java
 
b/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/converter/ResultConverterTest.java
new file mode 100644
index 00000000000..408da4585d8
--- /dev/null
+++ 
b/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/converter/ResultConverterTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.smooks.converter;
+
+import java.io.BufferedReader;
+import java.io.StringWriter;
+
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.camel.TypeConverter;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.smooks.io.payload.StringResult;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Unit test for {@link ResultConverter}.
+ *
+ * @author Daniel Bevenius
+ */
+public class ResultConverterTest {
+    private TypeConverter typeConverter;
+
+    @BeforeEach
+    public void beforeEach() {
+        DefaultCamelContext camelContext = new DefaultCamelContext();
+        typeConverter = camelContext.getTypeConverter();
+    }
+
+    @Test
+    public void convertStringResultToStreamSource() throws Exception {
+        StringResult stringResult = createStringResult("Bajja");
+
+        StreamSource streamSource = 
typeConverter.convertTo(StreamSource.class, stringResult);
+
+        BufferedReader reader = new BufferedReader(streamSource.getReader());
+        assertEquals("Bajja", reader.readLine());
+    }
+
+    private StringResult createStringResult(String string) {
+        StringWriter stringWriter = new StringWriter();
+        stringWriter.write(string);
+        StringResult stringResult = new StringResult();
+        stringResult.setWriter(stringWriter);
+        return stringResult;
+    }
+
+}
diff --git 
a/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/converter/SourceConverterTest.java
 
b/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/converter/SourceConverterTest.java
new file mode 100644
index 00000000000..92396a6ab8a
--- /dev/null
+++ 
b/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/converter/SourceConverterTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.smooks.converter;
+
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.TypeConverter;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.smooks.io.payload.JavaSourceWithoutEventStream;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Unit test for {@link SourceConverter}. </p>
+ *
+ * @author Daniel Bevenius
+ */
+public class SourceConverterTest {
+    private TypeConverter typeConverter;
+
+    @BeforeEach
+    public void beforeEach() {
+        CamelContext camelContext = new DefaultCamelContext();
+        typeConverter = camelContext.getTypeConverter();
+    }
+
+    @Test
+    public void convertStringToJavaSourceWithoutEventStream() {
+        final String payload = "dummyPayload";
+        final JavaSourceWithoutEventStream javaSource = 
typeConverter.convertTo(JavaSourceWithoutEventStream.class, payload);
+        final Map<String, Object> beans = javaSource.getBeans();
+        final String actualPayload = (String) beans.get("string");
+
+        assertThat(payload, is(actualPayload));
+    }
+}
diff --git 
a/components/camel-smooks/src/test/resources/EBCDIC-input-message.txt 
b/components/camel-smooks/src/test/resources/EBCDIC-input-message.txt
new file mode 100644
index 00000000000..bd37c1664e6
--- /dev/null
+++ b/components/camel-smooks/src/test/resources/EBCDIC-input-message.txt
@@ -0,0 +1 @@
+L�����n@@@@L������n@@@@@@@@L����n慄@Ֆ�@��@��z��z��@���@����La����n@@@@@@@@L��������@������~������nі�La��������n@@@@La������n@@@@L�����`�����n@@@@@@@@L�����`����n@@@@@@@@@@@@L�������n�La�������n@@@@@@@@@@@@L��������n�La��������n@@@@@@@@@@@@L�����n�K��La�����n@@@@@@@@La�����`����n@@@@@@@@L�����`����n@@@@@@@@@@@@L�������n�La�������n@@@@@@@@@@@@L��������n�La��������n@@@@@@@@@@@@L�����n�K��La�����n@@@@@@@@La�����`����n@@@@La�����`�����nLa�����n
\ No newline at end of file
diff --git a/components/camel-smooks/src/test/resources/data/order.txt 
b/components/camel-smooks/src/test/resources/data/order.txt
new file mode 100644
index 00000000000..060c2422ac8
--- /dev/null
+++ b/components/camel-smooks/src/test/resources/data/order.txt
@@ -0,0 +1,4 @@
+HDR*1*0*59.97*64.92*4.95*Wed Nov 15 13:45:28 EST 2006
+CUS*user1*Harry^Fletcher*SD
+ORD*1*1*364*The 40-Year-Old Virgin*29.98
+ORD*2*1*299*Pulp Fiction*29.99
diff --git 
a/components/camel-smooks/src/test/resources/edi-mapping-model.dfdl.xsd 
b/components/camel-smooks/src/test/resources/edi-mapping-model.dfdl.xsd
new file mode 100644
index 00000000000..27411ddee31
--- /dev/null
+++ b/components/camel-smooks/src/test/resources/edi-mapping-model.dfdl.xsd
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+
+    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.
+
+-->
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema";
+            xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"; 
xmlns:ibmEdiFmt="http://www.ibm.com/dfdl/EDI/Format";>
+
+    <xsd:import namespace="http://www.ibm.com/dfdl/EDI/Format";
+                schemaLocation="/EDIFACT-Common/IBM_EDI_Format.dfdl.xsd"/>
+
+    <xsd:annotation>
+        <xsd:appinfo source="http://www.ogf.org/dfdl/";>
+            <dfdl:format ref="ibmEdiFmt:EDIFormat"/>
+        </xsd:appinfo>
+    </xsd:annotation>
+
+    <xsd:element name="Order">
+        <xsd:complexType>
+            <xsd:sequence>
+                <xsd:sequence dfdl:initiatedContent="yes">
+                    <xsd:element dfdl:initiator="HDR" 
dfdl:ref="ibmEdiFmt:EDISegmentFormat" name="header">
+                        <xsd:complexType>
+                            <xsd:sequence 
dfdl:ref="ibmEdiFmt:EDISegmentSequenceFormat">
+                                <xsd:element name="order-id" 
type="xsd:string"/>
+                                <xsd:element name="status-code" 
type="xsd:string"/>
+                                <xsd:element name="net-amount" 
type="xsd:string"/>
+                                <xsd:element name="total-amount" 
type="xsd:string"/>
+                                <xsd:element name="tax" type="xsd:string"/>
+                                <xsd:element name="date" type="xsd:string"/>
+                            </xsd:sequence>
+                        </xsd:complexType>
+                    </xsd:element>
+                    <xsd:element dfdl:initiator="CUS" 
dfdl:ref="ibmEdiFmt:EDISegmentFormat" name="customer-details">
+                        <xsd:complexType>
+                            <xsd:sequence 
dfdl:ref="ibmEdiFmt:EDISegmentSequenceFormat">
+                                <xsd:element name="username" 
type="xsd:string"/>
+                                <xsd:element name="name">
+                                    <xsd:complexType>
+                                        <xsd:sequence 
dfdl:ref="ibmEdiFmt:EDICompositeSequenceFormat">
+                                            <xsd:element name="firstname" 
type="xsd:string"/>
+                                            <xsd:element name="lastname" 
type="xsd:string"/>
+                                        </xsd:sequence>
+                                    </xsd:complexType>
+                                </xsd:element>
+                                <xsd:element name="state" type="xsd:string"/>
+                            </xsd:sequence>
+                        </xsd:complexType>
+                    </xsd:element>
+                    <xsd:element dfdl:initiator="ORD" 
dfdl:ref="ibmEdiFmt:EDISegmentFormat" name="order-item" maxOccurs="unbounded">
+                        <xsd:complexType>
+                            <xsd:sequence 
dfdl:ref="ibmEdiFmt:EDISegmentSequenceFormat">
+                                <xsd:element name="position" 
type="xsd:string"/>
+                                <xsd:element name="quantity" 
type="xsd:string"/>
+                                <xsd:element name="product-id" 
type="xsd:string"/>
+                                <xsd:element name="title" type="xsd:string"/>
+                                <xsd:element name="price" type="xsd:string"/>
+                            </xsd:sequence>
+                        </xsd:complexType>
+                    </xsd:element>
+                </xsd:sequence>
+            </xsd:sequence>
+        </xsd:complexType>
+    </xsd:element>
+</xsd:schema>
\ No newline at end of file
diff --git 
a/components/camel-smooks/src/test/resources/edi-to-xml-smooks-config.xml 
b/components/camel-smooks/src/test/resources/edi-to-xml-smooks-config.xml
new file mode 100644
index 00000000000..82a5641a4e2
--- /dev/null
+++ b/components/camel-smooks/src/test/resources/edi-to-xml-smooks-config.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!--
+
+    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.
+
+-->
+<smooks-resource-list
+        xmlns="https://www.smooks.org/xsd/smooks-2.0.xsd";
+        xmlns:edi="https://www.smooks.org/xsd/smooks/edi-2.0.xsd";
+        xmlns:core="https://www.smooks.org/xsd/smooks/smooks-core-1.6.xsd";>
+
+    <!--
+    Configure the EDI Reader to process the message stream into a stream of 
SAX events.
+    -->
+    <edi:parser schemaUri="/edi-mapping-model.dfdl.xsd" 
segmentTerminator="%NL;" dataElementSeparator="*"
+                compositeDataElementSeparator="^"/>
+
+    <core:exports>
+        <core:result type="javax.xml.transform.dom.DOMResult"/>
+    </core:exports>
+
+</smooks-resource-list>
diff --git a/components/camel-smooks/src/test/resources/xml/expected-order.xml 
b/components/camel-smooks/src/test/resources/xml/expected-order.xml
new file mode 100644
index 00000000000..86521d8d1e9
--- /dev/null
+++ b/components/camel-smooks/src/test/resources/xml/expected-order.xml
@@ -0,0 +1,51 @@
+<?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.
+
+-->
+<Order>
+    <header>
+        <order-id>1</order-id>
+        <status-code>0</status-code>
+        <net-amount>59.97</net-amount>
+        <total-amount>64.92</total-amount>
+        <tax>4.95</tax>
+        <date>Wed Nov 15 13:45:28 EST 2006</date>
+    </header>
+    <customer-details>
+        <username>user1</username>
+        <name>
+            <firstname>Harry</firstname>
+            <lastname>Fletcher</lastname>
+        </name>
+        <state>SD</state>
+    </customer-details>
+    <order-item>
+        <position>1</position>
+        <quantity>1</quantity>
+        <product-id>364</product-id>
+        <title>The 40-Year-Old Virgin</title>
+        <price>29.98</price>
+    </order-item>
+    <order-item>
+        <position>2</position>
+        <quantity>1</quantity>
+        <product-id>299</product-id>
+        <title>Pulp Fiction</title>
+        <price>29.99</price>
+    </order-item>
+</Order>
diff --git a/components/pom.xml b/components/pom.xml
index 9ff2502109d..a6e903a87e2 100644
--- a/components/pom.xml
+++ b/components/pom.xml
@@ -272,6 +272,7 @@
         <module>camel-sjms</module>
         <module>camel-slack</module>
         <module>camel-smb</module>
+        <module>camel-smooks</module>
         <module>camel-smpp</module>
         <module>camel-snakeyaml</module>
         <module>camel-snmp</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 eda05e1c4c1..e321b253135 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
@@ -285,6 +285,7 @@ sjms
 sjms2
 slack
 smb
+smooks
 smpp
 smpps
 smtp
diff --git a/docs/components/modules/ROOT/nav.adoc 
b/docs/components/modules/ROOT/nav.adoc
index bbe5ed8bdc5..8b249c0f7e6 100644
--- a/docs/components/modules/ROOT/nav.adoc
+++ b/docs/components/modules/ROOT/nav.adoc
@@ -291,6 +291,7 @@
 ** xref:sjms2-component.adoc[Simple JMS2]
 ** xref:slack-component.adoc[Slack]
 ** xref:smb-component.adoc[SMB]
+** xref:smooks-component.adoc[Smooks]
 ** xref:smpp-component.adoc[SMPP]
 ** xref:snmp-component.adoc[SNMP]
 ** xref:splunk-component.adoc[Splunk]
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 95f70147e4b..5f699878c50 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
@@ -3855,6 +3855,20 @@ public interface ComponentsBuilderFactory {
     static SmbComponentBuilderFactory.SmbComponentBuilder smb() {
         return SmbComponentBuilderFactory.smb();
     }
+    /**
+     * Smooks (camel-smooks)
+     * Applies fragment-based processing in Smooks to perform a variety of
+     * operations like transformation.
+     * 
+     * Category: file
+     * Since: 4.7
+     * Maven coordinates: org.apache.camel:camel-smooks
+     * 
+     * @return the dsl builder
+     */
+    static SmooksComponentBuilderFactory.SmooksComponentBuilder smooks() {
+        return SmooksComponentBuilderFactory.smooks();
+    }
     /**
      * SMPP (camel-smpp)
      * Send and receive SMS messages using a SMSC (Short Message Service
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 e44d78fd785..553cf1630f3 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
@@ -302,6 +302,7 @@ public interface EndpointBuilderFactory
             
org.apache.camel.builder.endpoint.dsl.SjmsEndpointBuilderFactory.SjmsBuilders,
             
org.apache.camel.builder.endpoint.dsl.SlackEndpointBuilderFactory.SlackBuilders,
             
org.apache.camel.builder.endpoint.dsl.SmbEndpointBuilderFactory.SmbBuilders,
+            
org.apache.camel.builder.endpoint.dsl.SmooksEndpointBuilderFactory.SmooksBuilders,
             
org.apache.camel.builder.endpoint.dsl.SmppEndpointBuilderFactory.SmppBuilders,
             
org.apache.camel.builder.endpoint.dsl.SnmpEndpointBuilderFactory.SnmpBuilders,
             
org.apache.camel.builder.endpoint.dsl.Sns2EndpointBuilderFactory.Sns2Builders,
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 00484b3cc26..b91d8600978 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
@@ -299,6 +299,7 @@ public interface EndpointBuilders
             org.apache.camel.builder.endpoint.dsl.SjmsEndpointBuilderFactory,
             org.apache.camel.builder.endpoint.dsl.SlackEndpointBuilderFactory,
             org.apache.camel.builder.endpoint.dsl.SmbEndpointBuilderFactory,
+            org.apache.camel.builder.endpoint.dsl.SmooksEndpointBuilderFactory,
             org.apache.camel.builder.endpoint.dsl.SmppEndpointBuilderFactory,
             org.apache.camel.builder.endpoint.dsl.SnmpEndpointBuilderFactory,
             org.apache.camel.builder.endpoint.dsl.Sns2EndpointBuilderFactory,
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 59f2e70906f..dad93cb86c3 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
@@ -13035,6 +13035,48 @@ public class StaticEndpointBuilders {
     public static SmbEndpointBuilderFactory.SmbEndpointBuilder smb(String 
componentName, String path) {
         return SmbEndpointBuilderFactory.endpointBuilder(componentName, path);
     }
+    /**
+     * Smooks (camel-smooks)
+     * Applies fragment-based processing in Smooks to perform a variety of
+     * operations like transformation.
+     * 
+     * Category: file
+     * Since: 4.7
+     * Maven coordinates: org.apache.camel:camel-smooks
+     * 
+     * Syntax: <code>smooks://smooks-config-path</code>
+     * 
+     * Path parameter: database (required)
+     * database name
+     * 
+     * @param path smooks-config-path
+     * @return the dsl builder
+     */
+    public static SmooksEndpointBuilderFactory.SmooksEndpointBuilder 
smooks(String path) {
+        return smooks("smooks", path);
+    }
+    /**
+     * Smooks (camel-smooks)
+     * Applies fragment-based processing in Smooks to perform a variety of
+     * operations like transformation.
+     * 
+     * Category: file
+     * Since: 4.7
+     * Maven coordinates: org.apache.camel:camel-smooks
+     * 
+     * Syntax: <code>smooks://smooks-config-path</code>
+     * 
+     * Path parameter: database (required)
+     * database name
+     * 
+     * @param componentName to use a custom component name for the endpoint
+     * instead of the default name
+     * @param path smooks-config-path
+     * @return the dsl builder
+     */
+    public static SmooksEndpointBuilderFactory.SmooksEndpointBuilder 
smooks(String componentName, String path) {
+        return SmooksEndpointBuilderFactory.endpointBuilder(componentName, 
path);
+    }
     /**
      * SMPP (camel-smpp)
      * Send and receive SMS messages using a SMSC (Short Message Service
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 9d682b56ca3..138872650e2 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
@@ -295,6 +295,7 @@ org.apache.camel.component.sjms.SjmsComponent=camel:sjms
 org.apache.camel.component.sjms2.Sjms2Component=camel:sjms2
 org.apache.camel.component.slack.SlackComponent=camel:slack
 org.apache.camel.component.smb.SmbComponent=camel:smb
+org.apache.camel.component.smooks.SmooksComponent=camel:smooks
 org.apache.camel.component.smpp.SmppComponent=camel:smpp
 org.apache.camel.component.snmp.SnmpComponent=camel:snmp
 org.apache.camel.component.splunk.SplunkComponent=camel:splunk
diff --git a/parent/pom.xml b/parent/pom.xml
index c7e4d872490..00df68bb3d5 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -2209,6 +2209,11 @@
                 <artifactId>camel-smb</artifactId>
                 <version>${project.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.apache.camel</groupId>
+                <artifactId>camel-smooks</artifactId>
+                <version>${project.version}</version>
+            </dependency>
             <dependency>
                 <groupId>org.apache.camel</groupId>
                 <artifactId>camel-smpp</artifactId>

Reply via email to