You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ac...@apache.org on 2026/01/27 12:56:46 UTC
(camel) 01/02: Polly
This is an automated email from the ASF dual-hosted git repository.
acosentino pushed a commit to branch polly
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 4295ff4544b73a613160b291c532ff6d6f7342fd
Author: Andrea Cosentino <an...@gmail.com>
AuthorDate: Mon Jan 19 12:15:30 2026 +0100
Polly
Signed-off-by: Andrea Cosentino <an...@gmail.com>
---
catalog/camel-allcomponents/pom.xml | 5 +
components/camel-aws/camel-aws2-polly/pom.xml | 83 +++
.../aws2/polly/Polly2ComponentConfigurer.java | 219 ++++++++
.../aws2/polly/Polly2EndpointConfigurer.java | 191 +++++++
.../aws2/polly/Polly2EndpointUriFactory.java | 99 ++++
.../camel/component/aws2/polly/aws2-polly.json | 103 ++++
.../services/org/apache/camel/component.properties | 7 +
.../services/org/apache/camel/component/aws2-polly | 2 +
.../apache/camel/configurer/aws2-polly-component | 2 +
.../apache/camel/configurer/aws2-polly-endpoint | 2 +
.../apache/camel/urifactory/aws2-polly-endpoint | 2 +
.../src/main/docs/aws2-polly-component.adoc | 171 ++++++
.../component/aws2/polly/Polly2Component.java | 72 +++
.../component/aws2/polly/Polly2Configuration.java | 368 ++++++++++++
.../component/aws2/polly/Polly2Constants.java | 61 ++
.../camel/component/aws2/polly/Polly2Endpoint.java | 108 ++++
.../component/aws2/polly/Polly2Operations.java | 30 +
.../camel/component/aws2/polly/Polly2Producer.java | 624 +++++++++++++++++++++
.../aws2/polly/Polly2ProducerHealthCheck.java | 71 +++
.../aws2/polly/client/Polly2ClientFactory.java | 42 ++
.../aws2/polly/AmazonPollyClientMock.java | 187 ++++++
.../aws2/polly/Polly2ClientFactoryTest.java | 50 ++
.../component/aws2/polly/Polly2ProducerTest.java | 282 ++++++++++
components/camel-aws/pom.xml | 1 +
parent/pom.xml | 5 +
.../apache/camel/maven/packaging/MojoHelper.java | 2 +-
26 files changed, 2788 insertions(+), 1 deletion(-)
diff --git a/catalog/camel-allcomponents/pom.xml b/catalog/camel-allcomponents/pom.xml
index 83fff97272da..3becdd4fdf14 100644
--- a/catalog/camel-allcomponents/pom.xml
+++ b/catalog/camel-allcomponents/pom.xml
@@ -227,6 +227,11 @@
<artifactId>camel-aws2-msk</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-aws2-polly</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-aws2-redshift</artifactId>
diff --git a/components/camel-aws/camel-aws2-polly/pom.xml b/components/camel-aws/camel-aws2-polly/pom.xml
new file mode 100644
index 000000000000..961fb42357d6
--- /dev/null
+++ b/components/camel-aws/camel-aws2-polly/pom.xml
@@ -0,0 +1,83 @@
+<?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>camel-aws-parent</artifactId>
+ <version>4.18.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>camel-aws2-polly</artifactId>
+ <packaging>jar</packaging>
+
+ <name>Camel :: AWS2 Polly</name>
+ <description>Synthesize speech using AWS Polly Service</description>
+
+ <properties>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-support</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-aws-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>software.amazon.awssdk</groupId>
+ <artifactId>polly</artifactId>
+ <version>${aws-java-sdk2-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>software.amazon.awssdk</groupId>
+ <artifactId>sts</artifactId>
+ <version>${aws-java-sdk2-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>software.amazon.awssdk</groupId>
+ <artifactId>apache-client</artifactId>
+ <version>${aws-java-sdk2-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-health</artifactId>
+ </dependency>
+
+ <!-- for testing -->
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-test-spring-junit5</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <!-- test infra -->
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-test-infra-aws-v2</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/components/camel-aws/camel-aws2-polly/src/generated/java/org/apache/camel/component/aws2/polly/Polly2ComponentConfigurer.java b/components/camel-aws/camel-aws2-polly/src/generated/java/org/apache/camel/component/aws2/polly/Polly2ComponentConfigurer.java
new file mode 100644
index 000000000000..e6e5c007b225
--- /dev/null
+++ b/components/camel-aws/camel-aws2-polly/src/generated/java/org/apache/camel/component/aws2/polly/Polly2ComponentConfigurer.java
@@ -0,0 +1,219 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.aws2.polly;
+
+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 Polly2ComponentConfigurer extends PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+ private org.apache.camel.component.aws2.polly.Polly2Configuration getOrCreateConfiguration(Polly2Component target) {
+ if (target.getConfiguration() == null) {
+ target.setConfiguration(new org.apache.camel.component.aws2.polly.Polly2Configuration());
+ }
+ return target.getConfiguration();
+ }
+
+ @Override
+ public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) {
+ Polly2Component target = (Polly2Component) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "accesskey":
+ case "accessKey": getOrCreateConfiguration(target).setAccessKey(property(camelContext, java.lang.String.class, value)); return true;
+ case "autowiredenabled":
+ case "autowiredEnabled": target.setAutowiredEnabled(property(camelContext, boolean.class, value)); return true;
+ case "configuration": target.setConfiguration(property(camelContext, org.apache.camel.component.aws2.polly.Polly2Configuration.class, value)); return true;
+ case "engine": getOrCreateConfiguration(target).setEngine(property(camelContext, software.amazon.awssdk.services.polly.model.Engine.class, value)); return true;
+ case "healthcheckconsumerenabled":
+ case "healthCheckConsumerEnabled": target.setHealthCheckConsumerEnabled(property(camelContext, boolean.class, value)); return true;
+ case "healthcheckproducerenabled":
+ case "healthCheckProducerEnabled": target.setHealthCheckProducerEnabled(property(camelContext, boolean.class, value)); return true;
+ case "languagecode":
+ case "languageCode": getOrCreateConfiguration(target).setLanguageCode(property(camelContext, java.lang.String.class, value)); return true;
+ case "lazystartproducer":
+ case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
+ case "lexiconnames":
+ case "lexiconNames": getOrCreateConfiguration(target).setLexiconNames(property(camelContext, java.lang.String.class, value)); return true;
+ case "operation": getOrCreateConfiguration(target).setOperation(property(camelContext, org.apache.camel.component.aws2.polly.Polly2Operations.class, value)); return true;
+ case "outputformat":
+ case "outputFormat": getOrCreateConfiguration(target).setOutputFormat(property(camelContext, software.amazon.awssdk.services.polly.model.OutputFormat.class, value)); return true;
+ case "overrideendpoint":
+ case "overrideEndpoint": getOrCreateConfiguration(target).setOverrideEndpoint(property(camelContext, boolean.class, value)); return true;
+ case "pojorequest":
+ case "pojoRequest": getOrCreateConfiguration(target).setPojoRequest(property(camelContext, boolean.class, value)); return true;
+ case "pollyclient":
+ case "pollyClient": getOrCreateConfiguration(target).setPollyClient(property(camelContext, software.amazon.awssdk.services.polly.PollyClient.class, value)); return true;
+ case "profilecredentialsname":
+ case "profileCredentialsName": getOrCreateConfiguration(target).setProfileCredentialsName(property(camelContext, java.lang.String.class, value)); return true;
+ case "proxyhost":
+ case "proxyHost": getOrCreateConfiguration(target).setProxyHost(property(camelContext, java.lang.String.class, value)); return true;
+ case "proxyport":
+ case "proxyPort": getOrCreateConfiguration(target).setProxyPort(property(camelContext, java.lang.Integer.class, value)); return true;
+ case "proxyprotocol":
+ case "proxyProtocol": getOrCreateConfiguration(target).setProxyProtocol(property(camelContext, software.amazon.awssdk.core.Protocol.class, value)); return true;
+ case "region": getOrCreateConfiguration(target).setRegion(property(camelContext, java.lang.String.class, value)); return true;
+ case "samplerate":
+ case "sampleRate": getOrCreateConfiguration(target).setSampleRate(property(camelContext, java.lang.String.class, value)); return true;
+ case "secretkey":
+ case "secretKey": getOrCreateConfiguration(target).setSecretKey(property(camelContext, java.lang.String.class, value)); return true;
+ case "sessiontoken":
+ case "sessionToken": getOrCreateConfiguration(target).setSessionToken(property(camelContext, java.lang.String.class, value)); return true;
+ case "texttype":
+ case "textType": getOrCreateConfiguration(target).setTextType(property(camelContext, software.amazon.awssdk.services.polly.model.TextType.class, value)); return true;
+ case "trustallcertificates":
+ case "trustAllCertificates": getOrCreateConfiguration(target).setTrustAllCertificates(property(camelContext, boolean.class, value)); return true;
+ case "uriendpointoverride":
+ case "uriEndpointOverride": getOrCreateConfiguration(target).setUriEndpointOverride(property(camelContext, java.lang.String.class, value)); return true;
+ case "usedefaultcredentialsprovider":
+ case "useDefaultCredentialsProvider": getOrCreateConfiguration(target).setUseDefaultCredentialsProvider(property(camelContext, boolean.class, value)); return true;
+ case "useprofilecredentialsprovider":
+ case "useProfileCredentialsProvider": getOrCreateConfiguration(target).setUseProfileCredentialsProvider(property(camelContext, boolean.class, value)); return true;
+ case "usesessioncredentials":
+ case "useSessionCredentials": getOrCreateConfiguration(target).setUseSessionCredentials(property(camelContext, boolean.class, value)); return true;
+ case "voiceid":
+ case "voiceId": getOrCreateConfiguration(target).setVoiceId(property(camelContext, software.amazon.awssdk.services.polly.model.VoiceId.class, value)); return true;
+ default: return false;
+ }
+ }
+
+ @Override
+ public String[] getAutowiredNames() {
+ return new String[]{"pollyClient"};
+ }
+
+ @Override
+ public Class<?> getOptionType(String name, boolean ignoreCase) {
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "accesskey":
+ case "accessKey": return java.lang.String.class;
+ case "autowiredenabled":
+ case "autowiredEnabled": return boolean.class;
+ case "configuration": return org.apache.camel.component.aws2.polly.Polly2Configuration.class;
+ case "engine": return software.amazon.awssdk.services.polly.model.Engine.class;
+ case "healthcheckconsumerenabled":
+ case "healthCheckConsumerEnabled": return boolean.class;
+ case "healthcheckproducerenabled":
+ case "healthCheckProducerEnabled": return boolean.class;
+ case "languagecode":
+ case "languageCode": return java.lang.String.class;
+ case "lazystartproducer":
+ case "lazyStartProducer": return boolean.class;
+ case "lexiconnames":
+ case "lexiconNames": return java.lang.String.class;
+ case "operation": return org.apache.camel.component.aws2.polly.Polly2Operations.class;
+ case "outputformat":
+ case "outputFormat": return software.amazon.awssdk.services.polly.model.OutputFormat.class;
+ case "overrideendpoint":
+ case "overrideEndpoint": return boolean.class;
+ case "pojorequest":
+ case "pojoRequest": return boolean.class;
+ case "pollyclient":
+ case "pollyClient": return software.amazon.awssdk.services.polly.PollyClient.class;
+ case "profilecredentialsname":
+ case "profileCredentialsName": return java.lang.String.class;
+ case "proxyhost":
+ case "proxyHost": return java.lang.String.class;
+ case "proxyport":
+ case "proxyPort": return java.lang.Integer.class;
+ case "proxyprotocol":
+ case "proxyProtocol": return software.amazon.awssdk.core.Protocol.class;
+ case "region": return java.lang.String.class;
+ case "samplerate":
+ case "sampleRate": return java.lang.String.class;
+ case "secretkey":
+ case "secretKey": return java.lang.String.class;
+ case "sessiontoken":
+ case "sessionToken": return java.lang.String.class;
+ case "texttype":
+ case "textType": return software.amazon.awssdk.services.polly.model.TextType.class;
+ case "trustallcertificates":
+ case "trustAllCertificates": return boolean.class;
+ case "uriendpointoverride":
+ case "uriEndpointOverride": return java.lang.String.class;
+ case "usedefaultcredentialsprovider":
+ case "useDefaultCredentialsProvider": return boolean.class;
+ case "useprofilecredentialsprovider":
+ case "useProfileCredentialsProvider": return boolean.class;
+ case "usesessioncredentials":
+ case "useSessionCredentials": return boolean.class;
+ case "voiceid":
+ case "voiceId": return software.amazon.awssdk.services.polly.model.VoiceId.class;
+ default: return null;
+ }
+ }
+
+ @Override
+ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+ Polly2Component target = (Polly2Component) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "accesskey":
+ case "accessKey": return getOrCreateConfiguration(target).getAccessKey();
+ case "autowiredenabled":
+ case "autowiredEnabled": return target.isAutowiredEnabled();
+ case "configuration": return target.getConfiguration();
+ case "engine": return getOrCreateConfiguration(target).getEngine();
+ case "healthcheckconsumerenabled":
+ case "healthCheckConsumerEnabled": return target.isHealthCheckConsumerEnabled();
+ case "healthcheckproducerenabled":
+ case "healthCheckProducerEnabled": return target.isHealthCheckProducerEnabled();
+ case "languagecode":
+ case "languageCode": return getOrCreateConfiguration(target).getLanguageCode();
+ case "lazystartproducer":
+ case "lazyStartProducer": return target.isLazyStartProducer();
+ case "lexiconnames":
+ case "lexiconNames": return getOrCreateConfiguration(target).getLexiconNames();
+ case "operation": return getOrCreateConfiguration(target).getOperation();
+ case "outputformat":
+ case "outputFormat": return getOrCreateConfiguration(target).getOutputFormat();
+ case "overrideendpoint":
+ case "overrideEndpoint": return getOrCreateConfiguration(target).isOverrideEndpoint();
+ case "pojorequest":
+ case "pojoRequest": return getOrCreateConfiguration(target).isPojoRequest();
+ case "pollyclient":
+ case "pollyClient": return getOrCreateConfiguration(target).getPollyClient();
+ case "profilecredentialsname":
+ case "profileCredentialsName": return getOrCreateConfiguration(target).getProfileCredentialsName();
+ case "proxyhost":
+ case "proxyHost": return getOrCreateConfiguration(target).getProxyHost();
+ case "proxyport":
+ case "proxyPort": return getOrCreateConfiguration(target).getProxyPort();
+ case "proxyprotocol":
+ case "proxyProtocol": return getOrCreateConfiguration(target).getProxyProtocol();
+ case "region": return getOrCreateConfiguration(target).getRegion();
+ case "samplerate":
+ case "sampleRate": return getOrCreateConfiguration(target).getSampleRate();
+ case "secretkey":
+ case "secretKey": return getOrCreateConfiguration(target).getSecretKey();
+ case "sessiontoken":
+ case "sessionToken": return getOrCreateConfiguration(target).getSessionToken();
+ case "texttype":
+ case "textType": return getOrCreateConfiguration(target).getTextType();
+ case "trustallcertificates":
+ case "trustAllCertificates": return getOrCreateConfiguration(target).isTrustAllCertificates();
+ case "uriendpointoverride":
+ case "uriEndpointOverride": return getOrCreateConfiguration(target).getUriEndpointOverride();
+ case "usedefaultcredentialsprovider":
+ case "useDefaultCredentialsProvider": return getOrCreateConfiguration(target).isUseDefaultCredentialsProvider();
+ case "useprofilecredentialsprovider":
+ case "useProfileCredentialsProvider": return getOrCreateConfiguration(target).isUseProfileCredentialsProvider();
+ case "usesessioncredentials":
+ case "useSessionCredentials": return getOrCreateConfiguration(target).isUseSessionCredentials();
+ case "voiceid":
+ case "voiceId": return getOrCreateConfiguration(target).getVoiceId();
+ default: return null;
+ }
+ }
+}
+
diff --git a/components/camel-aws/camel-aws2-polly/src/generated/java/org/apache/camel/component/aws2/polly/Polly2EndpointConfigurer.java b/components/camel-aws/camel-aws2-polly/src/generated/java/org/apache/camel/component/aws2/polly/Polly2EndpointConfigurer.java
new file mode 100644
index 000000000000..2612e0e6ba74
--- /dev/null
+++ b/components/camel-aws/camel-aws2-polly/src/generated/java/org/apache/camel/component/aws2/polly/Polly2EndpointConfigurer.java
@@ -0,0 +1,191 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.aws2.polly;
+
+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 Polly2EndpointConfigurer extends PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+ @Override
+ public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) {
+ Polly2Endpoint target = (Polly2Endpoint) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "accesskey":
+ case "accessKey": target.getConfiguration().setAccessKey(property(camelContext, java.lang.String.class, value)); return true;
+ case "engine": target.getConfiguration().setEngine(property(camelContext, software.amazon.awssdk.services.polly.model.Engine.class, value)); return true;
+ case "languagecode":
+ case "languageCode": target.getConfiguration().setLanguageCode(property(camelContext, java.lang.String.class, value)); return true;
+ case "lazystartproducer":
+ case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
+ case "lexiconnames":
+ case "lexiconNames": target.getConfiguration().setLexiconNames(property(camelContext, java.lang.String.class, value)); return true;
+ case "operation": target.getConfiguration().setOperation(property(camelContext, org.apache.camel.component.aws2.polly.Polly2Operations.class, value)); return true;
+ case "outputformat":
+ case "outputFormat": target.getConfiguration().setOutputFormat(property(camelContext, software.amazon.awssdk.services.polly.model.OutputFormat.class, value)); return true;
+ case "overrideendpoint":
+ case "overrideEndpoint": target.getConfiguration().setOverrideEndpoint(property(camelContext, boolean.class, value)); return true;
+ case "pojorequest":
+ case "pojoRequest": target.getConfiguration().setPojoRequest(property(camelContext, boolean.class, value)); return true;
+ case "pollyclient":
+ case "pollyClient": target.getConfiguration().setPollyClient(property(camelContext, software.amazon.awssdk.services.polly.PollyClient.class, value)); return true;
+ case "profilecredentialsname":
+ case "profileCredentialsName": target.getConfiguration().setProfileCredentialsName(property(camelContext, java.lang.String.class, value)); return true;
+ case "proxyhost":
+ case "proxyHost": target.getConfiguration().setProxyHost(property(camelContext, java.lang.String.class, value)); return true;
+ case "proxyport":
+ case "proxyPort": target.getConfiguration().setProxyPort(property(camelContext, java.lang.Integer.class, value)); return true;
+ case "proxyprotocol":
+ case "proxyProtocol": target.getConfiguration().setProxyProtocol(property(camelContext, software.amazon.awssdk.core.Protocol.class, value)); return true;
+ case "region": target.getConfiguration().setRegion(property(camelContext, java.lang.String.class, value)); return true;
+ case "samplerate":
+ case "sampleRate": target.getConfiguration().setSampleRate(property(camelContext, java.lang.String.class, value)); return true;
+ case "secretkey":
+ case "secretKey": target.getConfiguration().setSecretKey(property(camelContext, java.lang.String.class, value)); return true;
+ case "sessiontoken":
+ case "sessionToken": target.getConfiguration().setSessionToken(property(camelContext, java.lang.String.class, value)); return true;
+ case "texttype":
+ case "textType": target.getConfiguration().setTextType(property(camelContext, software.amazon.awssdk.services.polly.model.TextType.class, value)); return true;
+ case "trustallcertificates":
+ case "trustAllCertificates": target.getConfiguration().setTrustAllCertificates(property(camelContext, boolean.class, value)); return true;
+ case "uriendpointoverride":
+ case "uriEndpointOverride": target.getConfiguration().setUriEndpointOverride(property(camelContext, java.lang.String.class, value)); return true;
+ case "usedefaultcredentialsprovider":
+ case "useDefaultCredentialsProvider": target.getConfiguration().setUseDefaultCredentialsProvider(property(camelContext, boolean.class, value)); return true;
+ case "useprofilecredentialsprovider":
+ case "useProfileCredentialsProvider": target.getConfiguration().setUseProfileCredentialsProvider(property(camelContext, boolean.class, value)); return true;
+ case "usesessioncredentials":
+ case "useSessionCredentials": target.getConfiguration().setUseSessionCredentials(property(camelContext, boolean.class, value)); return true;
+ case "voiceid":
+ case "voiceId": target.getConfiguration().setVoiceId(property(camelContext, software.amazon.awssdk.services.polly.model.VoiceId.class, value)); return true;
+ default: return false;
+ }
+ }
+
+ @Override
+ public String[] getAutowiredNames() {
+ return new String[]{"pollyClient"};
+ }
+
+ @Override
+ public Class<?> getOptionType(String name, boolean ignoreCase) {
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "accesskey":
+ case "accessKey": return java.lang.String.class;
+ case "engine": return software.amazon.awssdk.services.polly.model.Engine.class;
+ case "languagecode":
+ case "languageCode": return java.lang.String.class;
+ case "lazystartproducer":
+ case "lazyStartProducer": return boolean.class;
+ case "lexiconnames":
+ case "lexiconNames": return java.lang.String.class;
+ case "operation": return org.apache.camel.component.aws2.polly.Polly2Operations.class;
+ case "outputformat":
+ case "outputFormat": return software.amazon.awssdk.services.polly.model.OutputFormat.class;
+ case "overrideendpoint":
+ case "overrideEndpoint": return boolean.class;
+ case "pojorequest":
+ case "pojoRequest": return boolean.class;
+ case "pollyclient":
+ case "pollyClient": return software.amazon.awssdk.services.polly.PollyClient.class;
+ case "profilecredentialsname":
+ case "profileCredentialsName": return java.lang.String.class;
+ case "proxyhost":
+ case "proxyHost": return java.lang.String.class;
+ case "proxyport":
+ case "proxyPort": return java.lang.Integer.class;
+ case "proxyprotocol":
+ case "proxyProtocol": return software.amazon.awssdk.core.Protocol.class;
+ case "region": return java.lang.String.class;
+ case "samplerate":
+ case "sampleRate": return java.lang.String.class;
+ case "secretkey":
+ case "secretKey": return java.lang.String.class;
+ case "sessiontoken":
+ case "sessionToken": return java.lang.String.class;
+ case "texttype":
+ case "textType": return software.amazon.awssdk.services.polly.model.TextType.class;
+ case "trustallcertificates":
+ case "trustAllCertificates": return boolean.class;
+ case "uriendpointoverride":
+ case "uriEndpointOverride": return java.lang.String.class;
+ case "usedefaultcredentialsprovider":
+ case "useDefaultCredentialsProvider": return boolean.class;
+ case "useprofilecredentialsprovider":
+ case "useProfileCredentialsProvider": return boolean.class;
+ case "usesessioncredentials":
+ case "useSessionCredentials": return boolean.class;
+ case "voiceid":
+ case "voiceId": return software.amazon.awssdk.services.polly.model.VoiceId.class;
+ default: return null;
+ }
+ }
+
+ @Override
+ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+ Polly2Endpoint target = (Polly2Endpoint) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "accesskey":
+ case "accessKey": return target.getConfiguration().getAccessKey();
+ case "engine": return target.getConfiguration().getEngine();
+ case "languagecode":
+ case "languageCode": return target.getConfiguration().getLanguageCode();
+ case "lazystartproducer":
+ case "lazyStartProducer": return target.isLazyStartProducer();
+ case "lexiconnames":
+ case "lexiconNames": return target.getConfiguration().getLexiconNames();
+ case "operation": return target.getConfiguration().getOperation();
+ case "outputformat":
+ case "outputFormat": return target.getConfiguration().getOutputFormat();
+ case "overrideendpoint":
+ case "overrideEndpoint": return target.getConfiguration().isOverrideEndpoint();
+ case "pojorequest":
+ case "pojoRequest": return target.getConfiguration().isPojoRequest();
+ case "pollyclient":
+ case "pollyClient": return target.getConfiguration().getPollyClient();
+ case "profilecredentialsname":
+ case "profileCredentialsName": return target.getConfiguration().getProfileCredentialsName();
+ case "proxyhost":
+ case "proxyHost": return target.getConfiguration().getProxyHost();
+ case "proxyport":
+ case "proxyPort": return target.getConfiguration().getProxyPort();
+ case "proxyprotocol":
+ case "proxyProtocol": return target.getConfiguration().getProxyProtocol();
+ case "region": return target.getConfiguration().getRegion();
+ case "samplerate":
+ case "sampleRate": return target.getConfiguration().getSampleRate();
+ case "secretkey":
+ case "secretKey": return target.getConfiguration().getSecretKey();
+ case "sessiontoken":
+ case "sessionToken": return target.getConfiguration().getSessionToken();
+ case "texttype":
+ case "textType": return target.getConfiguration().getTextType();
+ case "trustallcertificates":
+ case "trustAllCertificates": return target.getConfiguration().isTrustAllCertificates();
+ case "uriendpointoverride":
+ case "uriEndpointOverride": return target.getConfiguration().getUriEndpointOverride();
+ case "usedefaultcredentialsprovider":
+ case "useDefaultCredentialsProvider": return target.getConfiguration().isUseDefaultCredentialsProvider();
+ case "useprofilecredentialsprovider":
+ case "useProfileCredentialsProvider": return target.getConfiguration().isUseProfileCredentialsProvider();
+ case "usesessioncredentials":
+ case "useSessionCredentials": return target.getConfiguration().isUseSessionCredentials();
+ case "voiceid":
+ case "voiceId": return target.getConfiguration().getVoiceId();
+ default: return null;
+ }
+ }
+}
+
diff --git a/components/camel-aws/camel-aws2-polly/src/generated/java/org/apache/camel/component/aws2/polly/Polly2EndpointUriFactory.java b/components/camel-aws/camel-aws2-polly/src/generated/java/org/apache/camel/component/aws2/polly/Polly2EndpointUriFactory.java
new file mode 100644
index 000000000000..5e29378eb593
--- /dev/null
+++ b/components/camel-aws/camel-aws2-polly/src/generated/java/org/apache/camel/component/aws2/polly/Polly2EndpointUriFactory.java
@@ -0,0 +1,99 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.aws2.polly;
+
+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 Polly2EndpointUriFactory extends org.apache.camel.support.component.EndpointUriFactorySupport implements EndpointUriFactory {
+
+ private static final String BASE = ":label";
+
+ private static final Set<String> PROPERTY_NAMES;
+ private static final Set<String> SECRET_PROPERTY_NAMES;
+ private static final Map<String, String> MULTI_VALUE_PREFIXES;
+ static {
+ Set<String> props = new HashSet<>(26);
+ props.add("accessKey");
+ props.add("engine");
+ props.add("label");
+ props.add("languageCode");
+ props.add("lazyStartProducer");
+ props.add("lexiconNames");
+ props.add("operation");
+ props.add("outputFormat");
+ props.add("overrideEndpoint");
+ props.add("pojoRequest");
+ props.add("pollyClient");
+ props.add("profileCredentialsName");
+ props.add("proxyHost");
+ props.add("proxyPort");
+ props.add("proxyProtocol");
+ props.add("region");
+ props.add("sampleRate");
+ props.add("secretKey");
+ props.add("sessionToken");
+ props.add("textType");
+ props.add("trustAllCertificates");
+ props.add("uriEndpointOverride");
+ props.add("useDefaultCredentialsProvider");
+ props.add("useProfileCredentialsProvider");
+ props.add("useSessionCredentials");
+ props.add("voiceId");
+ PROPERTY_NAMES = Collections.unmodifiableSet(props);
+ Set<String> secretProps = new HashSet<>(3);
+ secretProps.add("accessKey");
+ secretProps.add("secretKey");
+ secretProps.add("sessionToken");
+ SECRET_PROPERTY_NAMES = Collections.unmodifiableSet(secretProps);
+ MULTI_VALUE_PREFIXES = Collections.emptyMap();
+ }
+
+ @Override
+ public boolean isEnabled(String scheme) {
+ return "aws2-polly".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, "label", 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 Map<String, String> multiValuePrefixes() {
+ return MULTI_VALUE_PREFIXES;
+ }
+
+ @Override
+ public boolean isLenientProperties() {
+ return false;
+ }
+}
+
diff --git a/components/camel-aws/camel-aws2-polly/src/generated/resources/META-INF/org/apache/camel/component/aws2/polly/aws2-polly.json b/components/camel-aws/camel-aws2-polly/src/generated/resources/META-INF/org/apache/camel/component/aws2/polly/aws2-polly.json
new file mode 100644
index 000000000000..b4e3a41215ec
--- /dev/null
+++ b/components/camel-aws/camel-aws2-polly/src/generated/resources/META-INF/org/apache/camel/component/aws2/polly/aws2-polly.json
@@ -0,0 +1,103 @@
+{
+ "component": {
+ "kind": "component",
+ "name": "aws2-polly",
+ "title": "AWS Polly",
+ "description": "Synthesize speech using AWS Polly and AWS SDK version 2.x.",
+ "deprecated": false,
+ "firstVersion": "4.18.0",
+ "label": "cloud,ai",
+ "javaType": "org.apache.camel.component.aws2.polly.Polly2Component",
+ "supportLevel": "Preview",
+ "groupId": "org.apache.camel",
+ "artifactId": "camel-aws2-polly",
+ "version": "4.18.0-SNAPSHOT",
+ "scheme": "aws2-polly",
+ "extendsScheme": "",
+ "syntax": "aws2-polly:label",
+ "async": false,
+ "api": false,
+ "consumerOnly": false,
+ "producerOnly": true,
+ "lenientProperties": false,
+ "browsable": false,
+ "remote": true
+ },
+ "componentProperties": {
+ "configuration": { "index": 0, "kind": "property", "displayName": "Configuration", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.aws2.polly.Polly2Configuration", "deprecated": false, "autowired": false, "secret": false, "description": "Component configuration" },
+ "engine": { "index": 1, "kind": "property", "displayName": "Engine", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "software.amazon.awssdk.services.polly.model.Engine", "enum": [ "standard", "neural", "long-form", "generative", "null" ], "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "The engine to use f [...]
+ "languageCode": { "index": 2, "kind": "property", "displayName": "Language Code", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "The language code for the synthesis" },
+ "lazyStartProducer": { "index": 3, "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 [...]
+ "lexiconNames": { "index": 4, "kind": "property", "displayName": "Lexicon Names", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "Lexicon names to apply during synthesis" },
+ "operation": { "index": 5, "kind": "property", "displayName": "Operation", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.component.aws2.polly.Polly2Operations", "enum": [ "synthesizeSpeech", "describeVoices", "listLexicons", "getLexicon", "putLexicon", "deleteLexicon", "startSpeechSynthesisTask", "getSpeechSynthesisTask", "listSpeechSynthesisTasks" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, " [...]
+ "outputFormat": { "index": 6, "kind": "property", "displayName": "Output Format", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "software.amazon.awssdk.services.polly.model.OutputFormat", "enum": [ "json", "mp3", "ogg_opus", "ogg_vorbis", "pcm", "null" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "MP3", "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configurat [...]
+ "overrideEndpoint": { "index": 7, "kind": "property", "displayName": "Override Endpoint", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "Set the need for overriding the endpoint. This option needs to be used in combinatio [...]
+ "pojoRequest": { "index": 8, "kind": "property", "displayName": "Pojo Request", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "If we want to use a POJO request as body or not" },
+ "region": { "index": 9, "kind": "property", "displayName": "Region", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "ap-south-2", "ap-south-1", "eu-south-1", "eu-south-2", "us-gov-east-1", "me-central-1", "il-central-1", "ca-central-1", "eu-central-1", "us-iso-west-1", "eu-central-2", "eu-isoe-west-1", "us-west-1", "us-west-2", "af-south-1", "eu-north-1", "eu-west-3", "eu-west-2", "eu-west-1", "ap-northeast-3", "ap-north [...]
+ "sampleRate": { "index": 10, "kind": "property", "displayName": "Sample Rate", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "The sample rate in Hz for the audio output" },
+ "textType": { "index": 11, "kind": "property", "displayName": "Text Type", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "software.amazon.awssdk.services.polly.model.TextType", "enum": [ "ssml", "text", "null" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "TEXT", "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "The type of text inp [...]
+ "uriEndpointOverride": { "index": 12, "kind": "property", "displayName": "Uri Endpoint Override", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "Set the overriding uri endpoint. This option needs to be used in combination with overrideE [...]
+ "voiceId": { "index": 13, "kind": "property", "displayName": "Voice Id", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "software.amazon.awssdk.services.polly.model.VoiceId", "enum": [ "Aditi", "Amy", "Astrid", "Bianca", "Brian", "Camila", "Carla", "Carmen", "Celine", "Chantal", "Conchita", "Cristiano", "Dora", "Emma", "Enrique", "Ewa", "Filiz", "Gabrielle", "Geraint", "Giorgio", "Gwyneth", "Hans", "Ines", "Ivy", "Jacek", "Jan", "Joanna", "Joey", "Ju [...]
+ "autowiredEnabled": { "index": 14, "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 [...]
+ "pollyClient": { "index": 15, "kind": "property", "displayName": "Polly Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "software.amazon.awssdk.services.polly.PollyClient", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "To use an existing configured AWS Polly client" },
+ "healthCheckConsumerEnabled": { "index": 16, "kind": "property", "displayName": "Health Check Consumer Enabled", "group": "health", "label": "health", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Used for enabling or disabling all consumer based health checks from this component" },
+ "healthCheckProducerEnabled": { "index": 17, "kind": "property", "displayName": "Health Check Producer Enabled", "group": "health", "label": "health", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Used for enabling or disabling all producer based health checks from this component. Notice: Camel has by default disabled all producer based health-checks. You can turn on produce [...]
+ "proxyHost": { "index": 18, "kind": "property", "displayName": "Proxy Host", "group": "proxy", "label": "proxy", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "To define a proxy host when instantiating the Polly client" },
+ "proxyPort": { "index": 19, "kind": "property", "displayName": "Proxy Port", "group": "proxy", "label": "proxy", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "To define a proxy port when instantiating the Polly client" },
+ "proxyProtocol": { "index": 20, "kind": "property", "displayName": "Proxy Protocol", "group": "proxy", "label": "proxy", "required": false, "type": "enum", "javaType": "software.amazon.awssdk.core.Protocol", "enum": [ "HTTP", "HTTPS" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "HTTPS", "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "To define a proxy protocol whe [...]
+ "accessKey": { "index": 21, "kind": "property", "displayName": "Access Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "Amazon AWS Access Key" },
+ "profileCredentialsName": { "index": 22, "kind": "property", "displayName": "Profile Credentials Name", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "If using a profile credentials provider, this parameter will set the profile [...]
+ "secretKey": { "index": 23, "kind": "property", "displayName": "Secret Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "Amazon AWS Secret Key" },
+ "sessionToken": { "index": 24, "kind": "property", "displayName": "Session Token", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "Amazon AWS Session Token used when the user needs to assume an IAM role" },
+ "trustAllCertificates": { "index": 25, "kind": "property", "displayName": "Trust All Certificates", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "If we want to trust all certificates in case of overriding the end [...]
+ "useDefaultCredentialsProvider": { "index": 26, "kind": "property", "displayName": "Use Default Credentials Provider", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "Set whether the Polly client should expect to l [...]
+ "useProfileCredentialsProvider": { "index": 27, "kind": "property", "displayName": "Use Profile Credentials Provider", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "Set whether the Polly client should expect to l [...]
+ "useSessionCredentials": { "index": 28, "kind": "property", "displayName": "Use Session Credentials", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "Set whether the Polly client should expect to use Session Creden [...]
+ },
+ "headers": {
+ "CamelAwsPollyOperation": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The operation we want to perform", "constantName": "org.apache.camel.component.aws2.polly.Polly2Constants#OPERATION" },
+ "CamelAwsPollyVoiceId": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "software.amazon.awssdk.services.polly.model.VoiceId", "enum": [ "Aditi", "Amy", "Astrid", "Bianca", "Brian", "Camila", "Carla", "Carmen", "Celine", "Chantal", "Conchita", "Cristiano", "Dora", "Emma", "Enrique", "Ewa", "Filiz", "Gabrielle", "Geraint", "Giorgio", "Gwyneth", "Hans", "Ines", "Ivy", "Jacek", "Jan", "Joanna", "Joey", "Justin", "Karl", [...]
+ "CamelAwsPollyOutputFormat": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "software.amazon.awssdk.services.polly.model.OutputFormat", "enum": [ "json", "mp3", "ogg_opus", "ogg_vorbis", "pcm", "null" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The output format for the audio stream", "constantName": "org.apache.camel.component.aws2.polly.Polly2Constants#OUTPUT [...]
+ "CamelAwsPollyTextType": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "software.amazon.awssdk.services.polly.model.TextType", "enum": [ "ssml", "text", "null" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The type of text input (text or ssml)", "constantName": "org.apache.camel.component.aws2.polly.Polly2Constants#TEXT_TYPE" },
+ "CamelAwsPollySampleRate": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The sample rate in Hz", "constantName": "org.apache.camel.component.aws2.polly.Polly2Constants#SAMPLE_RATE" },
+ "CamelAwsPollyEngine": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "software.amazon.awssdk.services.polly.model.Engine", "enum": [ "standard", "neural", "long-form", "generative", "null" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The engine to use (standard, neural, long-form, generative)", "constantName": "org.apache.camel.component.aws2.polly.Polly2Consta [...]
+ "CamelAwsPollyLanguageCode": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The language code", "constantName": "org.apache.camel.component.aws2.polly.Polly2Constants#LANGUAGE_CODE" },
+ "CamelAwsPollyLexiconNames": { "index": 7, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Comma-separated list of lexicon names", "constantName": "org.apache.camel.component.aws2.polly.Polly2Constants#LEXICON_NAMES" },
+ "CamelAwsPollyLexiconName": { "index": 8, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name of the lexicon", "constantName": "org.apache.camel.component.aws2.polly.Polly2Constants#LEXICON_NAME" },
+ "CamelAwsPollyLexiconContent": { "index": 9, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The content of the lexicon in PLS format", "constantName": "org.apache.camel.component.aws2.polly.Polly2Constants#LEXICON_CONTENT" },
+ "CamelAwsPollyTaskId": { "index": 10, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The task ID for speech synthesis task", "constantName": "org.apache.camel.component.aws2.polly.Polly2Constants#TASK_ID" },
+ "CamelAwsPollyS3Bucket": { "index": 11, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The S3 bucket name for output", "constantName": "org.apache.camel.component.aws2.polly.Polly2Constants#S3_BUCKET" },
+ "CamelAwsPollyS3KeyPrefix": { "index": 12, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The S3 key prefix for output", "constantName": "org.apache.camel.component.aws2.polly.Polly2Constants#S3_KEY_PREFIX" },
+ "CamelAwsPollySnsTopicArn": { "index": 13, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The SNS topic ARN for notifications", "constantName": "org.apache.camel.component.aws2.polly.Polly2Constants#SNS_TOPIC_ARN" },
+ "CamelAwsPollyContentType": { "index": 14, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The content type of the audio stream", "constantName": "org.apache.camel.component.aws2.polly.Polly2Constants#CONTENT_TYPE" },
+ "CamelAwsPollyRequestCharacters": { "index": 15, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Number of characters synthesized", "constantName": "org.apache.camel.component.aws2.polly.Polly2Constants#REQUEST_CHARACTERS" }
+ },
+ "properties": {
+ "label": { "index": 0, "kind": "path", "displayName": "Label", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "Logical name" },
+ "engine": { "index": 1, "kind": "parameter", "displayName": "Engine", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "software.amazon.awssdk.services.polly.model.Engine", "enum": [ "standard", "neural", "long-form", "generative", "null" ], "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "The engine to use [...]
+ "languageCode": { "index": 2, "kind": "parameter", "displayName": "Language Code", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "The language code for the synthesis" },
+ "lexiconNames": { "index": 3, "kind": "parameter", "displayName": "Lexicon Names", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "Lexicon names to apply during synthesis" },
+ "operation": { "index": 4, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.component.aws2.polly.Polly2Operations", "enum": [ "synthesizeSpeech", "describeVoices", "listLexicons", "getLexicon", "putLexicon", "deleteLexicon", "startSpeechSynthesisTask", "getSpeechSynthesisTask", "listSpeechSynthesisTasks" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, [...]
+ "outputFormat": { "index": 5, "kind": "parameter", "displayName": "Output Format", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "software.amazon.awssdk.services.polly.model.OutputFormat", "enum": [ "json", "mp3", "ogg_opus", "ogg_vorbis", "pcm", "null" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "MP3", "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configura [...]
+ "overrideEndpoint": { "index": 6, "kind": "parameter", "displayName": "Override Endpoint", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "Set the need for overriding the endpoint. This option needs to be used in combinati [...]
+ "pojoRequest": { "index": 7, "kind": "parameter", "displayName": "Pojo Request", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "If we want to use a POJO request as body or not" },
+ "region": { "index": 8, "kind": "parameter", "displayName": "Region", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "ap-south-2", "ap-south-1", "eu-south-1", "eu-south-2", "us-gov-east-1", "me-central-1", "il-central-1", "ca-central-1", "eu-central-1", "us-iso-west-1", "eu-central-2", "eu-isoe-west-1", "us-west-1", "us-west-2", "af-south-1", "eu-north-1", "eu-west-3", "eu-west-2", "eu-west-1", "ap-northeast-3", "ap-nort [...]
+ "sampleRate": { "index": 9, "kind": "parameter", "displayName": "Sample Rate", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "The sample rate in Hz for the audio output" },
+ "textType": { "index": 10, "kind": "parameter", "displayName": "Text Type", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "software.amazon.awssdk.services.polly.model.TextType", "enum": [ "ssml", "text", "null" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "TEXT", "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "The type of text in [...]
+ "uriEndpointOverride": { "index": 11, "kind": "parameter", "displayName": "Uri Endpoint Override", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "Set the overriding uri endpoint. This option needs to be used in combination with override [...]
+ "voiceId": { "index": 12, "kind": "parameter", "displayName": "Voice Id", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "software.amazon.awssdk.services.polly.model.VoiceId", "enum": [ "Aditi", "Amy", "Astrid", "Bianca", "Brian", "Camila", "Carla", "Carmen", "Celine", "Chantal", "Conchita", "Cristiano", "Dora", "Emma", "Enrique", "Ewa", "Filiz", "Gabrielle", "Geraint", "Giorgio", "Gwyneth", "Hans", "Ines", "Ivy", "Jacek", "Jan", "Joanna", "Joey", "J [...]
+ "lazyStartProducer": { "index": 13, "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 produ [...]
+ "pollyClient": { "index": 14, "kind": "parameter", "displayName": "Polly Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "software.amazon.awssdk.services.polly.PollyClient", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "To use an existing configured AWS Polly client" },
+ "proxyHost": { "index": 15, "kind": "parameter", "displayName": "Proxy Host", "group": "proxy", "label": "proxy", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "To define a proxy host when instantiating the Polly client" },
+ "proxyPort": { "index": 16, "kind": "parameter", "displayName": "Proxy Port", "group": "proxy", "label": "proxy", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "To define a proxy port when instantiating the Polly client" },
+ "proxyProtocol": { "index": 17, "kind": "parameter", "displayName": "Proxy Protocol", "group": "proxy", "label": "proxy", "required": false, "type": "enum", "javaType": "software.amazon.awssdk.core.Protocol", "enum": [ "HTTP", "HTTPS" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "HTTPS", "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "To define a proxy protocol wh [...]
+ "accessKey": { "index": 18, "kind": "parameter", "displayName": "Access Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "Amazon AWS Access Key" },
+ "profileCredentialsName": { "index": 19, "kind": "parameter", "displayName": "Profile Credentials Name", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "If using a profile credentials provider, this parameter will set the profile [...]
+ "secretKey": { "index": 20, "kind": "parameter", "displayName": "Secret Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "Amazon AWS Secret Key" },
+ "sessionToken": { "index": 21, "kind": "parameter", "displayName": "Session Token", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "Amazon AWS Session Token used when the user needs to assume an IAM role" },
+ "trustAllCertificates": { "index": 22, "kind": "parameter", "displayName": "Trust All Certificates", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "If we want to trust all certificates in case of overriding the en [...]
+ "useDefaultCredentialsProvider": { "index": 23, "kind": "parameter", "displayName": "Use Default Credentials Provider", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "Set whether the Polly client should expect to [...]
+ "useProfileCredentialsProvider": { "index": 24, "kind": "parameter", "displayName": "Use Profile Credentials Provider", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "Set whether the Polly client should expect to [...]
+ "useSessionCredentials": { "index": 25, "kind": "parameter", "displayName": "Use Session Credentials", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.polly.Polly2Configuration", "configurationField": "configuration", "description": "Set whether the Polly client should expect to use Session Crede [...]
+ }
+}
diff --git a/components/camel-aws/camel-aws2-polly/src/generated/resources/META-INF/services/org/apache/camel/component.properties b/components/camel-aws/camel-aws2-polly/src/generated/resources/META-INF/services/org/apache/camel/component.properties
new file mode 100644
index 000000000000..d38a2831caeb
--- /dev/null
+++ b/components/camel-aws/camel-aws2-polly/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=aws2-polly
+groupId=org.apache.camel
+artifactId=camel-aws2-polly
+version=4.18.0-SNAPSHOT
+projectName=Camel :: AWS2 Polly
+projectDescription=Synthesize speech using AWS Polly Service
diff --git a/components/camel-aws/camel-aws2-polly/src/generated/resources/META-INF/services/org/apache/camel/component/aws2-polly b/components/camel-aws/camel-aws2-polly/src/generated/resources/META-INF/services/org/apache/camel/component/aws2-polly
new file mode 100644
index 000000000000..e638ce90b3f3
--- /dev/null
+++ b/components/camel-aws/camel-aws2-polly/src/generated/resources/META-INF/services/org/apache/camel/component/aws2-polly
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.aws2.polly.Polly2Component
diff --git a/components/camel-aws/camel-aws2-polly/src/generated/resources/META-INF/services/org/apache/camel/configurer/aws2-polly-component b/components/camel-aws/camel-aws2-polly/src/generated/resources/META-INF/services/org/apache/camel/configurer/aws2-polly-component
new file mode 100644
index 000000000000..1609c5101ccd
--- /dev/null
+++ b/components/camel-aws/camel-aws2-polly/src/generated/resources/META-INF/services/org/apache/camel/configurer/aws2-polly-component
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.aws2.polly.Polly2ComponentConfigurer
diff --git a/components/camel-aws/camel-aws2-polly/src/generated/resources/META-INF/services/org/apache/camel/configurer/aws2-polly-endpoint b/components/camel-aws/camel-aws2-polly/src/generated/resources/META-INF/services/org/apache/camel/configurer/aws2-polly-endpoint
new file mode 100644
index 000000000000..d7e3838fdf5d
--- /dev/null
+++ b/components/camel-aws/camel-aws2-polly/src/generated/resources/META-INF/services/org/apache/camel/configurer/aws2-polly-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.aws2.polly.Polly2EndpointConfigurer
diff --git a/components/camel-aws/camel-aws2-polly/src/generated/resources/META-INF/services/org/apache/camel/urifactory/aws2-polly-endpoint b/components/camel-aws/camel-aws2-polly/src/generated/resources/META-INF/services/org/apache/camel/urifactory/aws2-polly-endpoint
new file mode 100644
index 000000000000..ed351d7890c2
--- /dev/null
+++ b/components/camel-aws/camel-aws2-polly/src/generated/resources/META-INF/services/org/apache/camel/urifactory/aws2-polly-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.aws2.polly.Polly2EndpointUriFactory
diff --git a/components/camel-aws/camel-aws2-polly/src/main/docs/aws2-polly-component.adoc b/components/camel-aws/camel-aws2-polly/src/main/docs/aws2-polly-component.adoc
new file mode 100644
index 000000000000..0c475deea824
--- /dev/null
+++ b/components/camel-aws/camel-aws2-polly/src/main/docs/aws2-polly-component.adoc
@@ -0,0 +1,171 @@
+= AWS Polly Component
+:doctitle: AWS Polly
+:shortname: aws2-polly
+:artifactid: camel-aws2-polly
+:description: Synthesize speech using AWS Polly and AWS SDK version 2.x.
+:since: 4.18
+:supportlevel: Preview
+:tabs-sync-option:
+:component-header: Only producer is supported
+//Manually maintained attributes
+:group: AWS
+:camel-spring-boot-name: aws2-polly
+
+*Since Camel {since}*
+
+*{component-header}*
+
+The AWS2 Polly component supports text-to-speech synthesis using the AWS Polly service.
+https://aws.amazon.com/polly/[AWS Polly] is a cloud service that converts text into lifelike speech.
+
+Prerequisites
+
+You must have a valid Amazon Web Services developer account, and be
+signed up to use Amazon Polly. More information is available at
+https://aws.amazon.com/polly/[Amazon Polly].
+
+== URI Format
+
+-------------------------
+aws2-polly://label[?options]
+-------------------------
+
+You can append query options to the URI in the following format:
+
+`?options=value&option2=value&...`
+
+
+// component options: START
+include::partial$component-configure-options.adoc[]
+include::partial$component-endpoint-options.adoc[]
+include::partial$component-endpoint-headers.adoc[]
+// component options: END
+
+
+Required Polly component options
+
+You have to provide the amazonPollyClient in the
+Registry or your accessKey and secretKey to access
+the https://aws.amazon.com/polly/[Amazon Polly] service.
+
+== Usage
+
+=== Static credentials, Default Credential Provider and Profile Credentials Provider
+
+You have the possibility of avoiding the usage of explicit static credentials by specifying the useDefaultCredentialsProvider option and set it to true.
+
+The order of evaluation for Default Credentials Provider is the following:
+
+ - Java system properties - `aws.accessKeyId` and `aws.secretKey`
+ - Environment variables - `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`.
+ - Web Identity Token from AWS STS.
+ - The shared credentials and config files.
+ - Amazon ECS container credentials - loaded from the Amazon ECS if the environment variable `AWS_CONTAINER_CREDENTIALS_RELATIVE_URI` is set.
+ - Amazon EC2 Instance profile credentials.
+
+You have also the possibility of using Profile Credentials Provider, by specifying the useProfileCredentialsProvider option to true and profileCredentialsName to the profile name.
+
+Only one of static, default and profile credentials could be used at the same time.
+
+For more information about this you can look at https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/credentials.html[AWS credentials documentation]
+
+=== Polly Producer operations
+
+Camel-AWS Polly component provides the following operations on the producer side:
+
+- synthesizeSpeech
+- describeVoices
+- listLexicons
+- getLexicon
+- putLexicon
+- deleteLexicon
+- startSpeechSynthesisTask
+- getSpeechSynthesisTask
+- listSpeechSynthesisTasks
+
+== Examples
+
+=== Synthesize Speech example
+
+[source,java]
+------------------------------------------------------------------------------------------------------
+from("direct:start")
+ .setHeader(Polly2Constants.VOICE_ID, constant(VoiceId.JOANNA))
+ .setBody(constant("Hello, this is a test of Amazon Polly text to speech synthesis."))
+ .to("aws2-polly://test?operation=synthesizeSpeech")
+ .to("file:output?fileName=speech.mp3");
+------------------------------------------------------------------------------------------------------
+
+As a result, you'll get an exchange containing the audio stream (InputStream) with the synthesized speech.
+
+=== Using Neural Voices
+
+[source,java]
+------------------------------------------------------------------------------------------------------
+from("direct:start")
+ .setHeader(Polly2Constants.VOICE_ID, constant(VoiceId.MATTHEW))
+ .setHeader(Polly2Constants.ENGINE, constant(Engine.NEURAL))
+ .setBody(constant("This is synthesized using a neural voice."))
+ .to("aws2-polly://test?operation=synthesizeSpeech&outputFormat=MP3");
+------------------------------------------------------------------------------------------------------
+
+=== Describe Voices example
+
+[source,java]
+------------------------------------------------------------------------------------------------------
+from("direct:start")
+ .to("aws2-polly://test?operation=describeVoices")
+ .log("Available voices: ${body}");
+------------------------------------------------------------------------------------------------------
+
+=== Asynchronous Speech Synthesis with S3
+
+For long text, you can use asynchronous synthesis which stores the result in S3:
+
+[source,java]
+------------------------------------------------------------------------------------------------------
+from("direct:start")
+ .setHeader(Polly2Constants.VOICE_ID, constant(VoiceId.JOANNA))
+ .setHeader(Polly2Constants.S3_BUCKET, constant("my-audio-bucket"))
+ .setHeader(Polly2Constants.S3_KEY_PREFIX, constant("audio/"))
+ .setBody(constant("This is a very long text that will be synthesized asynchronously..."))
+ .to("aws2-polly://test?operation=startSpeechSynthesisTask");
+------------------------------------------------------------------------------------------------------
+
+=== Using a POJO as body
+
+Sometimes building an AWS Request can be complex because of multiple options. We introduce the possibility to use a POJO as the body.
+In AWS Polly, you can do something like:
+
+[source,java]
+------------------------------------------------------------------------------------------------------
+from("direct:start")
+ .setBody(SynthesizeSpeechRequest.builder()
+ .voiceId(VoiceId.JOANNA)
+ .outputFormat(OutputFormat.MP3)
+ .text("Hello from Camel!")
+ .build())
+ .to("aws2-polly://test?operation=synthesizeSpeech&pojoRequest=true");
+------------------------------------------------------------------------------------------------------
+
+In this way, you'll pass the request directly without the need of passing headers and options specifically related to this operation.
+
+== Dependencies
+
+Maven users will need to add the following dependency to their pom.xml.
+
+*pom.xml*
+
+[source,xml]
+---------------------------------------
+<dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-aws2-polly</artifactId>
+ <version>${camel-version}</version>
+</dependency>
+---------------------------------------
+
+where `$\{camel-version}` must be replaced by the actual version of Camel.
+
+
+include::spring-boot:partial$starter.adoc[]
diff --git a/components/camel-aws/camel-aws2-polly/src/main/java/org/apache/camel/component/aws2/polly/Polly2Component.java b/components/camel-aws/camel-aws2-polly/src/main/java/org/apache/camel/component/aws2/polly/Polly2Component.java
new file mode 100644
index 000000000000..d9ede2be6ea9
--- /dev/null
+++ b/components/camel-aws/camel-aws2-polly/src/main/java/org/apache/camel/component/aws2/polly/Polly2Component.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.aws2.polly;
+
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Endpoint;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.annotations.Component;
+import org.apache.camel.support.HealthCheckComponent;
+
+/**
+ * For working with Amazon Polly SDK v2.
+ */
+@Component("aws2-polly")
+public class Polly2Component extends HealthCheckComponent {
+
+ @Metadata
+ private Polly2Configuration configuration = new Polly2Configuration();
+
+ public Polly2Component() {
+ this(null);
+ }
+
+ public Polly2Component(CamelContext context) {
+ super(context);
+ }
+
+ @Override
+ protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
+ Polly2Configuration configuration
+ = this.configuration != null ? this.configuration.copy() : new Polly2Configuration();
+
+ Polly2Endpoint endpoint = new Polly2Endpoint(uri, this, configuration);
+ setProperties(endpoint, parameters);
+ if (Boolean.FALSE.equals(configuration.isUseDefaultCredentialsProvider())
+ && Boolean.FALSE.equals(configuration.isUseProfileCredentialsProvider())
+ && Boolean.FALSE.equals(configuration.isUseSessionCredentials())
+ && configuration.getPollyClient() == null
+ && (configuration.getAccessKey() == null || configuration.getSecretKey() == null)) {
+ throw new IllegalArgumentException(
+ "useDefaultCredentialsProvider is set to false, useProfileCredentialsProvider is set to false, useSessionCredentials is set to false, Amazon Polly client or accessKey and secretKey must be specified");
+ }
+ return endpoint;
+ }
+
+ public Polly2Configuration getConfiguration() {
+ return configuration;
+ }
+
+ /**
+ * Component configuration
+ */
+ public void setConfiguration(Polly2Configuration configuration) {
+ this.configuration = configuration;
+ }
+}
diff --git a/components/camel-aws/camel-aws2-polly/src/main/java/org/apache/camel/component/aws2/polly/Polly2Configuration.java b/components/camel-aws/camel-aws2-polly/src/main/java/org/apache/camel/component/aws2/polly/Polly2Configuration.java
new file mode 100644
index 000000000000..4fe33b7cc4cd
--- /dev/null
+++ b/components/camel-aws/camel-aws2-polly/src/main/java/org/apache/camel/component/aws2/polly/Polly2Configuration.java
@@ -0,0 +1,368 @@
+/*
+ * 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.aws2.polly;
+
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.component.aws.common.AwsCommonConfiguration;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.spi.UriParams;
+import org.apache.camel.spi.UriPath;
+import software.amazon.awssdk.core.Protocol;
+import software.amazon.awssdk.services.polly.PollyClient;
+import software.amazon.awssdk.services.polly.model.Engine;
+import software.amazon.awssdk.services.polly.model.OutputFormat;
+import software.amazon.awssdk.services.polly.model.TextType;
+import software.amazon.awssdk.services.polly.model.VoiceId;
+
+@UriParams
+public class Polly2Configuration implements Cloneable, AwsCommonConfiguration {
+
+ @UriPath(description = "Logical name")
+ @Metadata(required = true)
+ private String label;
+ @UriParam(label = "advanced")
+ @Metadata(autowired = true)
+ private PollyClient pollyClient;
+ @UriParam(label = "security", secret = true)
+ private String accessKey;
+ @UriParam(label = "security", secret = true)
+ private String secretKey;
+ @UriParam(label = "security", secret = true)
+ private String sessionToken;
+ @UriParam(defaultValue = "synthesizeSpeech")
+ @Metadata(required = true)
+ private Polly2Operations operation = Polly2Operations.synthesizeSpeech;
+ @UriParam(label = "proxy", enums = "HTTP,HTTPS", defaultValue = "HTTPS")
+ private Protocol proxyProtocol = Protocol.HTTPS;
+ @UriParam(label = "proxy")
+ private String proxyHost;
+ @UriParam(label = "proxy")
+ private Integer proxyPort;
+ @UriParam(enums = "ap-south-2,ap-south-1,eu-south-1,eu-south-2,us-gov-east-1,me-central-1,il-central-1,ca-central-1,eu-central-1,us-iso-west-1,eu-central-2,eu-isoe-west-1,us-west-1,us-west-2,af-south-1,eu-north-1,eu-west-3,eu-west-2,eu-west-1,ap-northeast-3,ap-northeast-2,ap-northeast-1,me-south-1,sa-east-1,ap-east-1,cn-north-1,ca-west-1,us-gov-west-1,ap-southeast-1,ap-southeast-2,us-iso-east-1,ap-southeast-3,ap-southeast-4,us-east-1,us-east-2,cn-northwest-1,us-isob-east-1,aws-global [...]
+ private String region;
+ @UriParam(description = "The voice ID to use for synthesis")
+ private VoiceId voiceId;
+ @UriParam(description = "The audio output format", defaultValue = "MP3")
+ private OutputFormat outputFormat = OutputFormat.MP3;
+ @UriParam(description = "The type of text input (text or ssml)", defaultValue = "TEXT")
+ private TextType textType = TextType.TEXT;
+ @UriParam(description = "The engine to use for synthesis (standard, neural, long-form, generative)")
+ private Engine engine;
+ @UriParam(description = "The sample rate in Hz for the audio output")
+ private String sampleRate;
+ @UriParam(description = "The language code for the synthesis")
+ private String languageCode;
+ @UriParam(description = "Lexicon names to apply during synthesis")
+ private String lexiconNames;
+ @UriParam
+ private boolean pojoRequest;
+ @UriParam(label = "security")
+ private boolean trustAllCertificates;
+ @UriParam
+ private boolean overrideEndpoint;
+ @UriParam
+ private String uriEndpointOverride;
+ @UriParam(label = "security")
+ private boolean useDefaultCredentialsProvider;
+ @UriParam(label = "security")
+ private boolean useProfileCredentialsProvider;
+ @UriParam(label = "security")
+ private boolean useSessionCredentials;
+ @UriParam(label = "security")
+ private String profileCredentialsName;
+
+ public PollyClient getPollyClient() {
+ return pollyClient;
+ }
+
+ /**
+ * To use an existing configured AWS Polly client
+ */
+ public void setPollyClient(PollyClient pollyClient) {
+ this.pollyClient = pollyClient;
+ }
+
+ public String getAccessKey() {
+ return accessKey;
+ }
+
+ /**
+ * Amazon AWS Access Key
+ */
+ public void setAccessKey(String accessKey) {
+ this.accessKey = accessKey;
+ }
+
+ public String getSecretKey() {
+ return secretKey;
+ }
+
+ /**
+ * Amazon AWS Secret Key
+ */
+ public void setSecretKey(String secretKey) {
+ this.secretKey = secretKey;
+ }
+
+ public String getSessionToken() {
+ return sessionToken;
+ }
+
+ /**
+ * Amazon AWS Session Token used when the user needs to assume an IAM role
+ */
+ public void setSessionToken(String sessionToken) {
+ this.sessionToken = sessionToken;
+ }
+
+ public Polly2Operations getOperation() {
+ return operation;
+ }
+
+ /**
+ * The operation to perform
+ */
+ public void setOperation(Polly2Operations operation) {
+ this.operation = operation;
+ }
+
+ public Protocol getProxyProtocol() {
+ return proxyProtocol;
+ }
+
+ /**
+ * To define a proxy protocol when instantiating the Polly client
+ */
+ public void setProxyProtocol(Protocol proxyProtocol) {
+ this.proxyProtocol = proxyProtocol;
+ }
+
+ public String getProxyHost() {
+ return proxyHost;
+ }
+
+ /**
+ * To define a proxy host when instantiating the Polly client
+ */
+ public void setProxyHost(String proxyHost) {
+ this.proxyHost = proxyHost;
+ }
+
+ public Integer getProxyPort() {
+ return proxyPort;
+ }
+
+ /**
+ * To define a proxy port when instantiating the Polly client
+ */
+ public void setProxyPort(Integer proxyPort) {
+ this.proxyPort = proxyPort;
+ }
+
+ public String getRegion() {
+ return region;
+ }
+
+ /**
+ * The region in which the Polly client needs to work. When using this parameter, the configuration will expect the
+ * lowercase name of the region (for example, ap-east-1) You'll need to use the name Region.EU_WEST_1.id()
+ */
+ public void setRegion(String region) {
+ this.region = region;
+ }
+
+ public VoiceId getVoiceId() {
+ return voiceId;
+ }
+
+ /**
+ * The voice ID to use for speech synthesis. If not set, it must be provided as a header.
+ */
+ public void setVoiceId(VoiceId voiceId) {
+ this.voiceId = voiceId;
+ }
+
+ public OutputFormat getOutputFormat() {
+ return outputFormat;
+ }
+
+ /**
+ * The audio format in which the resulting stream will be encoded
+ */
+ public void setOutputFormat(OutputFormat outputFormat) {
+ this.outputFormat = outputFormat;
+ }
+
+ public TextType getTextType() {
+ return textType;
+ }
+
+ /**
+ * Specifies whether the input text is plain text or SSML
+ */
+ public void setTextType(TextType textType) {
+ this.textType = textType;
+ }
+
+ public Engine getEngine() {
+ return engine;
+ }
+
+ /**
+ * Specifies the engine (standard, neural, long-form, generative) for Amazon Polly to use when processing input text
+ * for speech synthesis
+ */
+ public void setEngine(Engine engine) {
+ this.engine = engine;
+ }
+
+ public String getSampleRate() {
+ return sampleRate;
+ }
+
+ /**
+ * The audio frequency in Hz
+ */
+ public void setSampleRate(String sampleRate) {
+ this.sampleRate = sampleRate;
+ }
+
+ public String getLanguageCode() {
+ return languageCode;
+ }
+
+ /**
+ * Optional language code for voice synthesis. This is only necessary if using a bilingual voice.
+ */
+ public void setLanguageCode(String languageCode) {
+ this.languageCode = languageCode;
+ }
+
+ public String getLexiconNames() {
+ return lexiconNames;
+ }
+
+ /**
+ * Comma-separated list of lexicon names to apply during synthesis
+ */
+ public void setLexiconNames(String lexiconNames) {
+ this.lexiconNames = lexiconNames;
+ }
+
+ public boolean isPojoRequest() {
+ return pojoRequest;
+ }
+
+ /**
+ * If we want to use a POJO request as body or not
+ */
+ public void setPojoRequest(boolean pojoRequest) {
+ this.pojoRequest = pojoRequest;
+ }
+
+ public boolean isTrustAllCertificates() {
+ return trustAllCertificates;
+ }
+
+ /**
+ * If we want to trust all certificates in case of overriding the endpoint
+ */
+ public void setTrustAllCertificates(boolean trustAllCertificates) {
+ this.trustAllCertificates = trustAllCertificates;
+ }
+
+ public boolean isOverrideEndpoint() {
+ return overrideEndpoint;
+ }
+
+ /**
+ * Set the need for overriding the endpoint. This option needs to be used in combination with the
+ * uriEndpointOverride option
+ */
+ public void setOverrideEndpoint(boolean overrideEndpoint) {
+ this.overrideEndpoint = overrideEndpoint;
+ }
+
+ public String getUriEndpointOverride() {
+ return uriEndpointOverride;
+ }
+
+ /**
+ * Set the overriding uri endpoint. This option needs to be used in combination with overrideEndpoint option
+ */
+ public void setUriEndpointOverride(String uriEndpointOverride) {
+ this.uriEndpointOverride = uriEndpointOverride;
+ }
+
+ /**
+ * Set whether the Polly client should expect to load credentials through a default credentials provider or to
+ * expect static credentials to be passed in.
+ */
+ public void setUseDefaultCredentialsProvider(Boolean useDefaultCredentialsProvider) {
+ this.useDefaultCredentialsProvider = useDefaultCredentialsProvider;
+ }
+
+ public boolean isUseDefaultCredentialsProvider() {
+ return useDefaultCredentialsProvider;
+ }
+
+ public boolean isUseProfileCredentialsProvider() {
+ return useProfileCredentialsProvider;
+ }
+
+ /**
+ * Set whether the Polly client should expect to load credentials through a profile credentials provider.
+ */
+ public void setUseProfileCredentialsProvider(boolean useProfileCredentialsProvider) {
+ this.useProfileCredentialsProvider = useProfileCredentialsProvider;
+ }
+
+ public boolean isUseSessionCredentials() {
+ return useSessionCredentials;
+ }
+
+ /**
+ * Set whether the Polly client should expect to use Session Credentials. This is useful in a situation in which the
+ * user needs to assume an IAM role for doing operations in Polly.
+ */
+ public void setUseSessionCredentials(boolean useSessionCredentials) {
+ this.useSessionCredentials = useSessionCredentials;
+ }
+
+ public String getProfileCredentialsName() {
+ return profileCredentialsName;
+ }
+
+ /**
+ * If using a profile credentials provider, this parameter will set the profile name
+ */
+ public void setProfileCredentialsName(String profileCredentialsName) {
+ this.profileCredentialsName = profileCredentialsName;
+ }
+ // *************************************************
+ //
+ // *************************************************
+
+ public Polly2Configuration copy() {
+ try {
+ return (Polly2Configuration) super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeCamelException(e);
+ }
+ }
+}
diff --git a/components/camel-aws/camel-aws2-polly/src/main/java/org/apache/camel/component/aws2/polly/Polly2Constants.java b/components/camel-aws/camel-aws2-polly/src/main/java/org/apache/camel/component/aws2/polly/Polly2Constants.java
new file mode 100644
index 000000000000..41e3a66632a5
--- /dev/null
+++ b/components/camel-aws/camel-aws2-polly/src/main/java/org/apache/camel/component/aws2/polly/Polly2Constants.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.aws2.polly;
+
+import org.apache.camel.spi.Metadata;
+
+/**
+ * Constants used in Camel AWS2 Polly module
+ */
+public interface Polly2Constants {
+ @Metadata(description = "The operation we want to perform", javaType = "String")
+ String OPERATION = "CamelAwsPollyOperation";
+ @Metadata(description = "The voice ID to use for synthesis",
+ javaType = "software.amazon.awssdk.services.polly.model.VoiceId")
+ String VOICE_ID = "CamelAwsPollyVoiceId";
+ @Metadata(description = "The output format for the audio stream",
+ javaType = "software.amazon.awssdk.services.polly.model.OutputFormat")
+ String OUTPUT_FORMAT = "CamelAwsPollyOutputFormat";
+ @Metadata(description = "The type of text input (text or ssml)",
+ javaType = "software.amazon.awssdk.services.polly.model.TextType")
+ String TEXT_TYPE = "CamelAwsPollyTextType";
+ @Metadata(description = "The sample rate in Hz", javaType = "String")
+ String SAMPLE_RATE = "CamelAwsPollySampleRate";
+ @Metadata(description = "The engine to use (standard, neural, long-form, generative)",
+ javaType = "software.amazon.awssdk.services.polly.model.Engine")
+ String ENGINE = "CamelAwsPollyEngine";
+ @Metadata(description = "The language code", javaType = "String")
+ String LANGUAGE_CODE = "CamelAwsPollyLanguageCode";
+ @Metadata(description = "Comma-separated list of lexicon names", javaType = "String")
+ String LEXICON_NAMES = "CamelAwsPollyLexiconNames";
+ @Metadata(description = "The name of the lexicon", javaType = "String")
+ String LEXICON_NAME = "CamelAwsPollyLexiconName";
+ @Metadata(description = "The content of the lexicon in PLS format", javaType = "String")
+ String LEXICON_CONTENT = "CamelAwsPollyLexiconContent";
+ @Metadata(description = "The task ID for speech synthesis task", javaType = "String")
+ String TASK_ID = "CamelAwsPollyTaskId";
+ @Metadata(description = "The S3 bucket name for output", javaType = "String")
+ String S3_BUCKET = "CamelAwsPollyS3Bucket";
+ @Metadata(description = "The S3 key prefix for output", javaType = "String")
+ String S3_KEY_PREFIX = "CamelAwsPollyS3KeyPrefix";
+ @Metadata(description = "The SNS topic ARN for notifications", javaType = "String")
+ String SNS_TOPIC_ARN = "CamelAwsPollySnsTopicArn";
+ @Metadata(description = "The content type of the audio stream", javaType = "String")
+ String CONTENT_TYPE = "CamelAwsPollyContentType";
+ @Metadata(description = "Number of characters synthesized", javaType = "Integer")
+ String REQUEST_CHARACTERS = "CamelAwsPollyRequestCharacters";
+}
diff --git a/components/camel-aws/camel-aws2-polly/src/main/java/org/apache/camel/component/aws2/polly/Polly2Endpoint.java b/components/camel-aws/camel-aws2-polly/src/main/java/org/apache/camel/component/aws2/polly/Polly2Endpoint.java
new file mode 100644
index 000000000000..d9507dd51de9
--- /dev/null
+++ b/components/camel-aws/camel-aws2-polly/src/main/java/org/apache/camel/component/aws2/polly/Polly2Endpoint.java
@@ -0,0 +1,108 @@
+/*
+ * 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.aws2.polly;
+
+import org.apache.camel.Category;
+import org.apache.camel.Component;
+import org.apache.camel.Consumer;
+import org.apache.camel.Processor;
+import org.apache.camel.Producer;
+import org.apache.camel.component.aws2.polly.client.Polly2ClientFactory;
+import org.apache.camel.spi.EndpointServiceLocation;
+import org.apache.camel.spi.UriEndpoint;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.support.ScheduledPollEndpoint;
+import org.apache.camel.util.ObjectHelper;
+import software.amazon.awssdk.services.polly.PollyClient;
+
+/**
+ * Synthesize speech using AWS Polly and AWS SDK version 2.x.
+ */
+@UriEndpoint(firstVersion = "4.18.0", scheme = "aws2-polly", title = "AWS Polly", syntax = "aws2-polly:label",
+ producerOnly = true, category = { Category.CLOUD, Category.AI }, headersClass = Polly2Constants.class)
+public class Polly2Endpoint extends ScheduledPollEndpoint implements EndpointServiceLocation {
+
+ private PollyClient pollyClient;
+
+ @UriParam
+ private Polly2Configuration configuration;
+
+ public Polly2Endpoint(String uri, Component component, Polly2Configuration configuration) {
+ super(uri, component);
+ this.configuration = configuration;
+ }
+
+ @Override
+ public Consumer createConsumer(Processor processor) throws Exception {
+ throw new UnsupportedOperationException("You cannot receive messages from this endpoint");
+ }
+
+ @Override
+ public Producer createProducer() throws Exception {
+ return new Polly2Producer(this);
+ }
+
+ @Override
+ public Polly2Component getComponent() {
+ return (Polly2Component) super.getComponent();
+ }
+
+ @Override
+ public void doStart() throws Exception {
+ super.doStart();
+
+ pollyClient
+ = configuration.getPollyClient() != null
+ ? configuration.getPollyClient()
+ : Polly2ClientFactory.getPollyClient(configuration);
+ }
+
+ @Override
+ public void doStop() throws Exception {
+ if (ObjectHelper.isEmpty(configuration.getPollyClient())) {
+ if (pollyClient != null) {
+ pollyClient.close();
+ }
+ }
+ super.doStop();
+ }
+
+ public Polly2Configuration getConfiguration() {
+ return configuration;
+ }
+
+ public PollyClient getPollyClient() {
+ return pollyClient;
+ }
+
+ @Override
+ public String getServiceUrl() {
+ if (!configuration.isOverrideEndpoint()) {
+ if (ObjectHelper.isNotEmpty(configuration.getRegion())) {
+ return configuration.getRegion();
+ }
+ } else if (ObjectHelper.isNotEmpty(configuration.getUriEndpointOverride())) {
+ return configuration.getUriEndpointOverride();
+ }
+ return null;
+ }
+
+ @Override
+ public String getServiceProtocol() {
+ return "polly";
+ }
+}
diff --git a/components/camel-aws/camel-aws2-polly/src/main/java/org/apache/camel/component/aws2/polly/Polly2Operations.java b/components/camel-aws/camel-aws2-polly/src/main/java/org/apache/camel/component/aws2/polly/Polly2Operations.java
new file mode 100644
index 000000000000..54a27e6cd844
--- /dev/null
+++ b/components/camel-aws/camel-aws2-polly/src/main/java/org/apache/camel/component/aws2/polly/Polly2Operations.java
@@ -0,0 +1,30 @@
+/*
+ * 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.aws2.polly;
+
+public enum Polly2Operations {
+
+ synthesizeSpeech,
+ describeVoices,
+ listLexicons,
+ getLexicon,
+ putLexicon,
+ deleteLexicon,
+ startSpeechSynthesisTask,
+ getSpeechSynthesisTask,
+ listSpeechSynthesisTasks
+}
diff --git a/components/camel-aws/camel-aws2-polly/src/main/java/org/apache/camel/component/aws2/polly/Polly2Producer.java b/components/camel-aws/camel-aws2-polly/src/main/java/org/apache/camel/component/aws2/polly/Polly2Producer.java
new file mode 100644
index 000000000000..bdbd4a80e96b
--- /dev/null
+++ b/components/camel-aws/camel-aws2-polly/src/main/java/org/apache/camel/component/aws2/polly/Polly2Producer.java
@@ -0,0 +1,624 @@
+/*
+ * 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.aws2.polly;
+
+import java.util.Arrays;
+
+import org.apache.camel.Endpoint;
+import org.apache.camel.Exchange;
+import org.apache.camel.InvalidPayloadException;
+import org.apache.camel.Message;
+import org.apache.camel.health.HealthCheck;
+import org.apache.camel.health.HealthCheckHelper;
+import org.apache.camel.health.WritableHealthCheckRepository;
+import org.apache.camel.support.DefaultProducer;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.URISupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import software.amazon.awssdk.awscore.exception.AwsServiceException;
+import software.amazon.awssdk.core.ResponseInputStream;
+import software.amazon.awssdk.services.polly.PollyClient;
+import software.amazon.awssdk.services.polly.model.DeleteLexiconRequest;
+import software.amazon.awssdk.services.polly.model.DeleteLexiconResponse;
+import software.amazon.awssdk.services.polly.model.DescribeVoicesRequest;
+import software.amazon.awssdk.services.polly.model.DescribeVoicesResponse;
+import software.amazon.awssdk.services.polly.model.Engine;
+import software.amazon.awssdk.services.polly.model.GetLexiconRequest;
+import software.amazon.awssdk.services.polly.model.GetLexiconResponse;
+import software.amazon.awssdk.services.polly.model.GetSpeechSynthesisTaskRequest;
+import software.amazon.awssdk.services.polly.model.GetSpeechSynthesisTaskResponse;
+import software.amazon.awssdk.services.polly.model.ListLexiconsRequest;
+import software.amazon.awssdk.services.polly.model.ListLexiconsResponse;
+import software.amazon.awssdk.services.polly.model.ListSpeechSynthesisTasksRequest;
+import software.amazon.awssdk.services.polly.model.ListSpeechSynthesisTasksResponse;
+import software.amazon.awssdk.services.polly.model.OutputFormat;
+import software.amazon.awssdk.services.polly.model.PutLexiconRequest;
+import software.amazon.awssdk.services.polly.model.PutLexiconResponse;
+import software.amazon.awssdk.services.polly.model.StartSpeechSynthesisTaskRequest;
+import software.amazon.awssdk.services.polly.model.StartSpeechSynthesisTaskResponse;
+import software.amazon.awssdk.services.polly.model.SynthesizeSpeechRequest;
+import software.amazon.awssdk.services.polly.model.SynthesizeSpeechResponse;
+import software.amazon.awssdk.services.polly.model.TextType;
+import software.amazon.awssdk.services.polly.model.VoiceId;
+
+/**
+ * A Producer which sends messages to the Amazon Polly Service SDK v2 <a href="http://aws.amazon.com/polly/">AWS
+ * Polly</a>
+ */
+public class Polly2Producer extends DefaultProducer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(Polly2Producer.class);
+ private transient String pollyProducerToString;
+ private HealthCheck producerHealthCheck;
+ private WritableHealthCheckRepository healthCheckRepository;
+
+ public Polly2Producer(Endpoint endpoint) {
+ super(endpoint);
+ }
+
+ @Override
+ public void process(Exchange exchange) throws Exception {
+ switch (determineOperation(exchange)) {
+ case synthesizeSpeech:
+ synthesizeSpeech(getEndpoint().getPollyClient(), exchange);
+ break;
+ case describeVoices:
+ describeVoices(getEndpoint().getPollyClient(), exchange);
+ break;
+ case listLexicons:
+ listLexicons(getEndpoint().getPollyClient(), exchange);
+ break;
+ case getLexicon:
+ getLexicon(getEndpoint().getPollyClient(), exchange);
+ break;
+ case putLexicon:
+ putLexicon(getEndpoint().getPollyClient(), exchange);
+ break;
+ case deleteLexicon:
+ deleteLexicon(getEndpoint().getPollyClient(), exchange);
+ break;
+ case startSpeechSynthesisTask:
+ startSpeechSynthesisTask(getEndpoint().getPollyClient(), exchange);
+ break;
+ case getSpeechSynthesisTask:
+ getSpeechSynthesisTask(getEndpoint().getPollyClient(), exchange);
+ break;
+ case listSpeechSynthesisTasks:
+ listSpeechSynthesisTasks(getEndpoint().getPollyClient(), exchange);
+ break;
+ default:
+ throw new IllegalArgumentException("Unsupported operation");
+ }
+ }
+
+ private Polly2Operations determineOperation(Exchange exchange) {
+ Polly2Operations operation = exchange.getIn().getHeader(Polly2Constants.OPERATION, Polly2Operations.class);
+ if (operation == null) {
+ operation = getConfiguration().getOperation();
+ }
+ return operation;
+ }
+
+ protected Polly2Configuration getConfiguration() {
+ return getEndpoint().getConfiguration();
+ }
+
+ @Override
+ public String toString() {
+ if (pollyProducerToString == null) {
+ pollyProducerToString = "PollyProducer[" + URISupport.sanitizeUri(getEndpoint().getEndpointUri()) + "]";
+ }
+ return pollyProducerToString;
+ }
+
+ @Override
+ public Polly2Endpoint getEndpoint() {
+ return (Polly2Endpoint) super.getEndpoint();
+ }
+
+ private void synthesizeSpeech(PollyClient pollyClient, Exchange exchange) throws InvalidPayloadException {
+ if (getConfiguration().isPojoRequest()) {
+ Object payload = exchange.getIn().getMandatoryBody();
+ if (payload instanceof SynthesizeSpeechRequest) {
+ ResponseInputStream<SynthesizeSpeechResponse> result;
+ try {
+ result = pollyClient.synthesizeSpeech((SynthesizeSpeechRequest) payload);
+ } catch (AwsServiceException ase) {
+ LOG.trace("Synthesize Speech command returned the error code {}", ase.awsErrorDetails().errorCode());
+ throw ase;
+ }
+ Message message = getMessageForResponse(exchange);
+ message.setBody(result);
+ if (result.response().contentType() != null) {
+ message.setHeader(Polly2Constants.CONTENT_TYPE, result.response().contentType());
+ }
+ message.setHeader(Polly2Constants.REQUEST_CHARACTERS, result.response().requestCharacters());
+ }
+ } else {
+ SynthesizeSpeechRequest.Builder request = SynthesizeSpeechRequest.builder();
+
+ // Set voice ID
+ VoiceId voiceId = exchange.getIn().getHeader(Polly2Constants.VOICE_ID, VoiceId.class);
+ if (voiceId == null) {
+ voiceId = getConfiguration().getVoiceId();
+ }
+ if (voiceId == null) {
+ throw new IllegalArgumentException("Voice ID must be specified as header or endpoint option");
+ }
+ request.voiceId(voiceId);
+
+ // Set output format
+ OutputFormat outputFormat = exchange.getIn().getHeader(Polly2Constants.OUTPUT_FORMAT, OutputFormat.class);
+ if (outputFormat == null) {
+ outputFormat = getConfiguration().getOutputFormat();
+ }
+ request.outputFormat(outputFormat);
+
+ // Set text type
+ TextType textType = exchange.getIn().getHeader(Polly2Constants.TEXT_TYPE, TextType.class);
+ if (textType == null) {
+ textType = getConfiguration().getTextType();
+ }
+ request.textType(textType);
+
+ // Set engine
+ Engine engine = exchange.getIn().getHeader(Polly2Constants.ENGINE, Engine.class);
+ if (engine == null && getConfiguration().getEngine() != null) {
+ engine = getConfiguration().getEngine();
+ }
+ if (engine != null) {
+ request.engine(engine);
+ }
+
+ // Set sample rate
+ String sampleRate = exchange.getIn().getHeader(Polly2Constants.SAMPLE_RATE, String.class);
+ if (sampleRate == null) {
+ sampleRate = getConfiguration().getSampleRate();
+ }
+ if (sampleRate != null) {
+ request.sampleRate(sampleRate);
+ }
+
+ // Set language code
+ String languageCode = exchange.getIn().getHeader(Polly2Constants.LANGUAGE_CODE, String.class);
+ if (languageCode == null) {
+ languageCode = getConfiguration().getLanguageCode();
+ }
+ if (languageCode != null) {
+ request.languageCode(languageCode);
+ }
+
+ // Set lexicon names
+ String lexiconNames = exchange.getIn().getHeader(Polly2Constants.LEXICON_NAMES, String.class);
+ if (lexiconNames == null) {
+ lexiconNames = getConfiguration().getLexiconNames();
+ }
+ if (lexiconNames != null) {
+ request.lexiconNames(Arrays.asList(lexiconNames.split(",")));
+ }
+
+ // Set the text to synthesize
+ request.text(exchange.getMessage().getBody(String.class));
+
+ ResponseInputStream<SynthesizeSpeechResponse> result;
+ try {
+ result = pollyClient.synthesizeSpeech(request.build());
+ } catch (AwsServiceException ase) {
+ LOG.trace("Synthesize Speech command returned the error code {}", ase.awsErrorDetails().errorCode());
+ throw ase;
+ }
+ Message message = getMessageForResponse(exchange);
+ message.setBody(result);
+ if (result.response().contentType() != null) {
+ message.setHeader(Polly2Constants.CONTENT_TYPE, result.response().contentType());
+ }
+ message.setHeader(Polly2Constants.REQUEST_CHARACTERS, result.response().requestCharacters());
+ }
+ }
+
+ private void describeVoices(PollyClient pollyClient, Exchange exchange) throws InvalidPayloadException {
+ if (getConfiguration().isPojoRequest()) {
+ Object payload = exchange.getIn().getMandatoryBody();
+ if (payload instanceof DescribeVoicesRequest) {
+ DescribeVoicesResponse result;
+ try {
+ result = pollyClient.describeVoices((DescribeVoicesRequest) payload);
+ } catch (AwsServiceException ase) {
+ LOG.trace("Describe Voices command returned the error code {}", ase.awsErrorDetails().errorCode());
+ throw ase;
+ }
+ Message message = getMessageForResponse(exchange);
+ message.setBody(result.voices());
+ }
+ } else {
+ DescribeVoicesRequest.Builder request = DescribeVoicesRequest.builder();
+
+ // Set engine filter
+ Engine engine = exchange.getIn().getHeader(Polly2Constants.ENGINE, Engine.class);
+ if (engine == null && getConfiguration().getEngine() != null) {
+ engine = getConfiguration().getEngine();
+ }
+ if (engine != null) {
+ request.engine(engine);
+ }
+
+ // Set language code filter
+ String languageCode = exchange.getIn().getHeader(Polly2Constants.LANGUAGE_CODE, String.class);
+ if (languageCode == null) {
+ languageCode = getConfiguration().getLanguageCode();
+ }
+ if (languageCode != null) {
+ request.languageCode(languageCode);
+ }
+
+ DescribeVoicesResponse result;
+ try {
+ result = pollyClient.describeVoices(request.build());
+ } catch (AwsServiceException ase) {
+ LOG.trace("Describe Voices command returned the error code {}", ase.awsErrorDetails().errorCode());
+ throw ase;
+ }
+ Message message = getMessageForResponse(exchange);
+ message.setBody(result.voices());
+ }
+ }
+
+ private void listLexicons(PollyClient pollyClient, Exchange exchange) throws InvalidPayloadException {
+ if (getConfiguration().isPojoRequest()) {
+ Object payload = exchange.getIn().getMandatoryBody();
+ if (payload instanceof ListLexiconsRequest) {
+ ListLexiconsResponse result;
+ try {
+ result = pollyClient.listLexicons((ListLexiconsRequest) payload);
+ } catch (AwsServiceException ase) {
+ LOG.trace("List Lexicons command returned the error code {}", ase.awsErrorDetails().errorCode());
+ throw ase;
+ }
+ Message message = getMessageForResponse(exchange);
+ message.setBody(result.lexicons());
+ }
+ } else {
+ ListLexiconsRequest request = ListLexiconsRequest.builder().build();
+ ListLexiconsResponse result;
+ try {
+ result = pollyClient.listLexicons(request);
+ } catch (AwsServiceException ase) {
+ LOG.trace("List Lexicons command returned the error code {}", ase.awsErrorDetails().errorCode());
+ throw ase;
+ }
+ Message message = getMessageForResponse(exchange);
+ message.setBody(result.lexicons());
+ }
+ }
+
+ private void getLexicon(PollyClient pollyClient, Exchange exchange) throws InvalidPayloadException {
+ if (getConfiguration().isPojoRequest()) {
+ Object payload = exchange.getIn().getMandatoryBody();
+ if (payload instanceof GetLexiconRequest) {
+ GetLexiconResponse result;
+ try {
+ result = pollyClient.getLexicon((GetLexiconRequest) payload);
+ } catch (AwsServiceException ase) {
+ LOG.trace("Get Lexicon command returned the error code {}", ase.awsErrorDetails().errorCode());
+ throw ase;
+ }
+ Message message = getMessageForResponse(exchange);
+ message.setBody(result.lexicon());
+ }
+ } else {
+ String lexiconName = exchange.getIn().getHeader(Polly2Constants.LEXICON_NAME, String.class);
+ if (ObjectHelper.isEmpty(lexiconName)) {
+ throw new IllegalArgumentException("Lexicon name must be specified");
+ }
+ GetLexiconRequest request = GetLexiconRequest.builder().name(lexiconName).build();
+ GetLexiconResponse result;
+ try {
+ result = pollyClient.getLexicon(request);
+ } catch (AwsServiceException ase) {
+ LOG.trace("Get Lexicon command returned the error code {}", ase.awsErrorDetails().errorCode());
+ throw ase;
+ }
+ Message message = getMessageForResponse(exchange);
+ message.setBody(result.lexicon());
+ }
+ }
+
+ private void putLexicon(PollyClient pollyClient, Exchange exchange) throws InvalidPayloadException {
+ if (getConfiguration().isPojoRequest()) {
+ Object payload = exchange.getIn().getMandatoryBody();
+ if (payload instanceof PutLexiconRequest) {
+ PutLexiconResponse result;
+ try {
+ result = pollyClient.putLexicon((PutLexiconRequest) payload);
+ } catch (AwsServiceException ase) {
+ LOG.trace("Put Lexicon command returned the error code {}", ase.awsErrorDetails().errorCode());
+ throw ase;
+ }
+ Message message = getMessageForResponse(exchange);
+ message.setBody(result);
+ }
+ } else {
+ String lexiconName = exchange.getIn().getHeader(Polly2Constants.LEXICON_NAME, String.class);
+ String lexiconContent = exchange.getIn().getHeader(Polly2Constants.LEXICON_CONTENT, String.class);
+ if (ObjectHelper.isEmpty(lexiconContent)) {
+ lexiconContent = exchange.getMessage().getBody(String.class);
+ }
+ if (ObjectHelper.isEmpty(lexiconName)) {
+ throw new IllegalArgumentException("Lexicon name must be specified");
+ }
+ if (ObjectHelper.isEmpty(lexiconContent)) {
+ throw new IllegalArgumentException("Lexicon content must be specified");
+ }
+ PutLexiconRequest request = PutLexiconRequest.builder()
+ .name(lexiconName)
+ .content(lexiconContent)
+ .build();
+ PutLexiconResponse result;
+ try {
+ result = pollyClient.putLexicon(request);
+ } catch (AwsServiceException ase) {
+ LOG.trace("Put Lexicon command returned the error code {}", ase.awsErrorDetails().errorCode());
+ throw ase;
+ }
+ Message message = getMessageForResponse(exchange);
+ message.setBody(result);
+ }
+ }
+
+ private void deleteLexicon(PollyClient pollyClient, Exchange exchange) throws InvalidPayloadException {
+ if (getConfiguration().isPojoRequest()) {
+ Object payload = exchange.getIn().getMandatoryBody();
+ if (payload instanceof DeleteLexiconRequest) {
+ DeleteLexiconResponse result;
+ try {
+ result = pollyClient.deleteLexicon((DeleteLexiconRequest) payload);
+ } catch (AwsServiceException ase) {
+ LOG.trace("Delete Lexicon command returned the error code {}", ase.awsErrorDetails().errorCode());
+ throw ase;
+ }
+ Message message = getMessageForResponse(exchange);
+ message.setBody(result);
+ }
+ } else {
+ String lexiconName = exchange.getIn().getHeader(Polly2Constants.LEXICON_NAME, String.class);
+ if (ObjectHelper.isEmpty(lexiconName)) {
+ throw new IllegalArgumentException("Lexicon name must be specified");
+ }
+ DeleteLexiconRequest request = DeleteLexiconRequest.builder().name(lexiconName).build();
+ DeleteLexiconResponse result;
+ try {
+ result = pollyClient.deleteLexicon(request);
+ } catch (AwsServiceException ase) {
+ LOG.trace("Delete Lexicon command returned the error code {}", ase.awsErrorDetails().errorCode());
+ throw ase;
+ }
+ Message message = getMessageForResponse(exchange);
+ message.setBody(result);
+ }
+ }
+
+ private void startSpeechSynthesisTask(PollyClient pollyClient, Exchange exchange) throws InvalidPayloadException {
+ if (getConfiguration().isPojoRequest()) {
+ Object payload = exchange.getIn().getMandatoryBody();
+ if (payload instanceof StartSpeechSynthesisTaskRequest) {
+ StartSpeechSynthesisTaskResponse result;
+ try {
+ result = pollyClient.startSpeechSynthesisTask((StartSpeechSynthesisTaskRequest) payload);
+ } catch (AwsServiceException ase) {
+ LOG.trace("Start Speech Synthesis Task command returned the error code {}",
+ ase.awsErrorDetails().errorCode());
+ throw ase;
+ }
+ Message message = getMessageForResponse(exchange);
+ message.setBody(result.synthesisTask());
+ message.setHeader(Polly2Constants.TASK_ID, result.synthesisTask().taskId());
+ }
+ } else {
+ StartSpeechSynthesisTaskRequest.Builder request = StartSpeechSynthesisTaskRequest.builder();
+
+ // Set voice ID
+ VoiceId voiceId = exchange.getIn().getHeader(Polly2Constants.VOICE_ID, VoiceId.class);
+ if (voiceId == null) {
+ voiceId = getConfiguration().getVoiceId();
+ }
+ if (voiceId == null) {
+ throw new IllegalArgumentException("Voice ID must be specified as header or endpoint option");
+ }
+ request.voiceId(voiceId);
+
+ // Set output format
+ OutputFormat outputFormat = exchange.getIn().getHeader(Polly2Constants.OUTPUT_FORMAT, OutputFormat.class);
+ if (outputFormat == null) {
+ outputFormat = getConfiguration().getOutputFormat();
+ }
+ request.outputFormat(outputFormat);
+
+ // Set S3 bucket
+ String s3Bucket = exchange.getIn().getHeader(Polly2Constants.S3_BUCKET, String.class);
+ if (ObjectHelper.isEmpty(s3Bucket)) {
+ throw new IllegalArgumentException("S3 bucket must be specified for async synthesis");
+ }
+ request.outputS3BucketName(s3Bucket);
+
+ // Set S3 key prefix (optional)
+ String s3KeyPrefix = exchange.getIn().getHeader(Polly2Constants.S3_KEY_PREFIX, String.class);
+ if (ObjectHelper.isNotEmpty(s3KeyPrefix)) {
+ request.outputS3KeyPrefix(s3KeyPrefix);
+ }
+
+ // Set SNS topic ARN (optional)
+ String snsTopicArn = exchange.getIn().getHeader(Polly2Constants.SNS_TOPIC_ARN, String.class);
+ if (ObjectHelper.isNotEmpty(snsTopicArn)) {
+ request.snsTopicArn(snsTopicArn);
+ }
+
+ // Set text type
+ TextType textType = exchange.getIn().getHeader(Polly2Constants.TEXT_TYPE, TextType.class);
+ if (textType == null) {
+ textType = getConfiguration().getTextType();
+ }
+ request.textType(textType);
+
+ // Set engine
+ Engine engine = exchange.getIn().getHeader(Polly2Constants.ENGINE, Engine.class);
+ if (engine == null && getConfiguration().getEngine() != null) {
+ engine = getConfiguration().getEngine();
+ }
+ if (engine != null) {
+ request.engine(engine);
+ }
+
+ // Set sample rate
+ String sampleRate = exchange.getIn().getHeader(Polly2Constants.SAMPLE_RATE, String.class);
+ if (sampleRate == null) {
+ sampleRate = getConfiguration().getSampleRate();
+ }
+ if (sampleRate != null) {
+ request.sampleRate(sampleRate);
+ }
+
+ // Set language code
+ String languageCode = exchange.getIn().getHeader(Polly2Constants.LANGUAGE_CODE, String.class);
+ if (languageCode == null) {
+ languageCode = getConfiguration().getLanguageCode();
+ }
+ if (languageCode != null) {
+ request.languageCode(languageCode);
+ }
+
+ // Set lexicon names
+ String lexiconNames = exchange.getIn().getHeader(Polly2Constants.LEXICON_NAMES, String.class);
+ if (lexiconNames == null) {
+ lexiconNames = getConfiguration().getLexiconNames();
+ }
+ if (lexiconNames != null) {
+ request.lexiconNames(Arrays.asList(lexiconNames.split(",")));
+ }
+
+ // Set the text to synthesize
+ request.text(exchange.getMessage().getBody(String.class));
+
+ StartSpeechSynthesisTaskResponse result;
+ try {
+ result = pollyClient.startSpeechSynthesisTask(request.build());
+ } catch (AwsServiceException ase) {
+ LOG.trace("Start Speech Synthesis Task command returned the error code {}",
+ ase.awsErrorDetails().errorCode());
+ throw ase;
+ }
+ Message message = getMessageForResponse(exchange);
+ message.setBody(result.synthesisTask());
+ message.setHeader(Polly2Constants.TASK_ID, result.synthesisTask().taskId());
+ }
+ }
+
+ private void getSpeechSynthesisTask(PollyClient pollyClient, Exchange exchange) throws InvalidPayloadException {
+ if (getConfiguration().isPojoRequest()) {
+ Object payload = exchange.getIn().getMandatoryBody();
+ if (payload instanceof GetSpeechSynthesisTaskRequest) {
+ GetSpeechSynthesisTaskResponse result;
+ try {
+ result = pollyClient.getSpeechSynthesisTask((GetSpeechSynthesisTaskRequest) payload);
+ } catch (AwsServiceException ase) {
+ LOG.trace("Get Speech Synthesis Task command returned the error code {}",
+ ase.awsErrorDetails().errorCode());
+ throw ase;
+ }
+ Message message = getMessageForResponse(exchange);
+ message.setBody(result.synthesisTask());
+ }
+ } else {
+ String taskId = exchange.getIn().getHeader(Polly2Constants.TASK_ID, String.class);
+ if (ObjectHelper.isEmpty(taskId)) {
+ throw new IllegalArgumentException("Task ID must be specified");
+ }
+ GetSpeechSynthesisTaskRequest request = GetSpeechSynthesisTaskRequest.builder()
+ .taskId(taskId)
+ .build();
+ GetSpeechSynthesisTaskResponse result;
+ try {
+ result = pollyClient.getSpeechSynthesisTask(request);
+ } catch (AwsServiceException ase) {
+ LOG.trace("Get Speech Synthesis Task command returned the error code {}",
+ ase.awsErrorDetails().errorCode());
+ throw ase;
+ }
+ Message message = getMessageForResponse(exchange);
+ message.setBody(result.synthesisTask());
+ }
+ }
+
+ private void listSpeechSynthesisTasks(PollyClient pollyClient, Exchange exchange) throws InvalidPayloadException {
+ if (getConfiguration().isPojoRequest()) {
+ Object payload = exchange.getIn().getMandatoryBody();
+ if (payload instanceof ListSpeechSynthesisTasksRequest) {
+ ListSpeechSynthesisTasksResponse result;
+ try {
+ result = pollyClient.listSpeechSynthesisTasks((ListSpeechSynthesisTasksRequest) payload);
+ } catch (AwsServiceException ase) {
+ LOG.trace("List Speech Synthesis Tasks command returned the error code {}",
+ ase.awsErrorDetails().errorCode());
+ throw ase;
+ }
+ Message message = getMessageForResponse(exchange);
+ message.setBody(result.synthesisTasks());
+ }
+ } else {
+ ListSpeechSynthesisTasksRequest request = ListSpeechSynthesisTasksRequest.builder().build();
+ ListSpeechSynthesisTasksResponse result;
+ try {
+ result = pollyClient.listSpeechSynthesisTasks(request);
+ } catch (AwsServiceException ase) {
+ LOG.trace("List Speech Synthesis Tasks command returned the error code {}",
+ ase.awsErrorDetails().errorCode());
+ throw ase;
+ }
+ Message message = getMessageForResponse(exchange);
+ message.setBody(result.synthesisTasks());
+ }
+ }
+
+ public static Message getMessageForResponse(final Exchange exchange) {
+ return exchange.getMessage();
+ }
+
+ @Override
+ protected void doStart() throws Exception {
+ // health-check is optional so discover and resolve
+ healthCheckRepository = HealthCheckHelper.getHealthCheckRepository(
+ getEndpoint().getCamelContext(),
+ "producers",
+ WritableHealthCheckRepository.class);
+
+ if (healthCheckRepository != null) {
+ String id = getEndpoint().getId();
+ producerHealthCheck = new Polly2ProducerHealthCheck(getEndpoint(), id);
+ producerHealthCheck.setEnabled(getEndpoint().getComponent().isHealthCheckProducerEnabled());
+ healthCheckRepository.addHealthCheck(producerHealthCheck);
+ }
+ }
+
+ @Override
+ protected void doStop() throws Exception {
+ if (healthCheckRepository != null && producerHealthCheck != null) {
+ healthCheckRepository.removeHealthCheck(producerHealthCheck);
+ producerHealthCheck = null;
+ }
+ }
+
+}
diff --git a/components/camel-aws/camel-aws2-polly/src/main/java/org/apache/camel/component/aws2/polly/Polly2ProducerHealthCheck.java b/components/camel-aws/camel-aws2-polly/src/main/java/org/apache/camel/component/aws2/polly/Polly2ProducerHealthCheck.java
new file mode 100644
index 000000000000..7cd6205fa8b5
--- /dev/null
+++ b/components/camel-aws/camel-aws2-polly/src/main/java/org/apache/camel/component/aws2/polly/Polly2ProducerHealthCheck.java
@@ -0,0 +1,71 @@
+/*
+ * 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.aws2.polly;
+
+import java.util.Map;
+
+import org.apache.camel.health.HealthCheckResultBuilder;
+import org.apache.camel.impl.health.AbstractHealthCheck;
+import org.apache.camel.util.ObjectHelper;
+import software.amazon.awssdk.awscore.exception.AwsServiceException;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.polly.PollyClient;
+import software.amazon.awssdk.services.polly.model.DescribeVoicesRequest;
+
+public class Polly2ProducerHealthCheck extends AbstractHealthCheck {
+
+ private final Polly2Endpoint polly2Endpoint;
+
+ public Polly2ProducerHealthCheck(Polly2Endpoint polly2Endpoint, String clientId) {
+ super("camel", "producer:aws2-polly-" + clientId);
+ this.polly2Endpoint = polly2Endpoint;
+ }
+
+ @Override
+ protected void doCall(HealthCheckResultBuilder builder, Map<String, Object> options) {
+ Polly2Configuration configuration = polly2Endpoint.getConfiguration();
+ if (ObjectHelper.isNotEmpty(configuration.getRegion())) {
+ if (!PollyClient.serviceMetadata().regions().contains(Region.of(configuration.getRegion()))) {
+ builder.message("The service is not supported in this region");
+ builder.down();
+ return;
+ }
+ }
+ try {
+ PollyClient pollyClient = polly2Endpoint.getPollyClient();
+ pollyClient.describeVoices(DescribeVoicesRequest.builder().build());
+ } catch (AwsServiceException e) {
+ builder.message(e.getMessage());
+ builder.error(e);
+ if (ObjectHelper.isNotEmpty(e.statusCode())) {
+ builder.detail(SERVICE_STATUS_CODE, e.statusCode());
+ }
+ if (ObjectHelper.isNotEmpty(e.awsErrorDetails().errorCode())) {
+ builder.detail(SERVICE_ERROR_CODE, e.awsErrorDetails().errorCode());
+ }
+ builder.down();
+ return;
+ } catch (Exception e) {
+ builder.error(e);
+ builder.down();
+ return;
+ }
+ builder.up();
+ }
+
+}
diff --git a/components/camel-aws/camel-aws2-polly/src/main/java/org/apache/camel/component/aws2/polly/client/Polly2ClientFactory.java b/components/camel-aws/camel-aws2-polly/src/main/java/org/apache/camel/component/aws2/polly/client/Polly2ClientFactory.java
new file mode 100644
index 000000000000..6e378e6a5212
--- /dev/null
+++ b/components/camel-aws/camel-aws2-polly/src/main/java/org/apache/camel/component/aws2/polly/client/Polly2ClientFactory.java
@@ -0,0 +1,42 @@
+/*
+ * 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.aws2.polly.client;
+
+import org.apache.camel.component.aws.common.AwsClientBuilderUtil;
+import org.apache.camel.component.aws2.polly.Polly2Configuration;
+import software.amazon.awssdk.services.polly.PollyClient;
+
+/**
+ * Factory class to create AWS Polly clients using common configuration.
+ */
+public final class Polly2ClientFactory {
+
+ private Polly2ClientFactory() {
+ }
+
+ /**
+ * Create a PollyClient based on configuration.
+ *
+ * @param configuration The Polly configuration
+ * @return Configured PollyClient
+ */
+ public static PollyClient getPollyClient(Polly2Configuration configuration) {
+ return AwsClientBuilderUtil.buildClient(
+ configuration,
+ PollyClient::builder);
+ }
+}
diff --git a/components/camel-aws/camel-aws2-polly/src/test/java/org/apache/camel/component/aws2/polly/AmazonPollyClientMock.java b/components/camel-aws/camel-aws2-polly/src/test/java/org/apache/camel/component/aws2/polly/AmazonPollyClientMock.java
new file mode 100644
index 000000000000..36967ff75da4
--- /dev/null
+++ b/components/camel-aws/camel-aws2-polly/src/test/java/org/apache/camel/component/aws2/polly/AmazonPollyClientMock.java
@@ -0,0 +1,187 @@
+/*
+ * 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.aws2.polly;
+
+import java.io.ByteArrayInputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+
+import software.amazon.awssdk.core.ResponseInputStream;
+import software.amazon.awssdk.http.AbortableInputStream;
+import software.amazon.awssdk.services.polly.PollyClient;
+import software.amazon.awssdk.services.polly.PollyServiceClientConfiguration;
+import software.amazon.awssdk.services.polly.model.DeleteLexiconRequest;
+import software.amazon.awssdk.services.polly.model.DeleteLexiconResponse;
+import software.amazon.awssdk.services.polly.model.DescribeVoicesRequest;
+import software.amazon.awssdk.services.polly.model.DescribeVoicesResponse;
+import software.amazon.awssdk.services.polly.model.Engine;
+import software.amazon.awssdk.services.polly.model.Gender;
+import software.amazon.awssdk.services.polly.model.GetLexiconRequest;
+import software.amazon.awssdk.services.polly.model.GetLexiconResponse;
+import software.amazon.awssdk.services.polly.model.GetSpeechSynthesisTaskRequest;
+import software.amazon.awssdk.services.polly.model.GetSpeechSynthesisTaskResponse;
+import software.amazon.awssdk.services.polly.model.LanguageCode;
+import software.amazon.awssdk.services.polly.model.Lexicon;
+import software.amazon.awssdk.services.polly.model.LexiconDescription;
+import software.amazon.awssdk.services.polly.model.ListLexiconsRequest;
+import software.amazon.awssdk.services.polly.model.ListLexiconsResponse;
+import software.amazon.awssdk.services.polly.model.ListSpeechSynthesisTasksRequest;
+import software.amazon.awssdk.services.polly.model.ListSpeechSynthesisTasksResponse;
+import software.amazon.awssdk.services.polly.model.OutputFormat;
+import software.amazon.awssdk.services.polly.model.PutLexiconRequest;
+import software.amazon.awssdk.services.polly.model.PutLexiconResponse;
+import software.amazon.awssdk.services.polly.model.StartSpeechSynthesisTaskRequest;
+import software.amazon.awssdk.services.polly.model.StartSpeechSynthesisTaskResponse;
+import software.amazon.awssdk.services.polly.model.SynthesisTask;
+import software.amazon.awssdk.services.polly.model.SynthesizeSpeechRequest;
+import software.amazon.awssdk.services.polly.model.SynthesizeSpeechResponse;
+import software.amazon.awssdk.services.polly.model.TaskStatus;
+import software.amazon.awssdk.services.polly.model.Voice;
+import software.amazon.awssdk.services.polly.model.VoiceId;
+
+public class AmazonPollyClientMock implements PollyClient {
+
+ @Override
+ public ResponseInputStream<SynthesizeSpeechResponse> synthesizeSpeech(SynthesizeSpeechRequest request) {
+ SynthesizeSpeechResponse response = SynthesizeSpeechResponse.builder()
+ .contentType("audio/mpeg")
+ .requestCharacters(request.text().length())
+ .build();
+
+ byte[] audioData = "mock-audio-data".getBytes(StandardCharsets.UTF_8);
+ ByteArrayInputStream inputStream = new ByteArrayInputStream(audioData);
+ AbortableInputStream abortableInputStream = AbortableInputStream.create(inputStream);
+
+ return new ResponseInputStream<>(response, abortableInputStream);
+ }
+
+ @Override
+ public DescribeVoicesResponse describeVoices(DescribeVoicesRequest request) {
+ Voice voice1 = Voice.builder()
+ .id(VoiceId.JOANNA)
+ .name("Joanna")
+ .languageCode(LanguageCode.EN_US)
+ .languageName("US English")
+ .gender(Gender.FEMALE)
+ .supportedEngines(Engine.NEURAL, Engine.STANDARD)
+ .build();
+
+ Voice voice2 = Voice.builder()
+ .id(VoiceId.MATTHEW)
+ .name("Matthew")
+ .languageCode(LanguageCode.EN_US)
+ .languageName("US English")
+ .gender(Gender.MALE)
+ .supportedEngines(Engine.NEURAL, Engine.STANDARD)
+ .build();
+
+ return DescribeVoicesResponse.builder()
+ .voices(Arrays.asList(voice1, voice2))
+ .build();
+ }
+
+ @Override
+ public ListLexiconsResponse listLexicons(ListLexiconsRequest request) {
+ LexiconDescription lexicon = LexiconDescription.builder()
+ .name("TestLexicon")
+ .build();
+
+ return ListLexiconsResponse.builder()
+ .lexicons(Arrays.asList(lexicon))
+ .build();
+ }
+
+ @Override
+ public GetLexiconResponse getLexicon(GetLexiconRequest request) {
+ Lexicon lexicon = Lexicon.builder()
+ .name(request.name())
+ .content("<?xml version=\"1.0\" encoding=\"UTF-8\"?><lexicon></lexicon>")
+ .build();
+
+ return GetLexiconResponse.builder()
+ .lexicon(lexicon)
+ .build();
+ }
+
+ @Override
+ public PutLexiconResponse putLexicon(PutLexiconRequest request) {
+ return PutLexiconResponse.builder().build();
+ }
+
+ @Override
+ public DeleteLexiconResponse deleteLexicon(DeleteLexiconRequest request) {
+ return DeleteLexiconResponse.builder().build();
+ }
+
+ @Override
+ public StartSpeechSynthesisTaskResponse startSpeechSynthesisTask(StartSpeechSynthesisTaskRequest request) {
+ SynthesisTask task = SynthesisTask.builder()
+ .taskId("test-task-id-123")
+ .taskStatus(TaskStatus.IN_PROGRESS)
+ .outputFormat(request.outputFormat())
+ .voiceId(request.voiceId())
+ .outputUri("s3://" + request.outputS3BucketName() + "/output.mp3")
+ .build();
+
+ return StartSpeechSynthesisTaskResponse.builder()
+ .synthesisTask(task)
+ .build();
+ }
+
+ @Override
+ public GetSpeechSynthesisTaskResponse getSpeechSynthesisTask(GetSpeechSynthesisTaskRequest request) {
+ SynthesisTask task = SynthesisTask.builder()
+ .taskId(request.taskId())
+ .taskStatus(TaskStatus.COMPLETED)
+ .outputFormat(OutputFormat.MP3)
+ .voiceId(VoiceId.JOANNA)
+ .outputUri("s3://test-bucket/output.mp3")
+ .build();
+
+ return GetSpeechSynthesisTaskResponse.builder()
+ .synthesisTask(task)
+ .build();
+ }
+
+ @Override
+ public ListSpeechSynthesisTasksResponse listSpeechSynthesisTasks(ListSpeechSynthesisTasksRequest request) {
+ SynthesisTask task = SynthesisTask.builder()
+ .taskId("test-task-id-123")
+ .taskStatus(TaskStatus.COMPLETED)
+ .outputFormat(OutputFormat.MP3)
+ .voiceId(VoiceId.JOANNA)
+ .build();
+
+ return ListSpeechSynthesisTasksResponse.builder()
+ .synthesisTasks(Arrays.asList(task))
+ .build();
+ }
+
+ @Override
+ public PollyServiceClientConfiguration serviceClientConfiguration() {
+ return null;
+ }
+
+ @Override
+ public String serviceName() {
+ return "polly";
+ }
+
+ @Override
+ public void close() {
+ }
+}
diff --git a/components/camel-aws/camel-aws2-polly/src/test/java/org/apache/camel/component/aws2/polly/Polly2ClientFactoryTest.java b/components/camel-aws/camel-aws2-polly/src/test/java/org/apache/camel/component/aws2/polly/Polly2ClientFactoryTest.java
new file mode 100644
index 000000000000..fb9325232b60
--- /dev/null
+++ b/components/camel-aws/camel-aws2-polly/src/test/java/org/apache/camel/component/aws2/polly/Polly2ClientFactoryTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.aws2.polly;
+
+import org.apache.camel.component.aws2.polly.client.Polly2ClientFactory;
+import org.junit.jupiter.api.Test;
+import software.amazon.awssdk.services.polly.PollyClient;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class Polly2ClientFactoryTest {
+
+ @Test
+ public void getClientWithAccessKeyAndSecretKey() {
+ Polly2Configuration configuration = new Polly2Configuration();
+ configuration.setAccessKey("accessKey");
+ configuration.setSecretKey("secretKey");
+ configuration.setRegion("us-east-1");
+
+ PollyClient client = Polly2ClientFactory.getPollyClient(configuration);
+ assertNotNull(client);
+ client.close();
+ }
+
+ @Test
+ public void getClientWithDefaultCredentialsProvider() {
+ Polly2Configuration configuration = new Polly2Configuration();
+ configuration.setUseDefaultCredentialsProvider(true);
+ configuration.setRegion("us-east-1");
+
+ // Just verify the client is created - actual credential resolution happens on first API call
+ PollyClient client = Polly2ClientFactory.getPollyClient(configuration);
+ assertNotNull(client);
+ client.close();
+ }
+}
diff --git a/components/camel-aws/camel-aws2-polly/src/test/java/org/apache/camel/component/aws2/polly/Polly2ProducerTest.java b/components/camel-aws/camel-aws2-polly/src/test/java/org/apache/camel/component/aws2/polly/Polly2ProducerTest.java
new file mode 100644
index 000000000000..006b2283bbe9
--- /dev/null
+++ b/components/camel-aws/camel-aws2-polly/src/test/java/org/apache/camel/component/aws2/polly/Polly2ProducerTest.java
@@ -0,0 +1,282 @@
+/*
+ * 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.aws2.polly;
+
+import java.io.InputStream;
+import java.util.List;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+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 software.amazon.awssdk.services.polly.model.Lexicon;
+import software.amazon.awssdk.services.polly.model.LexiconDescription;
+import software.amazon.awssdk.services.polly.model.OutputFormat;
+import software.amazon.awssdk.services.polly.model.SynthesisTask;
+import software.amazon.awssdk.services.polly.model.SynthesizeSpeechRequest;
+import software.amazon.awssdk.services.polly.model.Voice;
+import software.amazon.awssdk.services.polly.model.VoiceId;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class Polly2ProducerTest extends CamelTestSupport {
+
+ @BindToRegistry("amazonPollyClient")
+ AmazonPollyClientMock clientMock = new AmazonPollyClientMock();
+
+ @EndpointInject("mock:result")
+ private MockEndpoint mock;
+
+ @Test
+ public void synthesizeSpeechTest() throws Exception {
+ mock.expectedMessageCount(1);
+ Exchange exchange = template.request("direct:synthesizeSpeech", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(Polly2Constants.VOICE_ID, VoiceId.JOANNA);
+ exchange.getIn().setBody("Hello, this is a test.");
+ }
+ });
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ assertNotNull(exchange.getIn().getBody(InputStream.class));
+ assertEquals("audio/mpeg", exchange.getIn().getHeader(Polly2Constants.CONTENT_TYPE));
+ }
+
+ @Test
+ public void synthesizeSpeechWithOptionsTest() throws Exception {
+ mock.expectedMessageCount(1);
+ Exchange exchange = template.request("direct:synthesizeSpeechWithOptions", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ exchange.getIn().setBody("Hello, this is a test with neural engine.");
+ }
+ });
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ assertNotNull(exchange.getIn().getBody(InputStream.class));
+ }
+
+ @Test
+ public void synthesizeSpeechPojoTest() throws Exception {
+ mock.expectedMessageCount(1);
+ Exchange exchange = template.request("direct:synthesizeSpeechPojo", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ exchange.getIn().setBody(SynthesizeSpeechRequest.builder()
+ .voiceId(VoiceId.JOANNA)
+ .outputFormat(OutputFormat.MP3)
+ .text("Hello from POJO request")
+ .build());
+ }
+ });
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ assertNotNull(exchange.getIn().getBody(InputStream.class));
+ }
+
+ @Test
+ public void describeVoicesTest() throws Exception {
+ mock.expectedMessageCount(1);
+ Exchange exchange = template.request("direct:describeVoices", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ }
+ });
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ List<Voice> voices = exchange.getIn().getBody(List.class);
+ assertNotNull(voices);
+ assertEquals(2, voices.size());
+ }
+
+ @Test
+ public void listLexiconsTest() throws Exception {
+ mock.expectedMessageCount(1);
+ Exchange exchange = template.request("direct:listLexicons", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ }
+ });
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ List<LexiconDescription> lexicons = exchange.getIn().getBody(List.class);
+ assertNotNull(lexicons);
+ assertEquals(1, lexicons.size());
+ }
+
+ @Test
+ public void getLexiconTest() throws Exception {
+ mock.expectedMessageCount(1);
+ Exchange exchange = template.request("direct:getLexicon", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(Polly2Constants.LEXICON_NAME, "TestLexicon");
+ }
+ });
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ Lexicon lexicon = exchange.getIn().getBody(Lexicon.class);
+ assertNotNull(lexicon);
+ assertEquals("TestLexicon", lexicon.name());
+ }
+
+ @Test
+ public void putLexiconTest() throws Exception {
+ mock.expectedMessageCount(1);
+ Exchange exchange = template.request("direct:putLexicon", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(Polly2Constants.LEXICON_NAME, "NewLexicon");
+ exchange.getIn().setBody("<?xml version=\"1.0\" encoding=\"UTF-8\"?><lexicon></lexicon>");
+ }
+ });
+
+ MockEndpoint.assertIsSatisfied(context);
+ assertNotNull(exchange.getIn().getBody());
+ }
+
+ @Test
+ public void deleteLexiconTest() throws Exception {
+ mock.expectedMessageCount(1);
+ Exchange exchange = template.request("direct:deleteLexicon", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(Polly2Constants.LEXICON_NAME, "TestLexicon");
+ }
+ });
+
+ MockEndpoint.assertIsSatisfied(context);
+ assertNotNull(exchange.getIn().getBody());
+ }
+
+ @Test
+ public void startSpeechSynthesisTaskTest() throws Exception {
+ mock.expectedMessageCount(1);
+ Exchange exchange = template.request("direct:startSpeechSynthesisTask", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(Polly2Constants.VOICE_ID, VoiceId.JOANNA);
+ exchange.getIn().setHeader(Polly2Constants.S3_BUCKET, "my-bucket");
+ exchange.getIn().setBody("This is a long text for async synthesis.");
+ }
+ });
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ SynthesisTask task = exchange.getIn().getBody(SynthesisTask.class);
+ assertNotNull(task);
+ assertEquals("test-task-id-123", task.taskId());
+ assertEquals("test-task-id-123", exchange.getIn().getHeader(Polly2Constants.TASK_ID));
+ }
+
+ @Test
+ public void getSpeechSynthesisTaskTest() throws Exception {
+ mock.expectedMessageCount(1);
+ Exchange exchange = template.request("direct:getSpeechSynthesisTask", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(Polly2Constants.TASK_ID, "test-task-id-123");
+ }
+ });
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ SynthesisTask task = exchange.getIn().getBody(SynthesisTask.class);
+ assertNotNull(task);
+ assertEquals("test-task-id-123", task.taskId());
+ }
+
+ @Test
+ public void listSpeechSynthesisTasksTest() throws Exception {
+ mock.expectedMessageCount(1);
+ Exchange exchange = template.request("direct:listSpeechSynthesisTasks", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ }
+ });
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ List<SynthesisTask> tasks = exchange.getIn().getBody(List.class);
+ assertNotNull(tasks);
+ assertEquals(1, tasks.size());
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ from("direct:synthesizeSpeech")
+ .to("aws2-polly://test?pollyClient=#amazonPollyClient&operation=synthesizeSpeech")
+ .to("mock:result");
+
+ from("direct:synthesizeSpeechWithOptions")
+ .to("aws2-polly://test?pollyClient=#amazonPollyClient&operation=synthesizeSpeech&voiceId=JOANNA&engine=NEURAL&outputFormat=MP3")
+ .to("mock:result");
+
+ from("direct:synthesizeSpeechPojo")
+ .to("aws2-polly://test?pollyClient=#amazonPollyClient&operation=synthesizeSpeech&pojoRequest=true")
+ .to("mock:result");
+
+ from("direct:describeVoices")
+ .to("aws2-polly://test?pollyClient=#amazonPollyClient&operation=describeVoices")
+ .to("mock:result");
+
+ from("direct:listLexicons")
+ .to("aws2-polly://test?pollyClient=#amazonPollyClient&operation=listLexicons")
+ .to("mock:result");
+
+ from("direct:getLexicon")
+ .to("aws2-polly://test?pollyClient=#amazonPollyClient&operation=getLexicon")
+ .to("mock:result");
+
+ from("direct:putLexicon")
+ .to("aws2-polly://test?pollyClient=#amazonPollyClient&operation=putLexicon")
+ .to("mock:result");
+
+ from("direct:deleteLexicon")
+ .to("aws2-polly://test?pollyClient=#amazonPollyClient&operation=deleteLexicon")
+ .to("mock:result");
+
+ from("direct:startSpeechSynthesisTask")
+ .to("aws2-polly://test?pollyClient=#amazonPollyClient&operation=startSpeechSynthesisTask")
+ .to("mock:result");
+
+ from("direct:getSpeechSynthesisTask")
+ .to("aws2-polly://test?pollyClient=#amazonPollyClient&operation=getSpeechSynthesisTask")
+ .to("mock:result");
+
+ from("direct:listSpeechSynthesisTasks")
+ .to("aws2-polly://test?pollyClient=#amazonPollyClient&operation=listSpeechSynthesisTasks")
+ .to("mock:result");
+ }
+ };
+ }
+}
diff --git a/components/camel-aws/pom.xml b/components/camel-aws/pom.xml
index d10ded276cc5..4538a09e66bf 100644
--- a/components/camel-aws/pom.xml
+++ b/components/camel-aws/pom.xml
@@ -56,6 +56,7 @@
<module>camel-aws2-lambda</module>
<module>camel-aws2-msk</module>
<module>camel-aws2-mq</module>
+ <module>camel-aws2-polly</module>
<module>camel-aws-parameter-store</module>
<module>camel-aws2-redshift</module>
<module>camel-aws2-s3</module>
diff --git a/parent/pom.xml b/parent/pom.xml
index ce0cfd3bc2c9..06f984cd970e 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -904,6 +904,11 @@
<artifactId>camel-aws2-msk</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-aws2-polly</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-aws2-redshift</artifactId>
diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/MojoHelper.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/MojoHelper.java
index 8f76e6a6d654..fe1ed8dfef99 100644
--- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/MojoHelper.java
+++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/MojoHelper.java
@@ -116,7 +116,7 @@ public final class MojoHelper {
dir.resolve("camel-aws2-iam"),
dir.resolve("camel-aws2-kinesis"), dir.resolve("camel-aws2-kms"), dir.resolve("camel-aws2-lambda"),
dir.resolve("camel-aws2-mq"),
- dir.resolve("camel-aws2-msk"), dir.resolve("camel-aws2-redshift"),
+ dir.resolve("camel-aws2-msk"), dir.resolve("camel-aws2-polly"), dir.resolve("camel-aws2-redshift"),
dir.resolve("camel-aws2-rekognition"),
dir.resolve("camel-aws2-s3"), dir.resolve("camel-aws2-ses"),
dir.resolve("camel-aws2-sns"),