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("direct:a").to("smooks://edi-to-xml-smooks-config.xml") + * </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>
