From 9269459b4f6dee3e403c5a8c726528a031551d9b Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 10 Aug 2026 17:32:35 +0000 Subject: [PATCH 01/12] CAMEL-24373: Add camel-alibaba-oss component (phase 1 MVP) Implement Alibaba Cloud OSS component using alibabacloud-oss-v2 SDK: - Producer operations: listBuckets, listObjects, putObject, getObject, deleteObject, copyObject, headObject - Consumer polls listObjectsV2 with optional deleteAfterRead - Shared AlibabaClientBuilderUtil in camel-alibaba-common - Unit tests with AssertJ and Mockito mock OSSClient Co-authored-by: Omar Atie --- .../camel-alibaba-common/pom.xml | 61 +++ .../org/apache/camel/other.properties | 7 + .../generated/resources/alibaba-common.json | 14 + .../common/AlibabaClientBuilderUtil.java | 61 +++ .../alibaba/common/models/ServiceKeys.java | 47 +++ .../common/AlibabaClientBuilderUtilTest.java | 55 +++ .../camel-alibaba/camel-alibaba-oss/pom.xml | 80 ++++ .../alibaba/oss/OSSComponentConfigurer.java | 75 ++++ .../alibaba/oss/OSSEndpointConfigurer.java | 233 +++++++++++ .../alibaba/oss/OSSEndpointUriFactory.java | 117 ++++++ .../component/alibaba/oss/alibaba-oss.json | 79 ++++ .../org/apache/camel/component.properties | 7 + .../org/apache/camel/component/alibaba-oss | 2 + .../camel/configurer/alibaba-oss-component | 2 + .../camel/configurer/alibaba-oss-endpoint | 2 + .../camel/urifactory/alibaba-oss-endpoint | 2 + .../src/main/docs/alibaba-oss-component.adoc | 102 +++++ .../component/alibaba/oss/OSSComponent.java | 33 ++ .../component/alibaba/oss/OSSConsumer.java | 183 +++++++++ .../component/alibaba/oss/OSSEndpoint.java | 240 ++++++++++++ .../component/alibaba/oss/OSSProducer.java | 365 ++++++++++++++++++ .../camel/component/alibaba/oss/OSSUtils.java | 86 +++++ .../alibaba/oss/constants/OSSConstants.java | 28 ++ .../alibaba/oss/constants/OSSHeaders.java | 48 +++ .../alibaba/oss/constants/OSSOperations.java | 33 ++ .../alibaba/oss/constants/OSSProperties.java | 33 ++ .../oss/models/ClientConfigurations.java | 89 +++++ .../alibaba/oss/DeleteObjectTest.java | 84 ++++ .../component/alibaba/oss/GetObjectTest.java | 101 +++++ .../component/alibaba/oss/HeadObjectTest.java | 91 +++++ .../alibaba/oss/ListObjectsTest.java | 99 +++++ .../component/alibaba/oss/PutObjectTest.java | 87 +++++ .../alibaba/oss/TestConfiguration.java | 45 +++ .../oss/constants/OSSOperationsTest.java | 34 ++ .../src/test/resources/log4j2.properties | 29 ++ components/camel-alibaba/pom.xml | 41 ++ components/pom.xml | 1 + .../camel/maven/packaging/MojoHelper.java | 4 + 38 files changed, 2700 insertions(+) create mode 100644 components/camel-alibaba/camel-alibaba-common/pom.xml create mode 100644 components/camel-alibaba/camel-alibaba-common/src/generated/resources/META-INF/services/org/apache/camel/other.properties create mode 100644 components/camel-alibaba/camel-alibaba-common/src/generated/resources/alibaba-common.json create mode 100644 components/camel-alibaba/camel-alibaba-common/src/main/java/org/apache/camel/component/alibaba/common/AlibabaClientBuilderUtil.java create mode 100644 components/camel-alibaba/camel-alibaba-common/src/main/java/org/apache/camel/component/alibaba/common/models/ServiceKeys.java create mode 100644 components/camel-alibaba/camel-alibaba-common/src/test/java/org/apache/camel/component/alibaba/common/AlibabaClientBuilderUtilTest.java create mode 100644 components/camel-alibaba/camel-alibaba-oss/pom.xml create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/generated/java/org/apache/camel/component/alibaba/oss/OSSComponentConfigurer.java create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/generated/java/org/apache/camel/component/alibaba/oss/OSSEndpointConfigurer.java create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/generated/java/org/apache/camel/component/alibaba/oss/OSSEndpointUriFactory.java create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/org/apache/camel/component/alibaba/oss/alibaba-oss.json create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/services/org/apache/camel/component.properties create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/services/org/apache/camel/component/alibaba-oss create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/services/org/apache/camel/configurer/alibaba-oss-component create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/services/org/apache/camel/configurer/alibaba-oss-endpoint create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/services/org/apache/camel/urifactory/alibaba-oss-endpoint create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/main/docs/alibaba-oss-component.adoc create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSComponent.java create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSConsumer.java create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSEndpoint.java create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSProducer.java create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSUtils.java create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/constants/OSSConstants.java create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/constants/OSSHeaders.java create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/constants/OSSOperations.java create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/constants/OSSProperties.java create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/models/ClientConfigurations.java create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/DeleteObjectTest.java create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/GetObjectTest.java create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/HeadObjectTest.java create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/ListObjectsTest.java create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/PutObjectTest.java create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/TestConfiguration.java create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/constants/OSSOperationsTest.java create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/test/resources/log4j2.properties create mode 100644 components/camel-alibaba/pom.xml diff --git a/components/camel-alibaba/camel-alibaba-common/pom.xml b/components/camel-alibaba/camel-alibaba-common/pom.xml new file mode 100644 index 0000000000000..f3adc4b52f08e --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-common/pom.xml @@ -0,0 +1,61 @@ + + + + + 4.0.0 + + + org.apache.camel + camel-alibaba-parent + 4.22.0-SNAPSHOT + + + + 4.22.0 + + + camel-alibaba-common + jar + Camel :: Alibaba Cloud :: Common + Common utilities for Camel Alibaba Cloud components + + + + org.apache.camel + camel-support + + + com.aliyun + alibabacloud-oss-v2 + 0.4.1 + + + org.apache.camel + camel-test-junit6 + test + + + org.assertj + assertj-core + test + + + + diff --git a/components/camel-alibaba/camel-alibaba-common/src/generated/resources/META-INF/services/org/apache/camel/other.properties b/components/camel-alibaba/camel-alibaba-common/src/generated/resources/META-INF/services/org/apache/camel/other.properties new file mode 100644 index 0000000000000..5b5950b30c120 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-common/src/generated/resources/META-INF/services/org/apache/camel/other.properties @@ -0,0 +1,7 @@ +# Generated by camel build tools - do NOT edit this file! +name=alibaba-common +groupId=org.apache.camel +artifactId=camel-alibaba-common +version=4.22.0-SNAPSHOT +projectName=Camel :: Alibaba Cloud :: Common +projectDescription=Common utilities for Camel Alibaba Cloud components diff --git a/components/camel-alibaba/camel-alibaba-common/src/generated/resources/alibaba-common.json b/components/camel-alibaba/camel-alibaba-common/src/generated/resources/alibaba-common.json new file mode 100644 index 0000000000000..eaeb8ad093c5d --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-common/src/generated/resources/alibaba-common.json @@ -0,0 +1,14 @@ +{ + "other": { + "kind": "other", + "name": "alibaba-common", + "title": "Alibaba Common", + "description": "Common utilities for Camel Alibaba Cloud components", + "deprecated": false, + "firstVersion": "4.22.0", + "supportLevel": "Preview", + "groupId": "org.apache.camel", + "artifactId": "camel-alibaba-common", + "version": "4.22.0-SNAPSHOT" + } +} diff --git a/components/camel-alibaba/camel-alibaba-common/src/main/java/org/apache/camel/component/alibaba/common/AlibabaClientBuilderUtil.java b/components/camel-alibaba/camel-alibaba-common/src/main/java/org/apache/camel/component/alibaba/common/AlibabaClientBuilderUtil.java new file mode 100644 index 0000000000000..6a687b02e4651 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-common/src/main/java/org/apache/camel/component/alibaba/common/AlibabaClientBuilderUtil.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.alibaba.common; + +import com.aliyun.sdk.service.oss2.OSSClient; +import com.aliyun.sdk.service.oss2.OSSClientBuilder; +import com.aliyun.sdk.service.oss2.credentials.StaticCredentialsProvider; +import org.apache.camel.util.ObjectHelper; + +public final class AlibabaClientBuilderUtil { + + private AlibabaClientBuilderUtil() { + } + + /** + * Create an OSS client using static credentials. + * + * @param accessKey access key id + * @param secretKey secret access key + * @param region OSS region + * @param endpoint optional custom endpoint + * @return configured OSS client + */ + public static OSSClient createOssClient(String accessKey, String secretKey, String region, String endpoint) { + if (ObjectHelper.isEmpty(accessKey)) { + throw new IllegalArgumentException("Authentication parameter 'access key (AK)' not found"); + } + if (ObjectHelper.isEmpty(secretKey)) { + throw new IllegalArgumentException("Authentication parameter 'secret key (SK)' not found"); + } + if (ObjectHelper.isEmpty(region) && ObjectHelper.isEmpty(endpoint)) { + throw new IllegalArgumentException("Region/endpoint not found"); + } + + OSSClientBuilder clientBuilder = OSSClient.newBuilder() + .credentialsProvider(new StaticCredentialsProvider(accessKey, secretKey)); + + if (ObjectHelper.isNotEmpty(region)) { + clientBuilder.region(region); + } + if (ObjectHelper.isNotEmpty(endpoint)) { + clientBuilder.endpoint(endpoint); + } + + return clientBuilder.build(); + } +} diff --git a/components/camel-alibaba/camel-alibaba-common/src/main/java/org/apache/camel/component/alibaba/common/models/ServiceKeys.java b/components/camel-alibaba/camel-alibaba-common/src/main/java/org/apache/camel/component/alibaba/common/models/ServiceKeys.java new file mode 100644 index 0000000000000..033e89b4f4141 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-common/src/main/java/org/apache/camel/component/alibaba/common/models/ServiceKeys.java @@ -0,0 +1,47 @@ +/* + * 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.alibaba.common.models; + +public class ServiceKeys { + + private String accessKey; + private String secretKey; + + public ServiceKeys() { + } + + public ServiceKeys(String accessKey, String secretKey) { + this.accessKey = accessKey; + this.secretKey = secretKey; + } + + public String getAccessKey() { + return accessKey; + } + + public void setAccessKey(String accessKey) { + this.accessKey = accessKey; + } + + public String getSecretKey() { + return secretKey; + } + + public void setSecretKey(String secretKey) { + this.secretKey = secretKey; + } +} diff --git a/components/camel-alibaba/camel-alibaba-common/src/test/java/org/apache/camel/component/alibaba/common/AlibabaClientBuilderUtilTest.java b/components/camel-alibaba/camel-alibaba-common/src/test/java/org/apache/camel/component/alibaba/common/AlibabaClientBuilderUtilTest.java new file mode 100644 index 0000000000000..7e7a7255b84c0 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-common/src/test/java/org/apache/camel/component/alibaba/common/AlibabaClientBuilderUtilTest.java @@ -0,0 +1,55 @@ +/* + * 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.alibaba.common; + +import com.aliyun.sdk.service.oss2.OSSClient; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class AlibabaClientBuilderUtilTest { + + @Test + void createOssClientWithRegion() throws Exception { + try (OSSClient client = AlibabaClientBuilderUtil.createOssClient("ak", "sk", "cn-hangzhou", null)) { + assertThat(client).isNotNull(); + } + } + + @Test + void createOssClientWithEndpoint() throws Exception { + try (OSSClient client = AlibabaClientBuilderUtil.createOssClient("ak", "sk", null, + "https://oss-cn-hangzhou.aliyuncs.com")) { + assertThat(client).isNotNull(); + } + } + + @Test + void createOssClientMissingAccessKey() { + assertThatThrownBy(() -> AlibabaClientBuilderUtil.createOssClient(null, "sk", "cn-hangzhou", null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("access key"); + } + + @Test + void createOssClientMissingRegionAndEndpoint() { + assertThatThrownBy(() -> AlibabaClientBuilderUtil.createOssClient("ak", "sk", null, null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Region/endpoint"); + } +} diff --git a/components/camel-alibaba/camel-alibaba-oss/pom.xml b/components/camel-alibaba/camel-alibaba-oss/pom.xml new file mode 100644 index 0000000000000..08f8d7e9196da --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/pom.xml @@ -0,0 +1,80 @@ + + + + + 4.0.0 + + + org.apache.camel + camel-alibaba-parent + 4.22.0-SNAPSHOT + + + + 4.22.0 + + + camel-alibaba-oss + jar + Camel :: Alibaba Cloud :: OSS + Alibaba Cloud Object Storage Service (OSS) component + + + + + org.apache.camel + camel-support + + + + org.apache.camel + camel-alibaba-common + ${project.version} + + + + com.aliyun + alibabacloud-oss-v2 + 0.4.1 + + + + com.google.code.gson + gson + + + + org.apache.camel + camel-test-junit6 + test + + + org.mockito + mockito-core + ${mockito-version} + test + + + org.assertj + assertj-core + test + + + diff --git a/components/camel-alibaba/camel-alibaba-oss/src/generated/java/org/apache/camel/component/alibaba/oss/OSSComponentConfigurer.java b/components/camel-alibaba/camel-alibaba-oss/src/generated/java/org/apache/camel/component/alibaba/oss/OSSComponentConfigurer.java new file mode 100644 index 0000000000000..18c5c5d677a2a --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/generated/java/org/apache/camel/component/alibaba/oss/OSSComponentConfigurer.java @@ -0,0 +1,75 @@ +/* Generated by camel build tools - do NOT edit this file! */ +package org.apache.camel.component.alibaba.oss; + +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 OSSComponentConfigurer extends PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter { + + @Override + public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) { + OSSComponent target = (OSSComponent) obj; + switch (ignoreCase ? name.toLowerCase() : name) { + case "autowiredenabled": + case "autowiredEnabled": target.setAutowiredEnabled(property(camelContext, boolean.class, value)); return true; + case "bridgeerrorhandler": + case "bridgeErrorHandler": target.setBridgeErrorHandler(property(camelContext, boolean.class, value)); return true; + case "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 "lazystartproducer": + case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true; + default: return false; + } + } + + @Override + public Class getOptionType(String name, boolean ignoreCase) { + switch (ignoreCase ? name.toLowerCase() : name) { + case "autowiredenabled": + case "autowiredEnabled": return boolean.class; + case "bridgeerrorhandler": + case "bridgeErrorHandler": return boolean.class; + case "healthcheckconsumerenabled": + case "healthCheckConsumerEnabled": return boolean.class; + case "healthcheckproducerenabled": + case "healthCheckProducerEnabled": return boolean.class; + case "lazystartproducer": + case "lazyStartProducer": return boolean.class; + default: return null; + } + } + + @Override + public Object getOptionValue(Object obj, String name, boolean ignoreCase) { + OSSComponent target = (OSSComponent) obj; + switch (ignoreCase ? name.toLowerCase() : name) { + case "autowiredenabled": + case "autowiredEnabled": return target.isAutowiredEnabled(); + case "bridgeerrorhandler": + case "bridgeErrorHandler": return target.isBridgeErrorHandler(); + case "healthcheckconsumerenabled": + case "healthCheckConsumerEnabled": return target.isHealthCheckConsumerEnabled(); + case "healthcheckproducerenabled": + case "healthCheckProducerEnabled": return target.isHealthCheckProducerEnabled(); + case "lazystartproducer": + case "lazyStartProducer": return target.isLazyStartProducer(); + default: return null; + } + } +} + diff --git a/components/camel-alibaba/camel-alibaba-oss/src/generated/java/org/apache/camel/component/alibaba/oss/OSSEndpointConfigurer.java b/components/camel-alibaba/camel-alibaba-oss/src/generated/java/org/apache/camel/component/alibaba/oss/OSSEndpointConfigurer.java new file mode 100644 index 0000000000000..809b2e0558296 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/generated/java/org/apache/camel/component/alibaba/oss/OSSEndpointConfigurer.java @@ -0,0 +1,233 @@ +/* Generated by camel build tools - do NOT edit this file! */ +package org.apache.camel.component.alibaba.oss; + +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 OSSEndpointConfigurer extends PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter { + + @Override + public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) { + OSSEndpoint target = (OSSEndpoint) obj; + switch (ignoreCase ? name.toLowerCase() : name) { + case "accesskey": + case "accessKey": target.setAccessKey(property(camelContext, java.lang.String.class, value)); return true; + case "backofferrorthreshold": + case "backoffErrorThreshold": target.setBackoffErrorThreshold(property(camelContext, int.class, value)); return true; + case "backoffidlethreshold": + case "backoffIdleThreshold": target.setBackoffIdleThreshold(property(camelContext, int.class, value)); return true; + case "backoffmultiplier": + case "backoffMultiplier": target.setBackoffMultiplier(property(camelContext, int.class, value)); return true; + case "bridgeerrorhandler": + case "bridgeErrorHandler": target.setBridgeErrorHandler(property(camelContext, boolean.class, value)); return true; + case "bucketname": + case "bucketName": target.setBucketName(property(camelContext, java.lang.String.class, value)); return true; + case "delay": target.setDelay(property(camelContext, long.class, value)); return true; + case "deleteafterread": + case "deleteAfterRead": target.setDeleteAfterRead(property(camelContext, boolean.class, value)); return true; + case "endpoint": target.setEndpoint(property(camelContext, java.lang.String.class, value)); return true; + case "exceptionhandler": + case "exceptionHandler": target.setExceptionHandler(property(camelContext, org.apache.camel.spi.ExceptionHandler.class, value)); return true; + case "exchangepattern": + case "exchangePattern": target.setExchangePattern(property(camelContext, org.apache.camel.ExchangePattern.class, value)); return true; + case "greedy": target.setGreedy(property(camelContext, boolean.class, value)); return true; + case "initialdelay": + case "initialDelay": target.setInitialDelay(property(camelContext, long.class, value)); return true; + case "lazystartproducer": + case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true; + case "maxkeys": + case "maxKeys": target.setMaxKeys(property(camelContext, java.lang.Integer.class, value)); return true; + case "maxmessagesperpoll": + case "maxMessagesPerPoll": target.setMaxMessagesPerPoll(property(camelContext, int.class, value)); return true; + case "objectname": + case "objectName": target.setObjectName(property(camelContext, java.lang.String.class, value)); return true; + case "ossclient": + case "ossClient": target.setOssClient(property(camelContext, com.aliyun.sdk.service.oss2.OSSClient.class, value)); return true; + case "pollstrategy": + case "pollStrategy": target.setPollStrategy(property(camelContext, org.apache.camel.spi.PollingConsumerPollStrategy.class, value)); return true; + case "prefix": target.setPrefix(property(camelContext, java.lang.String.class, value)); return true; + case "region": target.setRegion(property(camelContext, java.lang.String.class, value)); return true; + case "repeatcount": + case "repeatCount": target.setRepeatCount(property(camelContext, long.class, value)); return true; + case "runlogginglevel": + case "runLoggingLevel": target.setRunLoggingLevel(property(camelContext, org.apache.camel.LoggingLevel.class, value)); return true; + case "scheduledexecutorservice": + case "scheduledExecutorService": target.setScheduledExecutorService(property(camelContext, java.util.concurrent.ScheduledExecutorService.class, value)); return true; + case "scheduler": target.setScheduler(property(camelContext, java.lang.Object.class, value)); return true; + case "schedulerproperties": + case "schedulerProperties": target.setSchedulerProperties(property(camelContext, java.util.Map.class, value)); return true; + case "secretkey": + case "secretKey": target.setSecretKey(property(camelContext, java.lang.String.class, value)); return true; + case "sendemptymessagewhenidle": + case "sendEmptyMessageWhenIdle": target.setSendEmptyMessageWhenIdle(property(camelContext, boolean.class, value)); return true; + case "servicekeys": + case "serviceKeys": target.setServiceKeys(property(camelContext, org.apache.camel.component.alibaba.common.models.ServiceKeys.class, value)); return true; + case "startscheduler": + case "startScheduler": target.setStartScheduler(property(camelContext, boolean.class, value)); return true; + case "timeunit": + case "timeUnit": target.setTimeUnit(property(camelContext, java.util.concurrent.TimeUnit.class, value)); return true; + case "usefixeddelay": + case "useFixedDelay": target.setUseFixedDelay(property(camelContext, boolean.class, value)); return true; + default: return false; + } + } + + @Override + public String[] getAutowiredNames() { + return new String[]{"ossClient"}; + } + + @Override + public Class getOptionType(String name, boolean ignoreCase) { + switch (ignoreCase ? name.toLowerCase() : name) { + case "accesskey": + case "accessKey": return java.lang.String.class; + case "backofferrorthreshold": + case "backoffErrorThreshold": return int.class; + case "backoffidlethreshold": + case "backoffIdleThreshold": return int.class; + case "backoffmultiplier": + case "backoffMultiplier": return int.class; + case "bridgeerrorhandler": + case "bridgeErrorHandler": return boolean.class; + case "bucketname": + case "bucketName": return java.lang.String.class; + case "delay": return long.class; + case "deleteafterread": + case "deleteAfterRead": return boolean.class; + case "endpoint": return java.lang.String.class; + case "exceptionhandler": + case "exceptionHandler": return org.apache.camel.spi.ExceptionHandler.class; + case "exchangepattern": + case "exchangePattern": return org.apache.camel.ExchangePattern.class; + case "greedy": return boolean.class; + case "initialdelay": + case "initialDelay": return long.class; + case "lazystartproducer": + case "lazyStartProducer": return boolean.class; + case "maxkeys": + case "maxKeys": return java.lang.Integer.class; + case "maxmessagesperpoll": + case "maxMessagesPerPoll": return int.class; + case "objectname": + case "objectName": return java.lang.String.class; + case "ossclient": + case "ossClient": return com.aliyun.sdk.service.oss2.OSSClient.class; + case "pollstrategy": + case "pollStrategy": return org.apache.camel.spi.PollingConsumerPollStrategy.class; + case "prefix": return java.lang.String.class; + case "region": return java.lang.String.class; + case "repeatcount": + case "repeatCount": return long.class; + case "runlogginglevel": + case "runLoggingLevel": return org.apache.camel.LoggingLevel.class; + case "scheduledexecutorservice": + case "scheduledExecutorService": return java.util.concurrent.ScheduledExecutorService.class; + case "scheduler": return java.lang.Object.class; + case "schedulerproperties": + case "schedulerProperties": return java.util.Map.class; + case "secretkey": + case "secretKey": return java.lang.String.class; + case "sendemptymessagewhenidle": + case "sendEmptyMessageWhenIdle": return boolean.class; + case "servicekeys": + case "serviceKeys": return org.apache.camel.component.alibaba.common.models.ServiceKeys.class; + case "startscheduler": + case "startScheduler": return boolean.class; + case "timeunit": + case "timeUnit": return java.util.concurrent.TimeUnit.class; + case "usefixeddelay": + case "useFixedDelay": return boolean.class; + default: return null; + } + } + + @Override + public Object getOptionValue(Object obj, String name, boolean ignoreCase) { + OSSEndpoint target = (OSSEndpoint) obj; + switch (ignoreCase ? name.toLowerCase() : name) { + case "accesskey": + case "accessKey": return target.getAccessKey(); + case "backofferrorthreshold": + case "backoffErrorThreshold": return target.getBackoffErrorThreshold(); + case "backoffidlethreshold": + case "backoffIdleThreshold": return target.getBackoffIdleThreshold(); + case "backoffmultiplier": + case "backoffMultiplier": return target.getBackoffMultiplier(); + case "bridgeerrorhandler": + case "bridgeErrorHandler": return target.isBridgeErrorHandler(); + case "bucketname": + case "bucketName": return target.getBucketName(); + case "delay": return target.getDelay(); + case "deleteafterread": + case "deleteAfterRead": return target.isDeleteAfterRead(); + case "endpoint": return target.getEndpoint(); + case "exceptionhandler": + case "exceptionHandler": return target.getExceptionHandler(); + case "exchangepattern": + case "exchangePattern": return target.getExchangePattern(); + case "greedy": return target.isGreedy(); + case "initialdelay": + case "initialDelay": return target.getInitialDelay(); + case "lazystartproducer": + case "lazyStartProducer": return target.isLazyStartProducer(); + case "maxkeys": + case "maxKeys": return target.getMaxKeys(); + case "maxmessagesperpoll": + case "maxMessagesPerPoll": return target.getMaxMessagesPerPoll(); + case "objectname": + case "objectName": return target.getObjectName(); + case "ossclient": + case "ossClient": return target.getOssClient(); + case "pollstrategy": + case "pollStrategy": return target.getPollStrategy(); + case "prefix": return target.getPrefix(); + case "region": return target.getRegion(); + case "repeatcount": + case "repeatCount": return target.getRepeatCount(); + case "runlogginglevel": + case "runLoggingLevel": return target.getRunLoggingLevel(); + case "scheduledexecutorservice": + case "scheduledExecutorService": return target.getScheduledExecutorService(); + case "scheduler": return target.getScheduler(); + case "schedulerproperties": + case "schedulerProperties": return target.getSchedulerProperties(); + case "secretkey": + case "secretKey": return target.getSecretKey(); + case "sendemptymessagewhenidle": + case "sendEmptyMessageWhenIdle": return target.isSendEmptyMessageWhenIdle(); + case "servicekeys": + case "serviceKeys": return target.getServiceKeys(); + case "startscheduler": + case "startScheduler": return target.isStartScheduler(); + case "timeunit": + case "timeUnit": return target.getTimeUnit(); + case "usefixeddelay": + case "useFixedDelay": return target.isUseFixedDelay(); + default: return null; + } + } + + @Override + public Object getCollectionValueType(Object target, String name, boolean ignoreCase) { + switch (ignoreCase ? name.toLowerCase() : name) { + case "schedulerproperties": + case "schedulerProperties": return java.lang.Object.class; + default: return null; + } + } +} + diff --git a/components/camel-alibaba/camel-alibaba-oss/src/generated/java/org/apache/camel/component/alibaba/oss/OSSEndpointUriFactory.java b/components/camel-alibaba/camel-alibaba-oss/src/generated/java/org/apache/camel/component/alibaba/oss/OSSEndpointUriFactory.java new file mode 100644 index 0000000000000..58f5aa728f357 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/generated/java/org/apache/camel/component/alibaba/oss/OSSEndpointUriFactory.java @@ -0,0 +1,117 @@ +/* Generated by camel build tools - do NOT edit this file! */ +package org.apache.camel.component.alibaba.oss; + +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 OSSEndpointUriFactory extends org.apache.camel.support.component.EndpointUriFactorySupport implements EndpointUriFactory { + + private static final String BASE = ":operation"; + + private static final Set PROPERTY_NAMES; + private static final Set SECRET_PROPERTY_NAMES; + private static final Set ENDPOINT_IDENTITY_PROPERTY_NAMES; + private static final Map MULTI_VALUE_PREFIXES; + static { + Set props = new HashSet<>(33); + props.add("accessKey"); + props.add("backoffErrorThreshold"); + props.add("backoffIdleThreshold"); + props.add("backoffMultiplier"); + props.add("bridgeErrorHandler"); + props.add("bucketName"); + props.add("delay"); + props.add("deleteAfterRead"); + props.add("endpoint"); + props.add("exceptionHandler"); + props.add("exchangePattern"); + props.add("greedy"); + props.add("initialDelay"); + props.add("lazyStartProducer"); + props.add("maxKeys"); + props.add("maxMessagesPerPoll"); + props.add("objectName"); + props.add("operation"); + props.add("ossClient"); + props.add("pollStrategy"); + props.add("prefix"); + props.add("region"); + props.add("repeatCount"); + props.add("runLoggingLevel"); + props.add("scheduledExecutorService"); + props.add("scheduler"); + props.add("schedulerProperties"); + props.add("secretKey"); + props.add("sendEmptyMessageWhenIdle"); + props.add("serviceKeys"); + props.add("startScheduler"); + props.add("timeUnit"); + props.add("useFixedDelay"); + PROPERTY_NAMES = Collections.unmodifiableSet(props); + Set secretProps = new HashSet<>(3); + secretProps.add("accessKey"); + secretProps.add("secretKey"); + secretProps.add("serviceKeys"); + SECRET_PROPERTY_NAMES = Collections.unmodifiableSet(secretProps); + Set identityProps = new HashSet<>(1); + identityProps.add("bucketName"); + ENDPOINT_IDENTITY_PROPERTY_NAMES = Collections.unmodifiableSet(identityProps); + Map prefixes = new HashMap<>(1); + prefixes.put("schedulerProperties", "scheduler."); + MULTI_VALUE_PREFIXES = Collections.unmodifiableMap(prefixes); + } + + @Override + public boolean isEnabled(String scheme) { + return "alibaba-oss".equals(scheme); + } + + @Override + public String buildUri(String scheme, Map properties, boolean encode) throws URISyntaxException { + String syntax = scheme + BASE; + String uri = syntax; + + Map copy = new HashMap<>(properties); + + uri = buildPathParameter(syntax, uri, "operation", null, true, copy); + uri = buildQueryParameters(uri, copy, encode); + return uri; + } + + @Override + public Set propertyNames() { + return PROPERTY_NAMES; + } + + @Override + public Set secretPropertyNames() { + return SECRET_PROPERTY_NAMES; + } + + @Override + public Set endpointIdentityPropertyNames() { + return ENDPOINT_IDENTITY_PROPERTY_NAMES; + } + + @Override + public Map multiValuePrefixes() { + return MULTI_VALUE_PREFIXES; + } + + @Override + public boolean isLenientProperties() { + return false; + } +} + diff --git a/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/org/apache/camel/component/alibaba/oss/alibaba-oss.json b/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/org/apache/camel/component/alibaba/oss/alibaba-oss.json new file mode 100644 index 0000000000000..de6f70f530bfb --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/org/apache/camel/component/alibaba/oss/alibaba-oss.json @@ -0,0 +1,79 @@ +{ + "component": { + "kind": "component", + "name": "alibaba-oss", + "title": "Alibaba Object Storage Service (OSS)", + "description": "Alibaba Cloud Object Storage Service (OSS) component", + "deprecated": false, + "firstVersion": "4.22.0", + "label": "cloud", + "javaType": "org.apache.camel.component.alibaba.oss.OSSComponent", + "supportLevel": "Preview", + "groupId": "org.apache.camel", + "artifactId": "camel-alibaba-oss", + "version": "4.22.0-SNAPSHOT", + "scheme": "alibaba-oss", + "extendsScheme": "", + "syntax": "alibaba-oss:operation", + "async": false, + "api": false, + "consumerOnly": false, + "producerOnly": false, + "lenientProperties": false, + "browsable": false, + "remote": true + }, + "componentProperties": { + "bridgeErrorHandler": { "index": 0, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, + "lazyStartProducer": { "index": 1, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." }, + "autowiredEnabled": { "index": 2, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching type, which then gets configured on the component. This can be used for automatic configuring JDBC data sources, JMS connection factories, AWS Clients, etc." }, + "healthCheckConsumerEnabled": { "index": 3, "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": 4, "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 producer checks globally by setting camel.health.producersEnabled=true." } + }, + "headers": { + "CamelAlibabaOssBucketName": { "index": 0, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the bucket where object is contained", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#BUCKET_NAME" }, + "CamelAlibabaOssObjectKey": { "index": 1, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The key that the object is stored under", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#OBJECT_KEY" }, + "CamelAlibabaOssLastModified": { "index": 2, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The date and time that the object was last modified", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#LAST_MODIFIED" }, + "CamelAlibabaOssETag": { "index": 3, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The 128-bit MD5 digest of the object content", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#ETAG" }, + "CamelAlibabaOssContentMD5": { "index": 4, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The 128-bit Base64-encoded digest of the object", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#CONTENT_MD5" }, + "CamelAlibabaOssObjectType": { "index": 5, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Shows whether the object is a file or a folder", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#OBJECT_TYPE" }, + "Content-Length": { "index": 6, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The size of the object body in bytes", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#CONTENT_LENGTH" }, + "Content-Type": { "index": 7, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The type of content stored in the object", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#CONTENT_TYPE" }, + "CamelFileName": { "index": 8, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the object with which the operation is to be performed", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#FILE_NAME" } + }, + "properties": { + "operation": { "index": 0, "kind": "path", "displayName": "Operation", "group": "producer", "label": "producer", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Operation to be performed" }, + "bucketName": { "index": 1, "kind": "parameter", "displayName": "Bucket Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "endpointIdentity": true, "description": "Name of bucket to perform operation on" }, + "endpoint": { "index": 2, "kind": "parameter", "displayName": "Endpoint url", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "OSS endpoint URL. Carries higher precedence than region based client initialization" }, + "objectName": { "index": 3, "kind": "parameter", "displayName": "Object Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of object to perform operation with" }, + "region": { "index": 4, "kind": "parameter", "displayName": "Service region", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "OSS service region" }, + "deleteAfterRead": { "index": 5, "kind": "parameter", "displayName": "Delete after read", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Determines if objects should be deleted after they have been retrieved" }, + "maxMessagesPerPoll": { "index": 6, "kind": "parameter", "displayName": "Maximum messages per poll", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 10, "description": "The maximum number of messages to poll at each polling" }, + "prefix": { "index": 7, "kind": "parameter", "displayName": "Prefix", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The object name prefix used for filtering objects to be listed" }, + "sendEmptyMessageWhenIdle": { "index": 8, "kind": "parameter", "displayName": "Send Empty Message When Idle", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead." }, + "bridgeErrorHandler": { "index": 9, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, + "exceptionHandler": { "index": 10, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, + "exchangePattern": { "index": 11, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." }, + "pollStrategy": { "index": 12, "kind": "parameter", "displayName": "Poll Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.PollingConsumerPollStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "A pluggable org.apache.camel.PollingConsumerPollingStrategy allowing you to provide your custom implementation to control error handling usually occurred during the poll operation before an Exchange have been created and being routed in Camel." }, + "maxKeys": { "index": 13, "kind": "parameter", "displayName": "Max Keys", "group": "producer", "label": "consumer,producer", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "description": "The maximum number of keys returned when listing objects" }, + "lazyStartProducer": { "index": 14, "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 producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." }, + "ossClient": { "index": 15, "kind": "parameter", "displayName": "OSS Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "com.aliyun.sdk.service.oss2.OSSClient", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "description": "An autowired OSS client" }, + "backoffErrorThreshold": { "index": 16, "kind": "parameter", "displayName": "Backoff Error Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent error polls (failed due some error) that should happen before the backoffMultipler should kick-in." }, + "backoffIdleThreshold": { "index": 17, "kind": "parameter", "displayName": "Backoff Idle Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent idle polls that should happen before the backoffMultipler should kick-in." }, + "backoffMultiplier": { "index": 18, "kind": "parameter", "displayName": "Backoff Multiplier", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "To let the scheduled polling consumer backoff if there has been a number of subsequent idles\/errors in a row. The multiplier is then the number of polls that will be skipped before the next actual attempt is happening again. When this option is in use then backoffIdleThreshold and\/or backoffErrorThreshold must also be configured." }, + "delay": { "index": 19, "kind": "parameter", "displayName": "Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 500, "description": "Milliseconds before the next poll." }, + "greedy": { "index": 20, "kind": "parameter", "displayName": "Greedy", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If greedy is enabled, then the ScheduledPollConsumer will run immediately again, if the previous run polled 1 or more messages." }, + "initialDelay": { "index": 21, "kind": "parameter", "displayName": "Initial Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "Milliseconds before the first poll starts." }, + "repeatCount": { "index": 22, "kind": "parameter", "displayName": "Repeat Count", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "Specifies a maximum limit of number of fires. So if you set it to 1, the scheduler will only fire once. If you set it to 5, it will only fire five times. A value of zero or negative means fire forever." }, + "runLoggingLevel": { "index": 23, "kind": "parameter", "displayName": "Run Logging Level", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "enum", "javaType": "org.apache.camel.LoggingLevel", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "TRACE", "description": "The consumer logs a start\/complete log line when it polls. This option allows you to configure the logging level for that." }, + "scheduledExecutorService": { "index": 24, "kind": "parameter", "displayName": "Scheduled Executor Service", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.concurrent.ScheduledExecutorService", "deprecated": false, "autowired": false, "secret": false, "description": "Allows for configuring a custom\/shared thread pool to use for the consumer. By default each consumer has its own single threaded thread pool." }, + "scheduler": { "index": 25, "kind": "parameter", "displayName": "Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.lang.Object", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "none", "description": "To use a cron scheduler from either camel-spring or camel-quartz component. Use value spring or quartz for built in scheduler" }, + "schedulerProperties": { "index": 26, "kind": "parameter", "displayName": "Scheduler Properties", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.Map", "prefix": "scheduler.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "To configure additional properties when using a custom scheduler or any of the Quartz, Spring based scheduler. This is a multi-value option with prefix: scheduler." }, + "startScheduler": { "index": 27, "kind": "parameter", "displayName": "Start Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether the scheduler should be auto started." }, + "timeUnit": { "index": 28, "kind": "parameter", "displayName": "Time Unit", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "enum", "javaType": "java.util.concurrent.TimeUnit", "enum": [ "NANOSECONDS", "MICROSECONDS", "MILLISECONDS", "SECONDS", "MINUTES", "HOURS", "DAYS" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "MILLISECONDS", "description": "Time unit for initialDelay and delay options." }, + "useFixedDelay": { "index": 29, "kind": "parameter", "displayName": "Use Fixed Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in JDK for details." }, + "accessKey": { "index": 30, "kind": "parameter", "displayName": "API access key (AK)", "group": "security", "label": "security", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": true, "security": "secret", "description": "Access key for the cloud user" }, + "secretKey": { "index": 31, "kind": "parameter", "displayName": "API secret key (SK)", "group": "security", "label": "security", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": true, "security": "secret", "description": "Secret key for the cloud user" }, + "serviceKeys": { "index": 32, "kind": "parameter", "displayName": "Service Configuration", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.component.alibaba.common.models.ServiceKeys", "deprecated": false, "autowired": false, "secret": true, "security": "secret", "description": "Configuration object for cloud service authentication" } + } +} diff --git a/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/services/org/apache/camel/component.properties b/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/services/org/apache/camel/component.properties new file mode 100644 index 0000000000000..e04287e28ec5f --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/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=alibaba-oss +groupId=org.apache.camel +artifactId=camel-alibaba-oss +version=4.22.0-SNAPSHOT +projectName=Camel :: Alibaba Cloud :: OSS +projectDescription=Alibaba Cloud Object Storage Service (OSS) component diff --git a/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/services/org/apache/camel/component/alibaba-oss b/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/services/org/apache/camel/component/alibaba-oss new file mode 100644 index 0000000000000..c4852dd5342d3 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/services/org/apache/camel/component/alibaba-oss @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.component.alibaba.oss.OSSComponent diff --git a/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/services/org/apache/camel/configurer/alibaba-oss-component b/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/services/org/apache/camel/configurer/alibaba-oss-component new file mode 100644 index 0000000000000..c47dbb557bd1b --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/services/org/apache/camel/configurer/alibaba-oss-component @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.component.alibaba.oss.OSSComponentConfigurer diff --git a/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/services/org/apache/camel/configurer/alibaba-oss-endpoint b/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/services/org/apache/camel/configurer/alibaba-oss-endpoint new file mode 100644 index 0000000000000..272ce632c0c72 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/services/org/apache/camel/configurer/alibaba-oss-endpoint @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.component.alibaba.oss.OSSEndpointConfigurer diff --git a/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/services/org/apache/camel/urifactory/alibaba-oss-endpoint b/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/services/org/apache/camel/urifactory/alibaba-oss-endpoint new file mode 100644 index 0000000000000..fbf5e498e1ec9 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/services/org/apache/camel/urifactory/alibaba-oss-endpoint @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.component.alibaba.oss.OSSEndpointUriFactory diff --git a/components/camel-alibaba/camel-alibaba-oss/src/main/docs/alibaba-oss-component.adoc b/components/camel-alibaba/camel-alibaba-oss/src/main/docs/alibaba-oss-component.adoc new file mode 100644 index 0000000000000..97891f33c6375 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/main/docs/alibaba-oss-component.adoc @@ -0,0 +1,102 @@ += Alibaba Object Storage Service (OSS) Component +:doctitle: Alibaba Object Storage Service (OSS) +:shortname: alibaba-oss +:artifactid: camel-alibaba-oss +:description: Alibaba Cloud Object Storage Service (OSS) component +:since: 4.22 +:supportlevel: Preview +:tabs-sync-option: +:component-header: Both producer and consumer are supported +//Manually maintained attributes +:group: Alibaba Cloud + +*Since Camel {since}* + +*{component-header}* + +The Alibaba Cloud Object Storage Service (OSS) component allows you to integrate with https://www.alibabacloud.com/product/object-storage-service[Alibaba Cloud OSS]. + +Maven users will need to add the following dependency to their `pom.xml` for this component: + +[source,xml] +---- + + org.apache.camel + camel-alibaba-oss + x.x.x + + +---- + +== URI Format + +---- +alibaba-oss:operation[?options] +---- + +// component options: START +include::partial$component-configure-options.adoc[] +include::partial$component-endpoint-options.adoc[] +include::partial$component-endpoint-headers.adoc[] +// component options: END + +== Usage + +=== Message properties evaluated by the OSS producer + +[width="100%",cols="10%,10%,80%",options="header",] +|======================================================================= +|Header |Type |Description + +|`CamelAlibabaOssOperation` |`String` | Name of operation to invoke + +|`CamelAlibabaOssBucketName` |`String` | Bucket name to invoke operation on + +|`CamelAlibabaOssObjectName` |`String` | Name of the object to be used in operation + +|`CamelAlibabaOssSourceBucketName` |`String` | Source bucket name for copy operations + +|`CamelAlibabaOssSourceObjectName` |`String` | Source object name for copy operations + +|`CamelAlibabaOssPrefix` |`String` | Prefix filter when listing objects + +|`CamelAlibabaOssMaxKeys` |`Integer` | Maximum number of keys returned when listing objects + +|======================================================================= + +If any of the above properties are set, they will override their corresponding query parameter. + +=== List of Supported OSS Operations + +- listBuckets +- listObjects - `bucketName` parameter is *required* +- putObject - `bucketName` and `objectName` parameters are *required* (unless uploading a `File`) +- getObject - `bucketName` and `objectName` parameters are *required* +- deleteObject - `bucketName` and `objectName` parameters are *required* +- copyObject - source and destination bucket/object names are *required* +- headObject - `bucketName` and `objectName` parameters are *required* + +=== Consumer + +The consumer polls objects from a bucket using `listObjectsV2`, downloads each object body, and optionally deletes objects after they have been processed when `deleteAfterRead` is enabled. + +== Examples + +=== Put an object + +[source,java] +---- +from("direct:start") + .setBody(constant("Hello OSS")) + .setProperty("CamelAlibabaOssBucketName", constant("my-bucket")) + .setProperty("CamelAlibabaOssObjectName", constant("hello.txt")) + .to("alibaba-oss:putObject?region=cn-hangzhou&accessKey=xxx&secretKey=yyy"); +---- + +=== Consume objects from a bucket + +[source,java] +---- +from("alibaba-oss:consumer?bucketName=my-bucket®ion=cn-hangzhou&accessKey=xxx&secretKey=yyy&deleteAfterRead=true") + .to("log:output"); +---- diff --git a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSComponent.java b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSComponent.java new file mode 100644 index 0000000000000..da092c20673d3 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSComponent.java @@ -0,0 +1,33 @@ +/* + * 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.alibaba.oss; + +import java.util.Map; + +import org.apache.camel.Endpoint; +import org.apache.camel.spi.annotations.Component; +import org.apache.camel.support.HealthCheckComponent; + +@Component("alibaba-oss") +public class OSSComponent extends HealthCheckComponent { + + protected Endpoint createEndpoint(String uri, String remaining, Map parameters) throws Exception { + Endpoint endpoint = new OSSEndpoint(uri, remaining, this); + setProperties(endpoint, parameters); + return endpoint; + } +} diff --git a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSConsumer.java b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSConsumer.java new file mode 100644 index 0000000000000..4398e88a3fc6a --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSConsumer.java @@ -0,0 +1,183 @@ +/* + * 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.alibaba.oss; + +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +import com.aliyun.sdk.service.oss2.OSSClient; +import com.aliyun.sdk.service.oss2.models.DeleteObjectRequest; +import com.aliyun.sdk.service.oss2.models.GetObjectRequest; +import com.aliyun.sdk.service.oss2.models.GetObjectResult; +import com.aliyun.sdk.service.oss2.models.ListObjectsV2Request; +import com.aliyun.sdk.service.oss2.models.ListObjectsV2Result; +import com.aliyun.sdk.service.oss2.models.ObjectSummary; +import com.aliyun.sdk.service.oss2.utils.IOUtils; +import org.apache.camel.AsyncCallback; +import org.apache.camel.Exchange; +import org.apache.camel.ExchangePropertyKey; +import org.apache.camel.Processor; +import org.apache.camel.component.alibaba.oss.constants.OSSHeaders; +import org.apache.camel.spi.Synchronization; +import org.apache.camel.support.ScheduledBatchPollingConsumer; +import org.apache.camel.util.CastUtils; +import org.apache.camel.util.ObjectHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class OSSConsumer extends ScheduledBatchPollingConsumer { + private static final Logger LOG = LoggerFactory.getLogger(OSSConsumer.class); + + private final OSSEndpoint endpoint; + private OSSClient ossClient; + private String continuationToken; + + public OSSConsumer(OSSEndpoint endpoint, Processor processor) { + super(endpoint, processor); + this.endpoint = endpoint; + } + + @Override + protected void doStart() throws Exception { + super.doStart(); + + this.ossClient = this.endpoint.initClient(); + + if (ObjectHelper.isEmpty(endpoint.getBucketName())) { + throw new IllegalArgumentException("Bucket name is mandatory to consume objects"); + } + } + + @Override + protected int poll() throws Exception { + shutdownRunningTask = null; + pendingExchanges = 0; + + String bucketName = endpoint.getBucketName(); + ListObjectsV2Request.Builder requestBuilder = ListObjectsV2Request.newBuilder() + .bucket(bucketName); + + if (ObjectHelper.isNotEmpty(endpoint.getPrefix())) { + requestBuilder.prefix(endpoint.getPrefix()); + } + + int maxKeys = maxMessagesPerPoll > 0 ? maxMessagesPerPoll : 10; + requestBuilder.maxKeys((long) maxKeys); + + if (continuationToken != null) { + LOG.trace("Resuming from continuation token: {}", continuationToken); + requestBuilder.continuationToken(continuationToken); + } + + ListObjectsV2Result listing = ossClient.listObjectsV2(requestBuilder.build()); + + forceConsumerAsReady(); + + if (Boolean.TRUE.equals(listing.isTruncated()) && listing.nextContinuationToken() != null) { + continuationToken = listing.nextContinuationToken(); + } else { + continuationToken = null; + } + + Queue exchanges = createExchanges(bucketName, listing.contents()); + return processBatch(CastUtils.cast(exchanges)); + } + + @Override + public int processBatch(Queue exchanges) throws Exception { + int total = exchanges.size(); + + for (int index = 0; index < total && isBatchAllowed(); index++) { + final Exchange exchange = ObjectHelper.cast(Exchange.class, exchanges.poll()); + + exchange.setProperty(ExchangePropertyKey.BATCH_SIZE, total); + exchange.setProperty(ExchangePropertyKey.BATCH_INDEX, index); + exchange.setProperty(ExchangePropertyKey.BATCH_COMPLETE, index == total - 1); + + pendingExchanges = total - index - 1; + + exchange.getExchangeExtension().addOnCompletion(new Synchronization() { + @Override + public void onComplete(Exchange exchange) { + processComplete(exchange); + } + + @Override + public void onFailure(Exchange exchange) { + processFailure(exchange); + } + }); + + AsyncCallback callback = defaultConsumerCallback(exchange, true); + getAsyncProcessor().process(exchange, callback); + } + + return total; + } + + private Queue createExchanges(String bucketName, List summaries) throws Exception { + Queue answer = new LinkedList<>(); + if (summaries == null) { + return answer; + } + + for (ObjectSummary summary : summaries) { + if (summary.key() == null || summary.key().endsWith("/")) { + continue; + } + + GetObjectResult result = ossClient.getObject(GetObjectRequest.newBuilder() + .bucket(bucketName) + .key(summary.key()) + .build()); + + byte[] body; + try (var stream = result.body()) { + body = IOUtils.toByteArray(stream); + } + + Exchange exchange = createExchange(true); + exchange.setPattern(endpoint.getExchangePattern()); + OSSUtils.mapOssObject(exchange, bucketName, summary.key(), result, body); + answer.add(exchange); + } + return answer; + } + + private void processComplete(Exchange exchange) { + if (endpoint.isDeleteAfterRead()) { + String bucketName = exchange.getIn().getHeader(OSSHeaders.BUCKET_NAME, String.class); + String objectKey = exchange.getIn().getHeader(OSSHeaders.OBJECT_KEY, String.class); + if (ObjectHelper.isNotEmpty(bucketName) && ObjectHelper.isNotEmpty(objectKey)) { + ossClient.deleteObject(DeleteObjectRequest.newBuilder() + .bucket(bucketName) + .key(objectKey) + .build()); + } + } + } + + private void processFailure(Exchange exchange) { + Exception exception = exchange.getException(); + if (exception != null) { + LOG.warn("Exchange failed, so rolling back message status: {}", exchange, exception); + } else { + LOG.warn("Exchange failed, so rolling back message status: {}", exchange); + } + } +} diff --git a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSEndpoint.java b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSEndpoint.java new file mode 100644 index 0000000000000..d025027ff89f4 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSEndpoint.java @@ -0,0 +1,240 @@ +/* + * 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.alibaba.oss; + +import com.aliyun.sdk.service.oss2.OSSClient; +import org.apache.camel.Category; +import org.apache.camel.Consumer; +import org.apache.camel.Processor; +import org.apache.camel.Producer; +import org.apache.camel.component.alibaba.common.AlibabaClientBuilderUtil; +import org.apache.camel.component.alibaba.common.models.ServiceKeys; +import org.apache.camel.component.alibaba.oss.constants.OSSHeaders; +import org.apache.camel.spi.Metadata; +import org.apache.camel.spi.UriEndpoint; +import org.apache.camel.spi.UriParam; +import org.apache.camel.spi.UriPath; +import org.apache.camel.support.ScheduledPollEndpoint; +import org.apache.camel.util.ObjectHelper; + +/** + * Alibaba Cloud Object Storage Service (OSS) component + */ +@UriEndpoint(firstVersion = "4.22.0", scheme = "alibaba-oss", title = "Alibaba Object Storage Service (OSS)", + syntax = "alibaba-oss:operation", + category = { Category.CLOUD }, headersClass = OSSHeaders.class) +public class OSSEndpoint extends ScheduledPollEndpoint { + + @UriPath(description = "Operation to be performed", displayName = "Operation", label = "producer") + @Metadata(required = true) + private String operation; + + @UriParam(description = "OSS service region", displayName = "Service region") + @Metadata(required = true) + private String region; + + @UriParam(description = "OSS endpoint URL. Carries higher precedence than region based client initialization", + displayName = "Endpoint url") + private String endpoint; + + @UriParam(description = "Configuration object for cloud service authentication", displayName = "Service Configuration", + security = "secret", label = "security") + private ServiceKeys serviceKeys; + + @UriParam(description = "Access key for the cloud user", displayName = "API access key (AK)", + security = "secret", label = "security") + @Metadata(required = true) + private String accessKey; + + @UriParam(description = "Secret key for the cloud user", displayName = "API secret key (SK)", + security = "secret", label = "security") + @Metadata(required = true) + private String secretKey; + + @UriParam(description = "Name of bucket to perform operation on", displayName = "Bucket Name", endpointIdentity = true) + private String bucketName; + + @UriParam(description = "Name of object to perform operation with", displayName = "Object Name") + private String objectName; + + @UriParam(description = "The object name prefix used for filtering objects to be listed", displayName = "Prefix", + label = "consumer") + private String prefix; + + @UriParam(description = "The maximum number of keys returned when listing objects", displayName = "Max Keys", + label = "consumer,producer") + private Integer maxKeys; + + @UriParam(description = "Determines if objects should be deleted after they have been retrieved", + displayName = "Delete after read", defaultValue = "false", label = "consumer") + private boolean deleteAfterRead; + + @UriParam(description = "The maximum number of messages to poll at each polling", displayName = "Maximum messages per poll", + defaultValue = "10", label = "consumer") + private int maxMessagesPerPoll = 10; + + @UriParam(description = "An autowired OSS client", displayName = "OSS Client", label = "advanced") + @Metadata(autowired = true) + private OSSClient ossClient; + + public OSSEndpoint() { + } + + public OSSEndpoint(String uri, String operation, OSSComponent component) { + super(uri, component); + this.operation = operation; + } + + public Producer createProducer() throws Exception { + return new OSSProducer(this); + } + + public Consumer createConsumer(Processor processor) throws Exception { + OSSConsumer consumer = new OSSConsumer(this, processor); + configureConsumer(consumer); + consumer.setMaxMessagesPerPoll(maxMessagesPerPoll); + return consumer; + } + + /** + * Initialize and return an OSS client + */ + public OSSClient initClient() { + if (ossClient != null) { + return ossClient; + } + + if (ObjectHelper.isEmpty(getServiceKeys()) && ObjectHelper.isEmpty(getAccessKey())) { + throw new IllegalArgumentException("Authentication parameter 'access key (AK)' not found"); + } + if (ObjectHelper.isEmpty(getServiceKeys()) && ObjectHelper.isEmpty(getSecretKey())) { + throw new IllegalArgumentException("Authentication parameter 'secret key (SK)' not found"); + } + if (ObjectHelper.isEmpty(getRegion()) && ObjectHelper.isEmpty(getEndpoint())) { + throw new IllegalArgumentException("Region/endpoint not found"); + } + + String auth = getServiceKeys() != null ? getServiceKeys().getAccessKey() : getAccessKey(); + String secret = getServiceKeys() != null ? getServiceKeys().getSecretKey() : getSecretKey(); + + return AlibabaClientBuilderUtil.createOssClient(auth, secret, region, endpoint); + } + + public String getOperation() { + return operation; + } + + public void setOperation(String operation) { + this.operation = operation; + } + + public String getRegion() { + return region; + } + + public void setRegion(String region) { + this.region = region; + } + + public String getEndpoint() { + return endpoint; + } + + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; + } + + public ServiceKeys getServiceKeys() { + return serviceKeys; + } + + public void setServiceKeys(ServiceKeys serviceKeys) { + this.serviceKeys = serviceKeys; + } + + public String getAccessKey() { + return accessKey; + } + + public void setAccessKey(String accessKey) { + this.accessKey = accessKey; + } + + public String getSecretKey() { + return secretKey; + } + + public void setSecretKey(String secretKey) { + this.secretKey = secretKey; + } + + public String getBucketName() { + return bucketName; + } + + public void setBucketName(String bucketName) { + this.bucketName = bucketName; + } + + public String getObjectName() { + return objectName; + } + + public void setObjectName(String objectName) { + this.objectName = objectName; + } + + public String getPrefix() { + return prefix; + } + + public void setPrefix(String prefix) { + this.prefix = prefix; + } + + public Integer getMaxKeys() { + return maxKeys; + } + + public void setMaxKeys(Integer maxKeys) { + this.maxKeys = maxKeys; + } + + public boolean isDeleteAfterRead() { + return deleteAfterRead; + } + + public void setDeleteAfterRead(boolean deleteAfterRead) { + this.deleteAfterRead = deleteAfterRead; + } + + public int getMaxMessagesPerPoll() { + return maxMessagesPerPoll; + } + + public void setMaxMessagesPerPoll(int maxMessagesPerPoll) { + this.maxMessagesPerPoll = maxMessagesPerPoll; + } + + public OSSClient getOssClient() { + return ossClient; + } + + public void setOssClient(OSSClient ossClient) { + this.ossClient = ossClient; + } +} diff --git a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSProducer.java b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSProducer.java new file mode 100644 index 0000000000000..dc16b2c4fbbad --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSProducer.java @@ -0,0 +1,365 @@ +/* + * 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.alibaba.oss; + +import java.io.File; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.aliyun.sdk.service.oss2.OSSClient; +import com.aliyun.sdk.service.oss2.models.BucketSummary; +import com.aliyun.sdk.service.oss2.models.CopyObjectRequest; +import com.aliyun.sdk.service.oss2.models.CopyObjectResult; +import com.aliyun.sdk.service.oss2.models.DeleteObjectRequest; +import com.aliyun.sdk.service.oss2.models.DeleteObjectResult; +import com.aliyun.sdk.service.oss2.models.GetObjectRequest; +import com.aliyun.sdk.service.oss2.models.GetObjectResult; +import com.aliyun.sdk.service.oss2.models.HeadObjectRequest; +import com.aliyun.sdk.service.oss2.models.HeadObjectResult; +import com.aliyun.sdk.service.oss2.models.ListBucketsRequest; +import com.aliyun.sdk.service.oss2.models.ListBucketsResult; +import com.aliyun.sdk.service.oss2.models.ListObjectsRequest; +import com.aliyun.sdk.service.oss2.models.ListObjectsResult; +import com.aliyun.sdk.service.oss2.models.ObjectSummary; +import com.aliyun.sdk.service.oss2.models.PutObjectRequest; +import com.aliyun.sdk.service.oss2.models.PutObjectResult; +import com.aliyun.sdk.service.oss2.transport.BinaryData; +import com.google.gson.Gson; +import org.apache.camel.Exchange; +import org.apache.camel.WrappedFile; +import org.apache.camel.component.alibaba.oss.constants.OSSOperations; +import org.apache.camel.component.alibaba.oss.constants.OSSProperties; +import org.apache.camel.component.alibaba.oss.models.ClientConfigurations; +import org.apache.camel.support.DefaultProducer; +import org.apache.camel.util.ObjectHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class OSSProducer extends DefaultProducer { + private static final Logger LOG = LoggerFactory.getLogger(OSSProducer.class); + + private final OSSEndpoint endpoint; + private OSSClient ossClient; + private Gson gson; + + public OSSProducer(OSSEndpoint endpoint) { + super(endpoint); + this.endpoint = endpoint; + } + + @Override + protected void doInit() throws Exception { + super.doInit(); + this.gson = new Gson(); + } + + @Override + public void process(Exchange exchange) throws Exception { + ClientConfigurations clientConfigurations = new ClientConfigurations(); + + if (ossClient == null) { + this.ossClient = endpoint.initClient(); + } + + updateClientConfigs(exchange, clientConfigurations); + + switch (clientConfigurations.getOperation()) { + case OSSOperations.LIST_BUCKETS: + listBuckets(exchange); + break; + case OSSOperations.LIST_OBJECTS: + listObjects(exchange, clientConfigurations); + break; + case OSSOperations.PUT_OBJECT: + putObject(exchange, clientConfigurations); + break; + case OSSOperations.GET_OBJECT: + getObject(exchange, clientConfigurations); + break; + case OSSOperations.DELETE_OBJECT: + deleteObject(exchange, clientConfigurations); + break; + case OSSOperations.COPY_OBJECT: + copyObject(exchange, clientConfigurations); + break; + case OSSOperations.HEAD_OBJECT: + headObject(exchange, clientConfigurations); + break; + default: + throw new UnsupportedOperationException( + String.format("%s is not a supported operation", clientConfigurations.getOperation())); + } + } + + private void putObject(Exchange exchange, ClientConfigurations clientConfigurations) throws Exception { + Object body = exchange.getMessage().getBody(); + + if (body instanceof WrappedFile wf) { + body = wf.getFile(); + } + + if ((ObjectHelper.isEmpty(clientConfigurations.getBucketName()) + || ObjectHelper.isEmpty(clientConfigurations.getObjectName())) && !(body instanceof File)) { + throw new IllegalArgumentException("Bucket and object names are mandatory to put objects into bucket"); + } + + PutObjectRequest.Builder requestBuilder = PutObjectRequest.newBuilder() + .bucket(clientConfigurations.getBucketName()); + + if (body instanceof File file) { + String objectName = ObjectHelper.isEmpty(clientConfigurations.getObjectName()) + ? file.getName() + : clientConfigurations.getObjectName(); + requestBuilder.key(objectName); + PutObjectResult result = ossClient.putObjectFromFile(requestBuilder.build(), file); + exchange.getMessage() + .setBody(gson.toJson(toPutObjectMap(result, clientConfigurations.getBucketName(), objectName))); + } else if (body instanceof String stringBody) { + requestBuilder.key(clientConfigurations.getObjectName()) + .body(BinaryData.fromString(stringBody)); + PutObjectResult result = ossClient.putObject(requestBuilder.build()); + exchange.getMessage().setBody(gson.toJson(toPutObjectMap(result, clientConfigurations.getBucketName(), + clientConfigurations.getObjectName()))); + } else if (body instanceof InputStream inputStream) { + requestBuilder.key(clientConfigurations.getObjectName()) + .body(BinaryData.fromStream(inputStream)); + PutObjectResult result = ossClient.putObject(requestBuilder.build()); + exchange.getMessage().setBody(gson.toJson(toPutObjectMap(result, clientConfigurations.getBucketName(), + clientConfigurations.getObjectName()))); + } else if (body instanceof byte[] bytes) { + requestBuilder.key(clientConfigurations.getObjectName()) + .body(BinaryData.fromBytes(bytes)); + PutObjectResult result = ossClient.putObject(requestBuilder.build()); + exchange.getMessage().setBody(gson.toJson(toPutObjectMap(result, clientConfigurations.getBucketName(), + clientConfigurations.getObjectName()))); + } else { + InputStream is = exchange.getMessage().getMandatoryBody(InputStream.class); + requestBuilder.key(clientConfigurations.getObjectName()) + .body(BinaryData.fromStream(is)); + PutObjectResult result = ossClient.putObject(requestBuilder.build()); + exchange.getMessage().setBody(gson.toJson(toPutObjectMap(result, clientConfigurations.getBucketName(), + clientConfigurations.getObjectName()))); + } + } + + private Map toPutObjectMap(PutObjectResult result, String bucketName, String objectName) { + Map map = new HashMap<>(); + map.put("bucketName", bucketName); + map.put("objectKey", objectName); + map.put("eTag", result.eTag()); + map.put("contentMd5", result.contentMd5()); + map.put("versionId", result.versionId()); + map.put("statusCode", result.statusCode()); + return map; + } + + private void getObject(Exchange exchange, ClientConfigurations clientConfigurations) throws Exception { + if (ObjectHelper.isEmpty(clientConfigurations.getBucketName()) + || ObjectHelper.isEmpty(clientConfigurations.getObjectName())) { + throw new IllegalArgumentException("Bucket and object names are mandatory to get objects"); + } + + LOG.debug("Downloading OSS object {} from bucket {}", clientConfigurations.getObjectName(), + clientConfigurations.getBucketName()); + + GetObjectResult result = ossClient.getObject(GetObjectRequest.newBuilder() + .bucket(clientConfigurations.getBucketName()) + .key(clientConfigurations.getObjectName()) + .build()); + + OSSUtils.mapOssObject(exchange, clientConfigurations.getBucketName(), clientConfigurations.getObjectName(), result); + } + + private void listBuckets(Exchange exchange) { + ListBucketsResult response = ossClient.listBuckets(ListBucketsRequest.newBuilder().build()); + List> buckets = new ArrayList<>(); + if (response.buckets() != null) { + for (BucketSummary bucket : response.buckets()) { + Map bucketMap = new HashMap<>(); + bucketMap.put("name", bucket.name()); + bucketMap.put("region", bucket.region()); + bucketMap.put("storageClass", bucket.storageClass()); + buckets.add(bucketMap); + } + } + exchange.getMessage().setBody(gson.toJson(buckets)); + } + + private void listObjects(Exchange exchange, ClientConfigurations clientConfigurations) { + if (ObjectHelper.isEmpty(clientConfigurations.getBucketName())) { + throw new IllegalArgumentException("Bucket name is mandatory to list objects"); + } + + ListObjectsRequest.Builder requestBuilder = ListObjectsRequest.newBuilder() + .bucket(clientConfigurations.getBucketName()); + + if (ObjectHelper.isNotEmpty(clientConfigurations.getPrefix())) { + requestBuilder.prefix(clientConfigurations.getPrefix()); + } + if (clientConfigurations.getMaxKeys() != null) { + requestBuilder.maxKeys(clientConfigurations.getMaxKeys().longValue()); + } + + List> objects = new ArrayList<>(); + ListObjectsResult result; + ListObjectsRequest request = requestBuilder.build(); + do { + result = ossClient.listObjects(request); + if (result.contents() != null) { + for (ObjectSummary summary : result.contents()) { + Map objectMap = new HashMap<>(); + objectMap.put("bucketName", clientConfigurations.getBucketName()); + objectMap.put("objectKey", summary.key()); + objectMap.put("size", summary.size()); + objectMap.put("eTag", summary.eTag()); + objectMap.put("lastModified", summary.lastModified() != null ? summary.lastModified().toString() : null); + objects.add(objectMap); + } + } + if (Boolean.TRUE.equals(result.isTruncated()) && result.nextMarker() != null) { + request = request.toBuilder().marker(result.nextMarker()).build(); + } else { + break; + } + } while (Boolean.TRUE.equals(result.isTruncated())); + + exchange.getMessage().setBody(gson.toJson(objects)); + } + + private void deleteObject(Exchange exchange, ClientConfigurations clientConfigurations) { + if (ObjectHelper.isEmpty(clientConfigurations.getBucketName()) + || ObjectHelper.isEmpty(clientConfigurations.getObjectName())) { + throw new IllegalArgumentException("Bucket and object names are mandatory to delete objects"); + } + + DeleteObjectResult result = ossClient.deleteObject(DeleteObjectRequest.newBuilder() + .bucket(clientConfigurations.getBucketName()) + .key(clientConfigurations.getObjectName()) + .build()); + + Map map = new HashMap<>(); + map.put("statusCode", result.statusCode()); + map.put("requestId", result.requestId()); + map.put("deleteMarker", result.deleteMarker()); + map.put("versionId", result.versionId()); + exchange.getMessage().setBody(gson.toJson(map)); + } + + private void copyObject(Exchange exchange, ClientConfigurations clientConfigurations) { + if (ObjectHelper.isEmpty(clientConfigurations.getSourceBucketName()) + || ObjectHelper.isEmpty(clientConfigurations.getSourceObjectName()) + || ObjectHelper.isEmpty(clientConfigurations.getBucketName()) + || ObjectHelper.isEmpty(clientConfigurations.getObjectName())) { + throw new IllegalArgumentException( + "Source bucket, source object, destination bucket and destination object names are mandatory to copy objects"); + } + + CopyObjectResult result = ossClient.copyObject(CopyObjectRequest.newBuilder() + .sourceBucket(clientConfigurations.getSourceBucketName()) + .sourceKey(clientConfigurations.getSourceObjectName()) + .bucket(clientConfigurations.getBucketName()) + .key(clientConfigurations.getObjectName()) + .build()); + + Map map = new HashMap<>(); + map.put("eTag", result.eTag()); + map.put("lastModified", result.lastModified()); + map.put("statusCode", result.statusCode()); + map.put("requestId", result.requestId()); + exchange.getMessage().setBody(gson.toJson(map)); + } + + private void headObject(Exchange exchange, ClientConfigurations clientConfigurations) { + if (ObjectHelper.isEmpty(clientConfigurations.getBucketName()) + || ObjectHelper.isEmpty(clientConfigurations.getObjectName())) { + throw new IllegalArgumentException("Bucket and object names are mandatory to head objects"); + } + + HeadObjectResult result = ossClient.headObject(HeadObjectRequest.newBuilder() + .bucket(clientConfigurations.getBucketName()) + .key(clientConfigurations.getObjectName()) + .build()); + + Map map = new HashMap<>(); + map.put("eTag", result.eTag()); + map.put("contentLength", result.contentLength()); + map.put("contentType", result.contentType()); + map.put("contentMd5", result.contentMd5()); + map.put("lastModified", result.lastModified()); + map.put("storageClass", result.storageClass()); + map.put("metadata", result.metadata()); + map.put("statusCode", result.statusCode()); + map.put("requestId", result.requestId()); + exchange.getMessage().setBody(gson.toJson(map)); + } + + private void updateClientConfigs(Exchange exchange, ClientConfigurations clientConfigurations) { + if (ObjectHelper.isEmpty(exchange.getProperty(OSSProperties.OPERATION)) + && ObjectHelper.isEmpty(endpoint.getOperation())) { + LOG.error("No operation name given. Cannot proceed with OSS operations."); + throw new IllegalArgumentException("Operation name not found"); + } else { + clientConfigurations.setOperation( + ObjectHelper.isNotEmpty(exchange.getProperty(OSSProperties.OPERATION)) + ? (String) exchange.getProperty(OSSProperties.OPERATION) + : endpoint.getOperation()); + } + + if (ObjectHelper.isNotEmpty(exchange.getProperty(OSSProperties.BUCKET_NAME)) + || ObjectHelper.isNotEmpty(endpoint.getBucketName())) { + clientConfigurations.setBucketName( + ObjectHelper.isNotEmpty(exchange.getProperty(OSSProperties.BUCKET_NAME)) + ? (String) exchange.getProperty(OSSProperties.BUCKET_NAME) + : endpoint.getBucketName()); + } + + if (ObjectHelper.isNotEmpty(exchange.getProperty(OSSProperties.OBJECT_NAME)) + || ObjectHelper.isNotEmpty(endpoint.getObjectName())) { + clientConfigurations.setObjectName( + ObjectHelper.isNotEmpty(exchange.getProperty(OSSProperties.OBJECT_NAME)) + ? (String) exchange.getProperty(OSSProperties.OBJECT_NAME) + : endpoint.getObjectName()); + } + + if (ObjectHelper.isNotEmpty(exchange.getProperty(OSSProperties.SOURCE_BUCKET_NAME))) { + clientConfigurations.setSourceBucketName((String) exchange.getProperty(OSSProperties.SOURCE_BUCKET_NAME)); + } + + if (ObjectHelper.isNotEmpty(exchange.getProperty(OSSProperties.SOURCE_OBJECT_NAME))) { + clientConfigurations.setSourceObjectName((String) exchange.getProperty(OSSProperties.SOURCE_OBJECT_NAME)); + } + + if (ObjectHelper.isNotEmpty(exchange.getProperty(OSSProperties.PREFIX)) + || ObjectHelper.isNotEmpty(endpoint.getPrefix())) { + clientConfigurations.setPrefix( + ObjectHelper.isNotEmpty(exchange.getProperty(OSSProperties.PREFIX)) + ? (String) exchange.getProperty(OSSProperties.PREFIX) + : endpoint.getPrefix()); + } + + if (ObjectHelper.isNotEmpty(exchange.getProperty(OSSProperties.MAX_KEYS)) + || ObjectHelper.isNotEmpty(endpoint.getMaxKeys())) { + clientConfigurations.setMaxKeys( + ObjectHelper.isNotEmpty(exchange.getProperty(OSSProperties.MAX_KEYS)) + ? (Integer) exchange.getProperty(OSSProperties.MAX_KEYS) + : endpoint.getMaxKeys()); + } + } +} diff --git a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSUtils.java b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSUtils.java new file mode 100644 index 0000000000000..81b2981834bc1 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSUtils.java @@ -0,0 +1,86 @@ +/* + * 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.alibaba.oss; + +import java.io.IOException; +import java.io.InputStream; + +import com.aliyun.sdk.service.oss2.models.GetObjectResult; +import com.aliyun.sdk.service.oss2.utils.IOUtils; +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.apache.camel.RuntimeCamelException; +import org.apache.camel.component.alibaba.oss.constants.OSSConstants; +import org.apache.camel.component.alibaba.oss.constants.OSSHeaders; + +public final class OSSUtils { + private OSSUtils() { + } + + /** + * Maps the OSS object along with all its metadata into the exchange + */ + public static void mapOssObject(Exchange exchange, String bucketName, String objectKey, GetObjectResult result) + throws IOException { + Message message = exchange.getIn(); + + try (InputStream stream = result.body()) { + message.setBody(IOUtils.toByteArray(stream)); + } + + message.setHeader(OSSHeaders.BUCKET_NAME, bucketName); + message.setHeader(OSSHeaders.OBJECT_KEY, objectKey); + message.setHeader(OSSHeaders.LAST_MODIFIED, result.lastModified()); + message.setHeader(OSSHeaders.CONTENT_LENGTH, result.contentLength()); + message.setHeader(OSSHeaders.CONTENT_TYPE, result.contentType()); + message.setHeader(OSSHeaders.ETAG, result.eTag()); + message.setHeader(OSSHeaders.CONTENT_MD5, result.contentMd5()); + message.setHeader(OSSHeaders.FILE_NAME, objectKey); + + if (objectKey != null && objectKey.endsWith("/")) { + message.setHeader(OSSHeaders.OBJECT_TYPE, OSSConstants.FOLDER); + } else { + message.setHeader(OSSHeaders.OBJECT_TYPE, OSSConstants.FILE); + } + } + + public static void mapOssObject( + Exchange exchange, String bucketName, String objectKey, GetObjectResult result, + byte[] body) { + Message message = exchange.getIn(); + message.setBody(body); + + message.setHeader(OSSHeaders.BUCKET_NAME, bucketName); + message.setHeader(OSSHeaders.OBJECT_KEY, objectKey); + message.setHeader(OSSHeaders.LAST_MODIFIED, result.lastModified()); + message.setHeader(OSSHeaders.CONTENT_LENGTH, result.contentLength()); + message.setHeader(OSSHeaders.CONTENT_TYPE, result.contentType()); + message.setHeader(OSSHeaders.ETAG, result.eTag()); + message.setHeader(OSSHeaders.CONTENT_MD5, result.contentMd5()); + message.setHeader(OSSHeaders.FILE_NAME, objectKey); + + if (objectKey != null && objectKey.endsWith("/")) { + message.setHeader(OSSHeaders.OBJECT_TYPE, OSSConstants.FOLDER); + } else { + message.setHeader(OSSHeaders.OBJECT_TYPE, OSSConstants.FILE); + } + } + + public static RuntimeCamelException wrapIOException(IOException e) { + return new RuntimeCamelException(e); + } +} diff --git a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/constants/OSSConstants.java b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/constants/OSSConstants.java new file mode 100644 index 0000000000000..b9b52f7cc0231 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/constants/OSSConstants.java @@ -0,0 +1,28 @@ +/* + * 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.alibaba.oss.constants; + +/** + * Constants for OSS + */ +public final class OSSConstants { + public static final String FOLDER = "folder"; + public static final String FILE = "file"; + + private OSSConstants() { + } +} diff --git a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/constants/OSSHeaders.java b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/constants/OSSHeaders.java new file mode 100644 index 0000000000000..dbb1753dec93a --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/constants/OSSHeaders.java @@ -0,0 +1,48 @@ +/* + * 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.alibaba.oss.constants; + +import org.apache.camel.Exchange; +import org.apache.camel.spi.Metadata; + +/** + * Constants for the exchange headers when consuming objects + */ +public final class OSSHeaders { + @Metadata(label = "consumer", description = "Name of the bucket where object is contained", javaType = "String") + public static final String BUCKET_NAME = "CamelAlibabaOssBucketName"; + @Metadata(label = "consumer", description = "The key that the object is stored under", javaType = "String") + public static final String OBJECT_KEY = "CamelAlibabaOssObjectKey"; + @Metadata(label = "consumer", description = "The date and time that the object was last modified", javaType = "String") + public static final String LAST_MODIFIED = "CamelAlibabaOssLastModified"; + @Metadata(label = "consumer", description = "The 128-bit MD5 digest of the object content", javaType = "String") + public static final String ETAG = "CamelAlibabaOssETag"; + @Metadata(label = "consumer", description = "The 128-bit Base64-encoded digest of the object", javaType = "String") + public static final String CONTENT_MD5 = "CamelAlibabaOssContentMD5"; + @Metadata(label = "consumer", description = "Shows whether the object is a `file` or a `folder`", javaType = "String") + public static final String OBJECT_TYPE = "CamelAlibabaOssObjectType"; + @Metadata(label = "consumer", description = "The size of the object body in bytes", javaType = "Long") + public static final String CONTENT_LENGTH = Exchange.CONTENT_LENGTH; + @Metadata(label = "consumer", description = "The type of content stored in the object", javaType = "String") + public static final String CONTENT_TYPE = Exchange.CONTENT_TYPE; + @Metadata(label = "consumer", description = "Name of the object with which the operation is to be performed", + javaType = "String") + public static final String FILE_NAME = Exchange.FILE_NAME; + + private OSSHeaders() { + } +} diff --git a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/constants/OSSOperations.java b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/constants/OSSOperations.java new file mode 100644 index 0000000000000..4f3d7d60f7428 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/constants/OSSOperations.java @@ -0,0 +1,33 @@ +/* + * 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.alibaba.oss.constants; + +/** + * Constants for all the supported OSS operations + */ +public final class OSSOperations { + public static final String LIST_BUCKETS = "listBuckets"; + public static final String LIST_OBJECTS = "listObjects"; + public static final String PUT_OBJECT = "putObject"; + public static final String GET_OBJECT = "getObject"; + public static final String DELETE_OBJECT = "deleteObject"; + public static final String COPY_OBJECT = "copyObject"; + public static final String HEAD_OBJECT = "headObject"; + + private OSSOperations() { + } +} diff --git a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/constants/OSSProperties.java b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/constants/OSSProperties.java new file mode 100644 index 0000000000000..3814d07cddfa9 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/constants/OSSProperties.java @@ -0,0 +1,33 @@ +/* + * 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.alibaba.oss.constants; + +/** + * Constants for properties set on the exchange object + */ +public final class OSSProperties { + public static final String OPERATION = "CamelAlibabaOssOperation"; + public static final String BUCKET_NAME = "CamelAlibabaOssBucketName"; + public static final String OBJECT_NAME = "CamelAlibabaOssObjectName"; + public static final String SOURCE_BUCKET_NAME = "CamelAlibabaOssSourceBucketName"; + public static final String SOURCE_OBJECT_NAME = "CamelAlibabaOssSourceObjectName"; + public static final String PREFIX = "CamelAlibabaOssPrefix"; + public static final String MAX_KEYS = "CamelAlibabaOssMaxKeys"; + + private OSSProperties() { + } +} diff --git a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/models/ClientConfigurations.java b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/models/ClientConfigurations.java new file mode 100644 index 0000000000000..b1af5c06e6363 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/models/ClientConfigurations.java @@ -0,0 +1,89 @@ +/* + * 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.alibaba.oss.models; + +/** + * Class to combine parameters which can be passed through exchange properties and endpoint parameters + */ +public class ClientConfigurations { + private String operation; + private String bucketName; + private String objectName; + private String sourceBucketName; + private String sourceObjectName; + private String prefix; + private Integer maxKeys; + + public ClientConfigurations() { + } + + public String getOperation() { + return operation; + } + + public void setOperation(String operation) { + this.operation = operation; + } + + public String getBucketName() { + return bucketName; + } + + public void setBucketName(String bucketName) { + this.bucketName = bucketName; + } + + public String getObjectName() { + return objectName; + } + + public void setObjectName(String objectName) { + this.objectName = objectName; + } + + public String getSourceBucketName() { + return sourceBucketName; + } + + public void setSourceBucketName(String sourceBucketName) { + this.sourceBucketName = sourceBucketName; + } + + public String getSourceObjectName() { + return sourceObjectName; + } + + public void setSourceObjectName(String sourceObjectName) { + this.sourceObjectName = sourceObjectName; + } + + public String getPrefix() { + return prefix; + } + + public void setPrefix(String prefix) { + this.prefix = prefix; + } + + public Integer getMaxKeys() { + return maxKeys; + } + + public void setMaxKeys(Integer maxKeys) { + this.maxKeys = maxKeys; + } +} diff --git a/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/DeleteObjectTest.java b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/DeleteObjectTest.java new file mode 100644 index 0000000000000..ae295d97e0a11 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/DeleteObjectTest.java @@ -0,0 +1,84 @@ +/* + * 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.alibaba.oss; + +import com.aliyun.sdk.service.oss2.OSSClient; +import com.aliyun.sdk.service.oss2.models.DeleteObjectRequest; +import com.aliyun.sdk.service.oss2.models.DeleteObjectResult; +import org.apache.camel.BindToRegistry; +import org.apache.camel.Exchange; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.alibaba.common.models.ServiceKeys; +import org.apache.camel.component.alibaba.oss.constants.OSSProperties; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.junit6.CamelTestSupport; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import static org.assertj.core.api.Assertions.assertThat; + +class DeleteObjectTest extends CamelTestSupport { + + TestConfiguration testConfiguration = new TestConfiguration(); + + @BindToRegistry("ossClient") + OSSClient mockClient = Mockito.mock(OSSClient.class); + + @BindToRegistry("serviceKeys") + ServiceKeys serviceKeys = new ServiceKeys( + testConfiguration.getProperty("accessKey"), + testConfiguration.getProperty("secretKey")); + + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + from("direct:delete_object") + .setProperty(OSSProperties.BUCKET_NAME, constant(testConfiguration.getProperty("bucketName"))) + .setProperty(OSSProperties.OBJECT_NAME, constant(testConfiguration.getProperty("objectName"))) + .to("alibaba-oss:deleteObject?" + + "serviceKeys=#serviceKeys" + + "®ion=" + testConfiguration.getProperty("region") + + "&ossClient=#ossClient") + .to("mock:delete_object_result"); + } + }; + } + + @Test + void testDeleteObject() throws Exception { + DeleteObjectResult result = Mockito.mock(DeleteObjectResult.class); + Mockito.when(result.statusCode()).thenReturn(204); + Mockito.when(result.requestId()).thenReturn("request-id-123"); + Mockito.when(result.deleteMarker()).thenReturn(false); + Mockito.when(result.versionId()).thenReturn("version-1"); + + Mockito.when(mockClient.deleteObject(Mockito.any(DeleteObjectRequest.class))).thenReturn(result); + + MockEndpoint mock = getMockEndpoint("mock:delete_object_result"); + mock.expectedMinimumMessageCount(1); + template.sendBody("direct:delete_object", "sample_body"); + Exchange responseExchange = mock.getExchanges().get(0); + + mock.assertIsSatisfied(); + + assertThat(responseExchange.getIn().getBody(String.class)) + .contains("\"statusCode\":204") + .contains("\"requestId\":\"request-id-123\""); + } +} diff --git a/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/GetObjectTest.java b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/GetObjectTest.java new file mode 100644 index 0000000000000..532fe1906d638 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/GetObjectTest.java @@ -0,0 +1,101 @@ +/* + * 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.alibaba.oss; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import com.aliyun.sdk.service.oss2.OSSClient; +import com.aliyun.sdk.service.oss2.models.GetObjectRequest; +import com.aliyun.sdk.service.oss2.models.GetObjectResult; +import org.apache.camel.BindToRegistry; +import org.apache.camel.Exchange; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.alibaba.common.models.ServiceKeys; +import org.apache.camel.component.alibaba.oss.constants.OSSHeaders; +import org.apache.camel.component.alibaba.oss.constants.OSSProperties; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.junit6.CamelTestSupport; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import static org.assertj.core.api.Assertions.assertThat; + +class GetObjectTest extends CamelTestSupport { + + TestConfiguration testConfiguration = new TestConfiguration(); + + String bucketName = "test-bucket"; + String objectName = "test_file.txt"; + + @BindToRegistry("ossClient") + OSSClient mockClient = Mockito.mock(OSSClient.class); + + @BindToRegistry("serviceKeys") + ServiceKeys serviceKeys = new ServiceKeys( + testConfiguration.getProperty("accessKey"), + testConfiguration.getProperty("secretKey")); + + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + from("direct:get_object") + .setProperty(OSSProperties.BUCKET_NAME, constant(bucketName)) + .setProperty(OSSProperties.OBJECT_NAME, constant(objectName)) + .to("alibaba-oss:getObject?" + + "accessKey=" + testConfiguration.getProperty("accessKey") + + "&secretKey=" + testConfiguration.getProperty("secretKey") + + "®ion=" + testConfiguration.getProperty("region") + + "&ossClient=#ossClient") + .to("mock:get_object_result"); + } + }; + } + + @Test + void testGetObject() throws Exception { + GetObjectResult response = Mockito.mock(GetObjectResult.class); + InputStream stream = new ByteArrayInputStream("hello oss".getBytes()); + Mockito.when(response.body()).thenReturn(stream); + Mockito.when(response.contentLength()).thenReturn(9L); + Mockito.when(response.contentType()).thenReturn("text/plain"); + Mockito.when(response.eTag()).thenReturn("eb733a00c0c9d336e65691a37ab54293"); + Mockito.when(response.contentMd5()).thenReturn("63M6AMDJ0zbmVpGjerVCkw=="); + Mockito.when(response.lastModified()).thenReturn("2024-01-01T00:00:00Z"); + + Mockito.when(mockClient.getObject(Mockito.any(GetObjectRequest.class))).thenReturn(response); + + MockEndpoint mock = getMockEndpoint("mock:get_object_result"); + mock.expectedMinimumMessageCount(1); + template.sendBody("direct:get_object", "dummy"); + Exchange responseExchange = mock.getExchanges().get(0); + + mock.assertIsSatisfied(); + + assertThat(responseExchange.getIn().getHeader(Exchange.CONTENT_LENGTH)).isEqualTo(9L); + assertThat(responseExchange.getIn().getHeader(Exchange.CONTENT_TYPE)).isEqualTo("text/plain"); + assertThat(responseExchange.getIn().getHeader(OSSHeaders.ETAG)).isEqualTo("eb733a00c0c9d336e65691a37ab54293"); + assertThat(responseExchange.getIn().getHeader(OSSHeaders.CONTENT_MD5)).isEqualTo("63M6AMDJ0zbmVpGjerVCkw=="); + assertThat(responseExchange.getIn().getHeader(OSSHeaders.LAST_MODIFIED)).isEqualTo("2024-01-01T00:00:00Z"); + assertThat(responseExchange.getIn().getHeader(OSSHeaders.BUCKET_NAME)).isEqualTo(bucketName); + assertThat(responseExchange.getIn().getHeader(OSSHeaders.OBJECT_KEY)).isEqualTo(objectName); + assertThat(responseExchange.getIn().getHeader(Exchange.FILE_NAME)).isEqualTo(objectName); + assertThat(responseExchange.getIn().getBody(byte[].class)).isEqualTo("hello oss".getBytes()); + } +} diff --git a/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/HeadObjectTest.java b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/HeadObjectTest.java new file mode 100644 index 0000000000000..099e5d990592c --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/HeadObjectTest.java @@ -0,0 +1,91 @@ +/* + * 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.alibaba.oss; + +import com.aliyun.sdk.service.oss2.OSSClient; +import com.aliyun.sdk.service.oss2.models.HeadObjectRequest; +import com.aliyun.sdk.service.oss2.models.HeadObjectResult; +import org.apache.camel.BindToRegistry; +import org.apache.camel.Exchange; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.alibaba.common.models.ServiceKeys; +import org.apache.camel.component.alibaba.oss.constants.OSSProperties; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.junit6.CamelTestSupport; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import static org.assertj.core.api.Assertions.assertThat; + +class HeadObjectTest extends CamelTestSupport { + + TestConfiguration testConfiguration = new TestConfiguration(); + + @BindToRegistry("ossClient") + OSSClient mockClient = Mockito.mock(OSSClient.class); + + @BindToRegistry("serviceKeys") + ServiceKeys serviceKeys = new ServiceKeys( + testConfiguration.getProperty("accessKey"), + testConfiguration.getProperty("secretKey")); + + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + from("direct:head_object") + .setProperty(OSSProperties.BUCKET_NAME, constant(testConfiguration.getProperty("bucketName"))) + .setProperty(OSSProperties.OBJECT_NAME, constant(testConfiguration.getProperty("objectName"))) + .to("alibaba-oss:headObject?" + + "serviceKeys=#serviceKeys" + + "®ion=" + testConfiguration.getProperty("region") + + "&ossClient=#ossClient") + .to("mock:head_object_result"); + } + }; + } + + @Test + void testHeadObject() throws Exception { + HeadObjectResult result = Mockito.mock(HeadObjectResult.class); + Mockito.when(result.eTag()).thenReturn("eb733a00c0c9d336e65691a37ab54293"); + Mockito.when(result.contentLength()).thenReturn(1024L); + Mockito.when(result.contentType()).thenReturn("text/plain"); + Mockito.when(result.contentMd5()).thenReturn("content-md5"); + Mockito.when(result.lastModified()).thenReturn("2024-01-01T00:00:00Z"); + Mockito.when(result.storageClass()).thenReturn("Standard"); + Mockito.when(result.metadata()).thenReturn(java.util.Map.of("custom", "value")); + Mockito.when(result.statusCode()).thenReturn(200); + Mockito.when(result.requestId()).thenReturn("request-id-456"); + + Mockito.when(mockClient.headObject(Mockito.any(HeadObjectRequest.class))).thenReturn(result); + + MockEndpoint mock = getMockEndpoint("mock:head_object_result"); + mock.expectedMinimumMessageCount(1); + template.sendBody("direct:head_object", "sample_body"); + Exchange responseExchange = mock.getExchanges().get(0); + + mock.assertIsSatisfied(); + + assertThat(responseExchange.getIn().getBody(String.class)) + .contains("\"eTag\":\"eb733a00c0c9d336e65691a37ab54293\"") + .contains("\"contentLength\":1024") + .contains("\"contentType\":\"text/plain\"") + .contains("\"storageClass\":\"Standard\""); + } +} diff --git a/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/ListObjectsTest.java b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/ListObjectsTest.java new file mode 100644 index 0000000000000..c289c10d6d4c7 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/ListObjectsTest.java @@ -0,0 +1,99 @@ +/* + * 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.alibaba.oss; + +import java.time.Instant; +import java.util.List; + +import com.aliyun.sdk.service.oss2.OSSClient; +import com.aliyun.sdk.service.oss2.models.ListObjectsRequest; +import com.aliyun.sdk.service.oss2.models.ListObjectsResult; +import com.aliyun.sdk.service.oss2.models.ObjectSummary; +import org.apache.camel.BindToRegistry; +import org.apache.camel.Exchange; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.alibaba.common.models.ServiceKeys; +import org.apache.camel.component.alibaba.oss.constants.OSSProperties; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.junit6.CamelTestSupport; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import static org.assertj.core.api.Assertions.assertThat; + +class ListObjectsTest extends CamelTestSupport { + + TestConfiguration testConfiguration = new TestConfiguration(); + + @BindToRegistry("ossClient") + OSSClient mockClient = Mockito.mock(OSSClient.class); + + @BindToRegistry("serviceKeys") + ServiceKeys serviceKeys = new ServiceKeys( + testConfiguration.getProperty("accessKey"), + testConfiguration.getProperty("secretKey")); + + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + from("direct:list_objects") + .setProperty(OSSProperties.BUCKET_NAME, constant(testConfiguration.getProperty("bucketName"))) + .to("alibaba-oss:listObjects?" + + "serviceKeys=#serviceKeys" + + "®ion=" + testConfiguration.getProperty("region") + + "&ossClient=#ossClient") + .to("mock:list_objects_result"); + } + }; + } + + @Test + void testListObjects() throws Exception { + ObjectSummary object1 = ObjectSummary.newBuilder() + .key("Object 1") + .size(100L) + .eTag("etag-1") + .lastModified(Instant.parse("2024-01-01T00:00:00Z")) + .build(); + ObjectSummary object2 = ObjectSummary.newBuilder() + .key("Object 2") + .size(200L) + .eTag("etag-2") + .lastModified(Instant.parse("2024-01-02T00:00:00Z")) + .build(); + + ListObjectsResult listing = Mockito.mock(ListObjectsResult.class); + Mockito.when(listing.contents()).thenReturn(List.of(object1, object2)); + Mockito.when(listing.isTruncated()).thenReturn(false); + + Mockito.when(mockClient.listObjects(Mockito.any(ListObjectsRequest.class))).thenReturn(listing); + + MockEndpoint mock = getMockEndpoint("mock:list_objects_result"); + mock.expectedMinimumMessageCount(1); + template.sendBody("direct:list_objects", "sample_body"); + Exchange responseExchange = mock.getExchanges().get(0); + + mock.assertIsSatisfied(); + + assertThat(responseExchange.getIn().getBody(String.class)) + .contains("\"objectKey\":\"Object 1\"") + .contains("\"objectKey\":\"Object 2\"") + .contains("\"bucketName\":\"dummy_bucket_name\""); + } +} diff --git a/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/PutObjectTest.java b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/PutObjectTest.java new file mode 100644 index 0000000000000..29bad18384f19 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/PutObjectTest.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.alibaba.oss; + +import com.aliyun.sdk.service.oss2.OSSClient; +import com.aliyun.sdk.service.oss2.models.PutObjectRequest; +import com.aliyun.sdk.service.oss2.models.PutObjectResult; +import org.apache.camel.BindToRegistry; +import org.apache.camel.Exchange; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.alibaba.common.models.ServiceKeys; +import org.apache.camel.component.alibaba.oss.constants.OSSProperties; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.junit6.CamelTestSupport; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import static org.assertj.core.api.Assertions.assertThat; + +class PutObjectTest extends CamelTestSupport { + + TestConfiguration testConfiguration = new TestConfiguration(); + + @BindToRegistry("ossClient") + OSSClient mockClient = Mockito.mock(OSSClient.class); + + @BindToRegistry("serviceKeys") + ServiceKeys serviceKeys = new ServiceKeys( + testConfiguration.getProperty("accessKey"), + testConfiguration.getProperty("secretKey")); + + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + from("direct:put_object") + .setBody(constant("a test string")) + .setProperty(OSSProperties.OBJECT_NAME, constant("string_file.txt")) + .setProperty(OSSProperties.BUCKET_NAME, constant("test-bucket")) + .to("alibaba-oss:putObject?" + + "serviceKeys=#serviceKeys" + + "®ion=" + testConfiguration.getProperty("region") + + "&ossClient=#ossClient") + .to("mock:put_object_result"); + } + }; + } + + @Test + void putObjectStringTest() throws Exception { + PutObjectResult putObjectResult = Mockito.mock(PutObjectResult.class); + Mockito.when(putObjectResult.eTag()).thenReturn("eb733a00c0c9d336e65691a37ab54293"); + Mockito.when(putObjectResult.contentMd5()).thenReturn("content-md5"); + Mockito.when(putObjectResult.versionId()).thenReturn("version-xxx"); + Mockito.when(putObjectResult.statusCode()).thenReturn(200); + + Mockito.when(mockClient.putObject(Mockito.any(PutObjectRequest.class))) + .thenReturn(putObjectResult); + + MockEndpoint mock = getMockEndpoint("mock:put_object_result"); + mock.expectedMinimumMessageCount(1); + template.sendBody("direct:put_object", "sample file content"); + Exchange responseExchange = mock.getExchanges().get(0); + + mock.assertIsSatisfied(); + + assertThat(responseExchange.getIn().getBody(String.class)) + .contains("\"bucketName\":\"test-bucket\"") + .contains("\"objectKey\":\"string_file.txt\"") + .contains("\"eTag\":\"eb733a00c0c9d336e65691a37ab54293\""); + } +} diff --git a/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/TestConfiguration.java b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/TestConfiguration.java new file mode 100644 index 0000000000000..3441d8e7cb49a --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/TestConfiguration.java @@ -0,0 +1,45 @@ +/* + * 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.alibaba.oss; + +import java.util.HashMap; +import java.util.Map; + +public class TestConfiguration { + private static Map propertyMap; + + public TestConfiguration() { + initPropertyMap(); + } + + private void initPropertyMap() { + propertyMap = new HashMap<>(); + propertyMap.put("accessKey", "dummy_access_key"); + propertyMap.put("secretKey", "dummy_secret_key"); + propertyMap.put("region", "cn-hangzhou"); + propertyMap.put("endpoint", "https://oss-cn-hangzhou.aliyuncs.com"); + propertyMap.put("bucketName", "dummy_bucket_name"); + propertyMap.put("objectName", "dummy_object.txt"); + } + + public String getProperty(String key) { + if (propertyMap == null) { + initPropertyMap(); + } + return propertyMap.get(key); + } +} diff --git a/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/constants/OSSOperationsTest.java b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/constants/OSSOperationsTest.java new file mode 100644 index 0000000000000..f1d43acf68034 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/constants/OSSOperationsTest.java @@ -0,0 +1,34 @@ +/* + * 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.alibaba.oss.constants; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class OSSOperationsTest { + @Test + void testOperations() { + assertThat(OSSOperations.LIST_BUCKETS).isEqualTo("listBuckets"); + assertThat(OSSOperations.LIST_OBJECTS).isEqualTo("listObjects"); + assertThat(OSSOperations.PUT_OBJECT).isEqualTo("putObject"); + assertThat(OSSOperations.GET_OBJECT).isEqualTo("getObject"); + assertThat(OSSOperations.DELETE_OBJECT).isEqualTo("deleteObject"); + assertThat(OSSOperations.COPY_OBJECT).isEqualTo("copyObject"); + assertThat(OSSOperations.HEAD_OBJECT).isEqualTo("headObject"); + } +} diff --git a/components/camel-alibaba/camel-alibaba-oss/src/test/resources/log4j2.properties b/components/camel-alibaba/camel-alibaba-oss/src/test/resources/log4j2.properties new file mode 100644 index 0000000000000..a4c7b3d181092 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/test/resources/log4j2.properties @@ -0,0 +1,29 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- +rootLogger.level = INFO +rootLogger.appenderRef.stdout.ref = console + +appender.console.type = Console +appender.console.name = console +appender.console.layout.type = PatternLayout +appender.console.layout.pattern = %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n + +logger.camel.name = org.apache.camel +logger.camel.level = INFO + +logger.oss.name = org.apache.camel.component.alibaba.oss +logger.oss.level = DEBUG diff --git a/components/camel-alibaba/pom.xml b/components/camel-alibaba/pom.xml new file mode 100644 index 0000000000000..ee08cf0fec4cd --- /dev/null +++ b/components/camel-alibaba/pom.xml @@ -0,0 +1,41 @@ + + + + + 4.0.0 + + + org.apache.camel + components + 4.22.0-SNAPSHOT + + + camel-alibaba-parent + pom + Camel :: Alibaba Cloud :: Parent + Camel Alibaba Cloud parent + + + camel-alibaba-common + camel-alibaba-oss + camel-alibaba-mns + + + diff --git a/components/pom.xml b/components/pom.xml index e5c3970408dcd..b976af089d74a 100644 --- a/components/pom.xml +++ b/components/pom.xml @@ -80,6 +80,7 @@ camel-activemq camel-activemq6 camel-ai + camel-alibaba camel-amqp camel-arangodb camel-as2 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 678ec0b56e157..aa25bfb794369 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 @@ -142,6 +142,10 @@ public static List getComponentPath(Path dir) { return Arrays.asList(dir.resolve("camel-vertx"), dir.resolve("camel-vertx-http"), dir.resolve("camel-vertx-websocket")); + case "camel-alibaba": + return Arrays.asList(dir.resolve("camel-alibaba-common"), + dir.resolve("camel-alibaba-oss"), + dir.resolve("camel-alibaba-mns")); case "camel-huawei": return Arrays.asList(dir.resolve("camel-huaweicloud-frs"), dir.resolve("camel-huaweicloud-dms"), From 84d416effd47c77139fefe453531f55781016281 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 10 Aug 2026 17:40:19 +0000 Subject: [PATCH 02/12] CAMEL-24373: Add camel-alibaba-mns component (MVP phase 1) Implement Alibaba Cloud Message Service (MNS) component with queue and topic support. Includes sendMessage, receiveMessage, deleteMessage, and publishMessage operations, ScheduledBatchPollingConsumer for queue polling, HealthCheckComponent integration, unit tests with Mockito/AssertJ, and component documentation. Co-authored-by: Omar Atie --- catalog/camel-allcomponents/pom.xml | 15 ++ .../camel-alibaba/camel-alibaba-mns/pom.xml | 77 ++++++ .../alibaba/mns/MNSComponentConfigurer.java | 75 ++++++ .../alibaba/mns/MNSEndpointConfigurer.java | 230 +++++++++++++++++ .../alibaba/mns/MNSEndpointUriFactory.java | 114 +++++++++ .../component/alibaba/mns/alibaba-mns.json | 79 ++++++ .../org/apache/camel/component.properties | 7 + .../org/apache/camel/component/alibaba-mns | 2 + .../camel/configurer/alibaba-mns-component | 2 + .../camel/configurer/alibaba-mns-endpoint | 2 + .../camel/urifactory/alibaba-mns-endpoint | 2 + .../src/main/docs/alibaba-mns-component.adoc | 147 +++++++++++ .../component/alibaba/mns/MNSComponent.java | 35 +++ .../component/alibaba/mns/MNSConsumer.java | 179 +++++++++++++ .../component/alibaba/mns/MNSEndpoint.java | 242 ++++++++++++++++++ .../component/alibaba/mns/MNSProducer.java | 126 +++++++++ .../camel/component/alibaba/mns/MNSUtils.java | 149 +++++++++++ .../alibaba/mns/constants/MNSHeaders.java | 55 ++++ .../alibaba/mns/constants/MNSOperations.java | 28 ++ .../alibaba/mns/constants/MNSProperties.java | 32 +++ .../mns/models/ClientConfigurations.java | 84 ++++++ .../alibaba/mns/PublishMessageTest.java | 86 +++++++ .../mns/ReceiveMessageConsumerTest.java | 90 +++++++ .../alibaba/mns/SendMessageTest.java | 87 +++++++ .../alibaba/mns/TestConfiguration.java | 57 +++++ .../mns/constants/MNSOperationsTest.java | 32 +++ .../src/test/resources/log4j2.properties | 29 +++ .../resources/testconfiguration.properties | 23 ++ parent/pom.xml | 15 ++ 29 files changed, 2101 insertions(+) create mode 100644 components/camel-alibaba/camel-alibaba-mns/pom.xml create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/generated/java/org/apache/camel/component/alibaba/mns/MNSComponentConfigurer.java create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/generated/java/org/apache/camel/component/alibaba/mns/MNSEndpointConfigurer.java create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/generated/java/org/apache/camel/component/alibaba/mns/MNSEndpointUriFactory.java create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/org/apache/camel/component/alibaba/mns/alibaba-mns.json create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/services/org/apache/camel/component.properties create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/services/org/apache/camel/component/alibaba-mns create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/services/org/apache/camel/configurer/alibaba-mns-component create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/services/org/apache/camel/configurer/alibaba-mns-endpoint create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/services/org/apache/camel/urifactory/alibaba-mns-endpoint create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/main/docs/alibaba-mns-component.adoc create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSComponent.java create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSConsumer.java create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSEndpoint.java create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSProducer.java create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSUtils.java create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/constants/MNSHeaders.java create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/constants/MNSOperations.java create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/constants/MNSProperties.java create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/models/ClientConfigurations.java create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/PublishMessageTest.java create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/ReceiveMessageConsumerTest.java create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/SendMessageTest.java create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/TestConfiguration.java create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/constants/MNSOperationsTest.java create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/test/resources/log4j2.properties create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/test/resources/testconfiguration.properties diff --git a/catalog/camel-allcomponents/pom.xml b/catalog/camel-allcomponents/pom.xml index fab4a83b9ab1f..4ae87f8003f74 100644 --- a/catalog/camel-allcomponents/pom.xml +++ b/catalog/camel-allcomponents/pom.xml @@ -72,6 +72,21 @@ camel-ai-tool ${project.version} + + org.apache.camel + camel-alibaba-common + ${project.version} + + + org.apache.camel + camel-alibaba-mns + ${project.version} + + + org.apache.camel + camel-alibaba-oss + ${project.version} + org.apache.camel camel-amqp diff --git a/components/camel-alibaba/camel-alibaba-mns/pom.xml b/components/camel-alibaba/camel-alibaba-mns/pom.xml new file mode 100644 index 0000000000000..db5851a68fd06 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/pom.xml @@ -0,0 +1,77 @@ + + + + + 4.0.0 + + + org.apache.camel + camel-alibaba-parent + 4.22.0-SNAPSHOT + + + + 4.22.0 + + + camel-alibaba-mns + jar + Camel :: Alibaba Cloud :: Message Service (MNS) + Camel Alibaba Cloud Message Service (MNS) component + + + + org.apache.camel + camel-support + + + + org.apache.camel + camel-alibaba-common + ${project.version} + + + + com.aliyun.mns + aliyun-sdk-mns + 2.0.0 + + + + org.apache.camel + camel-test-junit6 + test + + + + org.assertj + assertj-core + test + + + + org.mockito + mockito-core + ${mockito-version} + test + + + + diff --git a/components/camel-alibaba/camel-alibaba-mns/src/generated/java/org/apache/camel/component/alibaba/mns/MNSComponentConfigurer.java b/components/camel-alibaba/camel-alibaba-mns/src/generated/java/org/apache/camel/component/alibaba/mns/MNSComponentConfigurer.java new file mode 100644 index 0000000000000..05eb92427cc00 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/generated/java/org/apache/camel/component/alibaba/mns/MNSComponentConfigurer.java @@ -0,0 +1,75 @@ +/* Generated by camel build tools - do NOT edit this file! */ +package org.apache.camel.component.alibaba.mns; + +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 MNSComponentConfigurer extends PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter { + + @Override + public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) { + MNSComponent target = (MNSComponent) obj; + switch (ignoreCase ? name.toLowerCase() : name) { + case "autowiredenabled": + case "autowiredEnabled": target.setAutowiredEnabled(property(camelContext, boolean.class, value)); return true; + case "bridgeerrorhandler": + case "bridgeErrorHandler": target.setBridgeErrorHandler(property(camelContext, boolean.class, value)); return true; + case "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 "lazystartproducer": + case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true; + default: return false; + } + } + + @Override + public Class getOptionType(String name, boolean ignoreCase) { + switch (ignoreCase ? name.toLowerCase() : name) { + case "autowiredenabled": + case "autowiredEnabled": return boolean.class; + case "bridgeerrorhandler": + case "bridgeErrorHandler": return boolean.class; + case "healthcheckconsumerenabled": + case "healthCheckConsumerEnabled": return boolean.class; + case "healthcheckproducerenabled": + case "healthCheckProducerEnabled": return boolean.class; + case "lazystartproducer": + case "lazyStartProducer": return boolean.class; + default: return null; + } + } + + @Override + public Object getOptionValue(Object obj, String name, boolean ignoreCase) { + MNSComponent target = (MNSComponent) obj; + switch (ignoreCase ? name.toLowerCase() : name) { + case "autowiredenabled": + case "autowiredEnabled": return target.isAutowiredEnabled(); + case "bridgeerrorhandler": + case "bridgeErrorHandler": return target.isBridgeErrorHandler(); + case "healthcheckconsumerenabled": + case "healthCheckConsumerEnabled": return target.isHealthCheckConsumerEnabled(); + case "healthcheckproducerenabled": + case "healthCheckProducerEnabled": return target.isHealthCheckProducerEnabled(); + case "lazystartproducer": + case "lazyStartProducer": return target.isLazyStartProducer(); + default: return null; + } + } +} + diff --git a/components/camel-alibaba/camel-alibaba-mns/src/generated/java/org/apache/camel/component/alibaba/mns/MNSEndpointConfigurer.java b/components/camel-alibaba/camel-alibaba-mns/src/generated/java/org/apache/camel/component/alibaba/mns/MNSEndpointConfigurer.java new file mode 100644 index 0000000000000..6866443c6bdd0 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/generated/java/org/apache/camel/component/alibaba/mns/MNSEndpointConfigurer.java @@ -0,0 +1,230 @@ +/* Generated by camel build tools - do NOT edit this file! */ +package org.apache.camel.component.alibaba.mns; + +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 MNSEndpointConfigurer extends PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter { + + @Override + public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) { + MNSEndpoint target = (MNSEndpoint) obj; + switch (ignoreCase ? name.toLowerCase() : name) { + case "accesskey": + case "accessKey": target.setAccessKey(property(camelContext, java.lang.String.class, value)); return true; + case "accountendpoint": + case "accountEndpoint": target.setAccountEndpoint(property(camelContext, java.lang.String.class, value)); return true; + case "backofferrorthreshold": + case "backoffErrorThreshold": target.setBackoffErrorThreshold(property(camelContext, int.class, value)); return true; + case "backoffidlethreshold": + case "backoffIdleThreshold": target.setBackoffIdleThreshold(property(camelContext, int.class, value)); return true; + case "backoffmultiplier": + case "backoffMultiplier": target.setBackoffMultiplier(property(camelContext, int.class, value)); return true; + case "bridgeerrorhandler": + case "bridgeErrorHandler": target.setBridgeErrorHandler(property(camelContext, boolean.class, value)); return true; + case "delay": target.setDelay(property(camelContext, long.class, value)); return true; + case "deleteafterread": + case "deleteAfterRead": target.setDeleteAfterRead(property(camelContext, boolean.class, value)); return true; + case "exceptionhandler": + case "exceptionHandler": target.setExceptionHandler(property(camelContext, org.apache.camel.spi.ExceptionHandler.class, value)); return true; + case "exchangepattern": + case "exchangePattern": target.setExchangePattern(property(camelContext, org.apache.camel.ExchangePattern.class, value)); return true; + case "greedy": target.setGreedy(property(camelContext, boolean.class, value)); return true; + case "initialdelay": + case "initialDelay": target.setInitialDelay(property(camelContext, long.class, value)); return true; + case "lazystartproducer": + case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true; + case "maxmessagesperpoll": + case "maxMessagesPerPoll": target.setMaxMessagesPerPoll(property(camelContext, int.class, value)); return true; + case "mnsclient": + case "mnsClient": target.setMnsClient(property(camelContext, com.aliyun.mns.client.MNSClient.class, value)); return true; + case "operation": target.setOperation(property(camelContext, java.lang.String.class, value)); return true; + case "pollstrategy": + case "pollStrategy": target.setPollStrategy(property(camelContext, org.apache.camel.spi.PollingConsumerPollStrategy.class, value)); return true; + case "region": target.setRegion(property(camelContext, java.lang.String.class, value)); return true; + case "repeatcount": + case "repeatCount": target.setRepeatCount(property(camelContext, long.class, value)); return true; + case "runlogginglevel": + case "runLoggingLevel": target.setRunLoggingLevel(property(camelContext, org.apache.camel.LoggingLevel.class, value)); return true; + case "scheduledexecutorservice": + case "scheduledExecutorService": target.setScheduledExecutorService(property(camelContext, java.util.concurrent.ScheduledExecutorService.class, value)); return true; + case "scheduler": target.setScheduler(property(camelContext, java.lang.Object.class, value)); return true; + case "schedulerproperties": + case "schedulerProperties": target.setSchedulerProperties(property(camelContext, java.util.Map.class, value)); return true; + case "secretkey": + case "secretKey": target.setSecretKey(property(camelContext, java.lang.String.class, value)); return true; + case "sendemptymessagewhenidle": + case "sendEmptyMessageWhenIdle": target.setSendEmptyMessageWhenIdle(property(camelContext, boolean.class, value)); return true; + case "servicekeys": + case "serviceKeys": target.setServiceKeys(property(camelContext, org.apache.camel.component.alibaba.common.models.ServiceKeys.class, value)); return true; + case "startscheduler": + case "startScheduler": target.setStartScheduler(property(camelContext, boolean.class, value)); return true; + case "timeunit": + case "timeUnit": target.setTimeUnit(property(camelContext, java.util.concurrent.TimeUnit.class, value)); return true; + case "topicname": + case "topicName": target.setTopicName(property(camelContext, java.lang.String.class, value)); return true; + case "usefixeddelay": + case "useFixedDelay": target.setUseFixedDelay(property(camelContext, boolean.class, value)); return true; + case "waitseconds": + case "waitSeconds": target.setWaitSeconds(property(camelContext, int.class, value)); return true; + default: return false; + } + } + + @Override + public String[] getAutowiredNames() { + return new String[]{"mnsClient"}; + } + + @Override + public Class getOptionType(String name, boolean ignoreCase) { + switch (ignoreCase ? name.toLowerCase() : name) { + case "accesskey": + case "accessKey": return java.lang.String.class; + case "accountendpoint": + case "accountEndpoint": return java.lang.String.class; + case "backofferrorthreshold": + case "backoffErrorThreshold": return int.class; + case "backoffidlethreshold": + case "backoffIdleThreshold": return int.class; + case "backoffmultiplier": + case "backoffMultiplier": return int.class; + case "bridgeerrorhandler": + case "bridgeErrorHandler": return boolean.class; + case "delay": return long.class; + case "deleteafterread": + case "deleteAfterRead": return boolean.class; + case "exceptionhandler": + case "exceptionHandler": return org.apache.camel.spi.ExceptionHandler.class; + case "exchangepattern": + case "exchangePattern": return org.apache.camel.ExchangePattern.class; + case "greedy": return boolean.class; + case "initialdelay": + case "initialDelay": return long.class; + case "lazystartproducer": + case "lazyStartProducer": return boolean.class; + case "maxmessagesperpoll": + case "maxMessagesPerPoll": return int.class; + case "mnsclient": + case "mnsClient": return com.aliyun.mns.client.MNSClient.class; + case "operation": return java.lang.String.class; + case "pollstrategy": + case "pollStrategy": return org.apache.camel.spi.PollingConsumerPollStrategy.class; + case "region": return java.lang.String.class; + case "repeatcount": + case "repeatCount": return long.class; + case "runlogginglevel": + case "runLoggingLevel": return org.apache.camel.LoggingLevel.class; + case "scheduledexecutorservice": + case "scheduledExecutorService": return java.util.concurrent.ScheduledExecutorService.class; + case "scheduler": return java.lang.Object.class; + case "schedulerproperties": + case "schedulerProperties": return java.util.Map.class; + case "secretkey": + case "secretKey": return java.lang.String.class; + case "sendemptymessagewhenidle": + case "sendEmptyMessageWhenIdle": return boolean.class; + case "servicekeys": + case "serviceKeys": return org.apache.camel.component.alibaba.common.models.ServiceKeys.class; + case "startscheduler": + case "startScheduler": return boolean.class; + case "timeunit": + case "timeUnit": return java.util.concurrent.TimeUnit.class; + case "topicname": + case "topicName": return java.lang.String.class; + case "usefixeddelay": + case "useFixedDelay": return boolean.class; + case "waitseconds": + case "waitSeconds": return int.class; + default: return null; + } + } + + @Override + public Object getOptionValue(Object obj, String name, boolean ignoreCase) { + MNSEndpoint target = (MNSEndpoint) obj; + switch (ignoreCase ? name.toLowerCase() : name) { + case "accesskey": + case "accessKey": return target.getAccessKey(); + case "accountendpoint": + case "accountEndpoint": return target.getAccountEndpoint(); + case "backofferrorthreshold": + case "backoffErrorThreshold": return target.getBackoffErrorThreshold(); + case "backoffidlethreshold": + case "backoffIdleThreshold": return target.getBackoffIdleThreshold(); + case "backoffmultiplier": + case "backoffMultiplier": return target.getBackoffMultiplier(); + case "bridgeerrorhandler": + case "bridgeErrorHandler": return target.isBridgeErrorHandler(); + case "delay": return target.getDelay(); + case "deleteafterread": + case "deleteAfterRead": return target.isDeleteAfterRead(); + case "exceptionhandler": + case "exceptionHandler": return target.getExceptionHandler(); + case "exchangepattern": + case "exchangePattern": return target.getExchangePattern(); + case "greedy": return target.isGreedy(); + case "initialdelay": + case "initialDelay": return target.getInitialDelay(); + case "lazystartproducer": + case "lazyStartProducer": return target.isLazyStartProducer(); + case "maxmessagesperpoll": + case "maxMessagesPerPoll": return target.getMaxMessagesPerPoll(); + case "mnsclient": + case "mnsClient": return target.getMnsClient(); + case "operation": return target.getOperation(); + case "pollstrategy": + case "pollStrategy": return target.getPollStrategy(); + case "region": return target.getRegion(); + case "repeatcount": + case "repeatCount": return target.getRepeatCount(); + case "runlogginglevel": + case "runLoggingLevel": return target.getRunLoggingLevel(); + case "scheduledexecutorservice": + case "scheduledExecutorService": return target.getScheduledExecutorService(); + case "scheduler": return target.getScheduler(); + case "schedulerproperties": + case "schedulerProperties": return target.getSchedulerProperties(); + case "secretkey": + case "secretKey": return target.getSecretKey(); + case "sendemptymessagewhenidle": + case "sendEmptyMessageWhenIdle": return target.isSendEmptyMessageWhenIdle(); + case "servicekeys": + case "serviceKeys": return target.getServiceKeys(); + case "startscheduler": + case "startScheduler": return target.isStartScheduler(); + case "timeunit": + case "timeUnit": return target.getTimeUnit(); + case "topicname": + case "topicName": return target.getTopicName(); + case "usefixeddelay": + case "useFixedDelay": return target.isUseFixedDelay(); + case "waitseconds": + case "waitSeconds": return target.getWaitSeconds(); + default: return null; + } + } + + @Override + public Object getCollectionValueType(Object target, String name, boolean ignoreCase) { + switch (ignoreCase ? name.toLowerCase() : name) { + case "schedulerproperties": + case "schedulerProperties": return java.lang.Object.class; + default: return null; + } + } +} + diff --git a/components/camel-alibaba/camel-alibaba-mns/src/generated/java/org/apache/camel/component/alibaba/mns/MNSEndpointUriFactory.java b/components/camel-alibaba/camel-alibaba-mns/src/generated/java/org/apache/camel/component/alibaba/mns/MNSEndpointUriFactory.java new file mode 100644 index 0000000000000..be7fced35e33b --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/generated/java/org/apache/camel/component/alibaba/mns/MNSEndpointUriFactory.java @@ -0,0 +1,114 @@ +/* Generated by camel build tools - do NOT edit this file! */ +package org.apache.camel.component.alibaba.mns; + +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 MNSEndpointUriFactory extends org.apache.camel.support.component.EndpointUriFactorySupport implements EndpointUriFactory { + + private static final String BASE = ":queueName"; + + private static final Set PROPERTY_NAMES; + private static final Set SECRET_PROPERTY_NAMES; + private static final Set ENDPOINT_IDENTITY_PROPERTY_NAMES; + private static final Map MULTI_VALUE_PREFIXES; + static { + Set props = new HashSet<>(32); + props.add("accessKey"); + props.add("accountEndpoint"); + props.add("backoffErrorThreshold"); + props.add("backoffIdleThreshold"); + props.add("backoffMultiplier"); + props.add("bridgeErrorHandler"); + props.add("delay"); + props.add("deleteAfterRead"); + props.add("exceptionHandler"); + props.add("exchangePattern"); + props.add("greedy"); + props.add("initialDelay"); + props.add("lazyStartProducer"); + props.add("maxMessagesPerPoll"); + props.add("mnsClient"); + props.add("operation"); + props.add("pollStrategy"); + props.add("queueName"); + props.add("region"); + props.add("repeatCount"); + props.add("runLoggingLevel"); + props.add("scheduledExecutorService"); + props.add("scheduler"); + props.add("schedulerProperties"); + props.add("secretKey"); + props.add("sendEmptyMessageWhenIdle"); + props.add("serviceKeys"); + props.add("startScheduler"); + props.add("timeUnit"); + props.add("topicName"); + props.add("useFixedDelay"); + props.add("waitSeconds"); + PROPERTY_NAMES = Collections.unmodifiableSet(props); + Set secretProps = new HashSet<>(3); + secretProps.add("accessKey"); + secretProps.add("secretKey"); + secretProps.add("serviceKeys"); + SECRET_PROPERTY_NAMES = Collections.unmodifiableSet(secretProps); + ENDPOINT_IDENTITY_PROPERTY_NAMES = Collections.emptySet(); + Map prefixes = new HashMap<>(1); + prefixes.put("schedulerProperties", "scheduler."); + MULTI_VALUE_PREFIXES = Collections.unmodifiableMap(prefixes); + } + + @Override + public boolean isEnabled(String scheme) { + return "alibaba-mns".equals(scheme); + } + + @Override + public String buildUri(String scheme, Map properties, boolean encode) throws URISyntaxException { + String syntax = scheme + BASE; + String uri = syntax; + + Map copy = new HashMap<>(properties); + + uri = buildPathParameter(syntax, uri, "queueName", null, true, copy); + uri = buildQueryParameters(uri, copy, encode); + return uri; + } + + @Override + public Set propertyNames() { + return PROPERTY_NAMES; + } + + @Override + public Set secretPropertyNames() { + return SECRET_PROPERTY_NAMES; + } + + @Override + public Set endpointIdentityPropertyNames() { + return ENDPOINT_IDENTITY_PROPERTY_NAMES; + } + + @Override + public Map multiValuePrefixes() { + return MULTI_VALUE_PREFIXES; + } + + @Override + public boolean isLenientProperties() { + return false; + } +} + diff --git a/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/org/apache/camel/component/alibaba/mns/alibaba-mns.json b/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/org/apache/camel/component/alibaba/mns/alibaba-mns.json new file mode 100644 index 0000000000000..d78d4c416999c --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/org/apache/camel/component/alibaba/mns/alibaba-mns.json @@ -0,0 +1,79 @@ +{ + "component": { + "kind": "component", + "name": "alibaba-mns", + "title": "Alibaba Message Service (MNS)", + "description": "Send and receive messages to\/from Alibaba Cloud Message Service (MNS).", + "deprecated": false, + "firstVersion": "4.22.0", + "label": "cloud,messaging", + "javaType": "org.apache.camel.component.alibaba.mns.MNSComponent", + "supportLevel": "Preview", + "groupId": "org.apache.camel", + "artifactId": "camel-alibaba-mns", + "version": "4.22.0-SNAPSHOT", + "scheme": "alibaba-mns", + "extendsScheme": "", + "syntax": "alibaba-mns:queueName", + "async": false, + "api": false, + "consumerOnly": false, + "producerOnly": false, + "lenientProperties": false, + "browsable": false, + "remote": true + }, + "componentProperties": { + "bridgeErrorHandler": { "index": 0, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, + "lazyStartProducer": { "index": 1, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." }, + "autowiredEnabled": { "index": 2, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching type, which then gets configured on the component. This can be used for automatic configuring JDBC data sources, JMS connection factories, AWS Clients, etc." }, + "healthCheckConsumerEnabled": { "index": 3, "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": 4, "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 producer checks globally by setting camel.health.producersEnabled=true." } + }, + "headers": { + "CamelAlibabaMnsMessageId": { "index": 0, "kind": "header", "displayName": "", "group": "common", "label": "common", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The MNS message id", "constantName": "org.apache.camel.component.alibaba.mns.constants.MNSHeaders#MESSAGE_ID" }, + "CamelAlibabaMnsReceiptHandle": { "index": 1, "kind": "header", "displayName": "", "group": "common", "label": "common", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The MNS receipt handle", "constantName": "org.apache.camel.component.alibaba.mns.constants.MNSHeaders#RECEIPT_HANDLE" }, + "CamelAlibabaMnsMessageBodyMd5": { "index": 2, "kind": "header", "displayName": "", "group": "common", "label": "common", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The MD5 digest of the message body", "constantName": "org.apache.camel.component.alibaba.mns.constants.MNSHeaders#MESSAGE_BODY_MD5" }, + "CamelAlibabaMnsDelaySeconds": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Delay in seconds before the message becomes visible", "constantName": "org.apache.camel.component.alibaba.mns.constants.MNSHeaders#DELAY_SECONDS" }, + "CamelAlibabaMnsPriority": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Message priority", "constantName": "org.apache.camel.component.alibaba.mns.constants.MNSHeaders#PRIORITY" }, + "CamelAlibabaMnsMessageTag": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Message tag for topic publish operations", "constantName": "org.apache.camel.component.alibaba.mns.constants.MNSHeaders#MESSAGE_TAG" }, + "CamelAlibabaMnsDequeueCount": { "index": 6, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Number of times the message has been dequeued", "constantName": "org.apache.camel.component.alibaba.mns.constants.MNSHeaders#DEQUEUE_COUNT" }, + "CamelAlibabaMnsEnqueueTime": { "index": 7, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "java.util.Date", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Time when the message was enqueued", "constantName": "org.apache.camel.component.alibaba.mns.constants.MNSHeaders#ENQUEUE_TIME" }, + "CamelAlibabaMnsNextVisibleTime": { "index": 8, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "java.util.Date", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Next time the message becomes visible", "constantName": "org.apache.camel.component.alibaba.mns.constants.MNSHeaders#NEXT_VISIBLE_TIME" }, + "CamelAlibabaMnsFirstDequeueTime": { "index": 9, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "java.util.Date", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Time when the message was first dequeued", "constantName": "org.apache.camel.component.alibaba.mns.constants.MNSHeaders#FIRST_DEQUEUE_TIME" } + }, + "properties": { + "queueName": { "index": 0, "kind": "path", "displayName": "Queue Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Queue name, or topic name when using the topic URI syntax" }, + "accessKey": { "index": 1, "kind": "parameter", "displayName": "Access Key", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "security": "secret", "description": "Access key for the cloud user" }, + "accountEndpoint": { "index": 2, "kind": "parameter", "displayName": "Account Endpoint", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "MNS account endpoint, for example https:\/\/123456.mns.cn-hangzhou.aliyuncs.com" }, + "operation": { "index": 3, "kind": "parameter", "displayName": "Operation", "group": "common", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "sendMessage", "receiveMessage", "deleteMessage", "publishMessage" ], "deprecated": false, "autowired": false, "secret": false, "description": "Operation to perform" }, + "region": { "index": 4, "kind": "parameter", "displayName": "Region", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Alibaba Cloud region" }, + "secretKey": { "index": 5, "kind": "parameter", "displayName": "Secret Key", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "security": "secret", "description": "Secret key for the cloud user" }, + "serviceKeys": { "index": 6, "kind": "parameter", "displayName": "Service Keys", "group": "common", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.alibaba.common.models.ServiceKeys", "deprecated": false, "autowired": false, "secret": true, "security": "secret", "description": "Configuration object for cloud service authentication" }, + "topicName": { "index": 7, "kind": "parameter", "displayName": "Topic Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Topic name for publishMessage operations" }, + "waitSeconds": { "index": 8, "kind": "parameter", "displayName": "Wait Seconds", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "Long polling wait time in seconds when receiving messages" }, + "deleteAfterRead": { "index": 9, "kind": "parameter", "displayName": "Delete After Read", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Delete message from the queue after it has been processed" }, + "maxMessagesPerPoll": { "index": 10, "kind": "parameter", "displayName": "Max Messages Per Poll", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Maximum number of messages to receive per poll" }, + "sendEmptyMessageWhenIdle": { "index": 11, "kind": "parameter", "displayName": "Send Empty Message When Idle", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead." }, + "bridgeErrorHandler": { "index": 12, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, + "exceptionHandler": { "index": 13, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, + "exchangePattern": { "index": 14, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." }, + "pollStrategy": { "index": 15, "kind": "parameter", "displayName": "Poll Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.PollingConsumerPollStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "A pluggable org.apache.camel.PollingConsumerPollingStrategy allowing you to provide your custom implementation to control error handling usually occurred during the poll operation before an Exchange have been created and being routed in Camel." }, + "lazyStartProducer": { "index": 16, "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 producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." }, + "mnsClient": { "index": 17, "kind": "parameter", "displayName": "MNS Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "com.aliyun.mns.client.MNSClient", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "description": "Autowire an existing MNSClient instance" }, + "backoffErrorThreshold": { "index": 18, "kind": "parameter", "displayName": "Backoff Error Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent error polls (failed due some error) that should happen before the backoffMultipler should kick-in." }, + "backoffIdleThreshold": { "index": 19, "kind": "parameter", "displayName": "Backoff Idle Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent idle polls that should happen before the backoffMultipler should kick-in." }, + "backoffMultiplier": { "index": 20, "kind": "parameter", "displayName": "Backoff Multiplier", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "To let the scheduled polling consumer backoff if there has been a number of subsequent idles\/errors in a row. The multiplier is then the number of polls that will be skipped before the next actual attempt is happening again. When this option is in use then backoffIdleThreshold and\/or backoffErrorThreshold must also be configured." }, + "delay": { "index": 21, "kind": "parameter", "displayName": "Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 500, "description": "Milliseconds before the next poll." }, + "greedy": { "index": 22, "kind": "parameter", "displayName": "Greedy", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If greedy is enabled, then the ScheduledPollConsumer will run immediately again, if the previous run polled 1 or more messages." }, + "initialDelay": { "index": 23, "kind": "parameter", "displayName": "Initial Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "Milliseconds before the first poll starts." }, + "repeatCount": { "index": 24, "kind": "parameter", "displayName": "Repeat Count", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "Specifies a maximum limit of number of fires. So if you set it to 1, the scheduler will only fire once. If you set it to 5, it will only fire five times. A value of zero or negative means fire forever." }, + "runLoggingLevel": { "index": 25, "kind": "parameter", "displayName": "Run Logging Level", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "enum", "javaType": "org.apache.camel.LoggingLevel", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "TRACE", "description": "The consumer logs a start\/complete log line when it polls. This option allows you to configure the logging level for that." }, + "scheduledExecutorService": { "index": 26, "kind": "parameter", "displayName": "Scheduled Executor Service", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.concurrent.ScheduledExecutorService", "deprecated": false, "autowired": false, "secret": false, "description": "Allows for configuring a custom\/shared thread pool to use for the consumer. By default each consumer has its own single threaded thread pool." }, + "scheduler": { "index": 27, "kind": "parameter", "displayName": "Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.lang.Object", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "none", "description": "To use a cron scheduler from either camel-spring or camel-quartz component. Use value spring or quartz for built in scheduler" }, + "schedulerProperties": { "index": 28, "kind": "parameter", "displayName": "Scheduler Properties", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.Map", "prefix": "scheduler.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "To configure additional properties when using a custom scheduler or any of the Quartz, Spring based scheduler. This is a multi-value option with prefix: scheduler." }, + "startScheduler": { "index": 29, "kind": "parameter", "displayName": "Start Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether the scheduler should be auto started." }, + "timeUnit": { "index": 30, "kind": "parameter", "displayName": "Time Unit", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "enum", "javaType": "java.util.concurrent.TimeUnit", "enum": [ "NANOSECONDS", "MICROSECONDS", "MILLISECONDS", "SECONDS", "MINUTES", "HOURS", "DAYS" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "MILLISECONDS", "description": "Time unit for initialDelay and delay options." }, + "useFixedDelay": { "index": 31, "kind": "parameter", "displayName": "Use Fixed Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in JDK for details." } + } +} diff --git a/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/services/org/apache/camel/component.properties b/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/services/org/apache/camel/component.properties new file mode 100644 index 0000000000000..d0fa7a95e870b --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/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=alibaba-mns +groupId=org.apache.camel +artifactId=camel-alibaba-mns +version=4.22.0-SNAPSHOT +projectName=Camel :: Alibaba Cloud :: Message Service (MNS) +projectDescription=Camel Alibaba Cloud Message Service (MNS) component diff --git a/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/services/org/apache/camel/component/alibaba-mns b/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/services/org/apache/camel/component/alibaba-mns new file mode 100644 index 0000000000000..5d2962600c879 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/services/org/apache/camel/component/alibaba-mns @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.component.alibaba.mns.MNSComponent diff --git a/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/services/org/apache/camel/configurer/alibaba-mns-component b/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/services/org/apache/camel/configurer/alibaba-mns-component new file mode 100644 index 0000000000000..70678be551413 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/services/org/apache/camel/configurer/alibaba-mns-component @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.component.alibaba.mns.MNSComponentConfigurer diff --git a/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/services/org/apache/camel/configurer/alibaba-mns-endpoint b/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/services/org/apache/camel/configurer/alibaba-mns-endpoint new file mode 100644 index 0000000000000..de659ae4e297f --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/services/org/apache/camel/configurer/alibaba-mns-endpoint @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.component.alibaba.mns.MNSEndpointConfigurer diff --git a/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/services/org/apache/camel/urifactory/alibaba-mns-endpoint b/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/services/org/apache/camel/urifactory/alibaba-mns-endpoint new file mode 100644 index 0000000000000..0c059ae71060c --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/services/org/apache/camel/urifactory/alibaba-mns-endpoint @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.component.alibaba.mns.MNSEndpointUriFactory diff --git a/components/camel-alibaba/camel-alibaba-mns/src/main/docs/alibaba-mns-component.adoc b/components/camel-alibaba/camel-alibaba-mns/src/main/docs/alibaba-mns-component.adoc new file mode 100644 index 0000000000000..1567e661cad22 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/main/docs/alibaba-mns-component.adoc @@ -0,0 +1,147 @@ += Alibaba Message Service (MNS) Component +:doctitle: Alibaba Message Service (MNS) +:shortname: alibaba-mns +:artifactid: camel-alibaba-mns +:description: Send and receive messages to/from Alibaba Cloud Message Service (MNS). +:since: 4.22 +:supportlevel: Preview +:tabs-sync-option: +:component-header: Both producer and consumer are supported +//Manually maintained attributes +:group: Alibaba Cloud + +*Since Camel {since}* + +*{component-header}* + +The Alibaba Cloud Message Service (MNS) component allows you to integrate with +https://www.alibabacloud.com/product/mns[Alibaba Cloud MNS] for queue and topic messaging. + +Maven users will need to add the following dependency to their `pom.xml` +for this component: + +[source,xml] +---- + + org.apache.camel + camel-alibaba-mns + x.x.x + + +---- + +== URI format + +Queue endpoints: + +[source] +---- +alibaba-mns:queueName[?options] +---- + +Topic endpoints: + +[source] +---- +alibaba-mns:topic:topicName[?options] +---- + +// component options: START +include::partial$component-configure-options.adoc[] +include::partial$component-endpoint-options.adoc[] +include::partial$component-endpoint-headers.adoc[] +// component options: END + +== Usage + +=== Operations + +The component supports the following operations: + +* `sendMessage` - send a message to a queue (producer) +* `receiveMessage` - receive messages from a queue (consumer) +* `deleteMessage` - delete a message from a queue using its receipt handle (producer) +* `publishMessage` - publish a message to a topic (producer) + +=== Queue producer example + +[source,java] +---- +from("direct:start") + .setBody(constant("Hello MNS")) + .to("alibaba-mns:myQueue?operation=sendMessage®ion=cn-hangzhou&accountEndpoint=https://123456.mns.cn-hangzhou.aliyuncs.com&accessKey=RAW(accessKey)&secretKey=RAW(secretKey)"); +---- + +=== Topic producer example + +[source,java] +---- +from("direct:start") + .setBody(constant("Hello Topic")) + .to("alibaba-mns:topic:myTopic?operation=publishMessage®ion=cn-hangzhou&accountEndpoint=https://123456.mns.cn-hangzhou.aliyuncs.com&accessKey=RAW(accessKey)&secretKey=RAW(secretKey)"); +---- + +=== Queue consumer example + +[source,java] +---- +from("alibaba-mns:myQueue?region=cn-hangzhou&accountEndpoint=https://123456.mns.cn-hangzhou.aliyuncs.com&accessKey=RAW(accessKey)&secretKey=RAW(secretKey)&deleteAfterRead=true") + .to("bean:processMessage"); +---- + +=== Exchange properties evaluated by the producer + +[width="100%",cols="10%,10%,80%",options="header",] +|======================================================================= +|Property |Type |Description + +|`CamelAlibabaMnsOperation` |`String` |Operation to perform + +|`CamelAlibabaMnsQueueName` |`String` |Queue name override + +|`CamelAlibabaMnsTopicName` |`String` |Topic name for publish operations + +|`CamelAlibabaMnsReceiptHandle` |`String` |Receipt handle for delete operations + +|======================================================================= + +=== Exchange properties set by the producer + +[width="100%",cols="10%,10%,80%",options="header",] +|======================================================================= +|Property |Type |Description + +|`CamelAlibabaMnsMessageId` |`String` |Message id returned by MNS + +|`CamelAlibabaMnsRequestId` |`String` |Request id returned by MNS + +|`CamelAlibabaMnsMessageBodyMd5` |`String` |MD5 digest of the message body + +|======================================================================= + +== Spring Boot auto-configuration + +When using `alibaba-mns` with Spring Boot, add the following dependency: + +[source,xml] +---- + + org.apache.camel.springboot + camel-alibaba-mns-starter + x.x.x + + +---- + +The component supports 0 options, which are listed below. + +include::partial$starter-configure-options.adoc[] + +== Spring Boot Auto-Configuration + +When using Spring Boot, the component is auto-configured. Refer to the +xref:manual::spring-boot.adoc[Spring Boot documentation] for more details. + +== Examples + +For more examples, see the unit tests in the `camel-alibaba-mns` module. diff --git a/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSComponent.java b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSComponent.java new file mode 100644 index 0000000000000..6c6e5c439ada6 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSComponent.java @@ -0,0 +1,35 @@ +/* + * 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.alibaba.mns; + +import java.util.Map; + +import org.apache.camel.Endpoint; +import org.apache.camel.spi.annotations.Component; +import org.apache.camel.support.HealthCheckComponent; + +@Component("alibaba-mns") +public class MNSComponent extends HealthCheckComponent { + + @Override + protected Endpoint createEndpoint(String uri, String remaining, Map parameters) throws Exception { + MNSEndpoint endpoint = new MNSEndpoint(uri, this); + MNSUtils.configurePath(remaining, endpoint); + setProperties(endpoint, parameters); + return endpoint; + } +} diff --git a/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSConsumer.java b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSConsumer.java new file mode 100644 index 0000000000000..d206920079636 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSConsumer.java @@ -0,0 +1,179 @@ +/* + * 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.alibaba.mns; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +import com.aliyun.mns.client.CloudQueue; +import com.aliyun.mns.model.Message; +import org.apache.camel.AsyncCallback; +import org.apache.camel.Exchange; +import org.apache.camel.ExchangePropertyKey; +import org.apache.camel.Processor; +import org.apache.camel.component.alibaba.mns.constants.MNSHeaders; +import org.apache.camel.spi.Synchronization; +import org.apache.camel.support.ScheduledBatchPollingConsumer; +import org.apache.camel.util.CastUtils; +import org.apache.camel.util.ObjectHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MNSConsumer extends ScheduledBatchPollingConsumer { + + private static final Logger LOG = LoggerFactory.getLogger(MNSConsumer.class); + + public MNSConsumer(MNSEndpoint endpoint, Processor processor) { + super(endpoint, processor); + } + + @Override + protected int poll() throws Exception { + shutdownRunningTask = null; + pendingExchanges = 0; + + MNSEndpoint endpoint = getEndpoint(); + endpoint.initClient(); + + CloudQueue queue = endpoint.getMnsClient().getQueueRef(endpoint.getQueueName()); + List messages = receiveMessages(queue, endpoint.getMaxMessagesPerPoll(), endpoint.getWaitSeconds()); + + forceConsumerAsReady(); + + if (messages.isEmpty()) { + return 0; + } + + Queue exchanges = createExchanges(messages); + return processBatch(CastUtils.cast(exchanges)); + } + + private List receiveMessages(CloudQueue queue, int maxMessagesPerPoll, int waitSeconds) throws Exception { + int maxMessages = Math.max(1, maxMessagesPerPoll); + List messages = new ArrayList<>(); + + if (maxMessages == 1) { + Message message = waitSeconds > 0 ? queue.popMessage(waitSeconds) : queue.popMessage(); + if (message != null) { + messages.add(message); + } + return messages; + } + + List batch = waitSeconds > 0 + ? queue.batchPopMessage(maxMessages, waitSeconds) + : queue.batchPopMessage(maxMessages); + if (batch != null) { + messages.addAll(batch); + } + return messages; + } + + protected Queue createExchanges(List messages) { + Queue answer = new LinkedList<>(); + for (Message message : messages) { + if (ObjectHelper.isNotEmpty(message)) { + answer.add(createExchange(message)); + } + } + return answer; + } + + private Exchange createExchange(Message message) { + Exchange exchange = createExchange(true); + org.apache.camel.Message camelMessage = exchange.getIn(); + camelMessage.setBody(message.getMessageBody()); + camelMessage.setHeader(MNSHeaders.MESSAGE_ID, message.getMessageId()); + camelMessage.setHeader(MNSHeaders.RECEIPT_HANDLE, message.getReceiptHandle()); + camelMessage.setHeader(MNSHeaders.MESSAGE_BODY_MD5, message.getMessageBodyMD5()); + camelMessage.setHeader(MNSHeaders.DEQUEUE_COUNT, message.getDequeueCount()); + camelMessage.setHeader(MNSHeaders.ENQUEUE_TIME, message.getEnqueueTime()); + camelMessage.setHeader(MNSHeaders.NEXT_VISIBLE_TIME, message.getNextVisibleTime()); + camelMessage.setHeader(MNSHeaders.FIRST_DEQUEUE_TIME, message.getFirstDequeueTime()); + camelMessage.setHeader(MNSHeaders.PRIORITY, message.getPriority()); + return exchange; + } + + @Override + public int processBatch(Queue exchanges) throws Exception { + int total = exchanges.size(); + + for (int index = 0; index < total && isBatchAllowed(); index++) { + final Exchange exchange = ObjectHelper.cast(Exchange.class, exchanges.poll()); + exchange.setProperty(ExchangePropertyKey.BATCH_INDEX, index); + exchange.setProperty(ExchangePropertyKey.BATCH_SIZE, total); + exchange.setProperty(ExchangePropertyKey.BATCH_COMPLETE, index == total - 1); + + pendingExchanges = total - index - 1; + + exchange.getExchangeExtension().addOnCompletion(new Synchronization() { + @Override + public void onComplete(Exchange exchange) { + processCommit(exchange); + } + + @Override + public void onFailure(Exchange exchange) { + processRollback(exchange); + } + + @Override + public String toString() { + return "MNSConsumerOnCompletion"; + } + }); + + AsyncCallback callback = defaultConsumerCallback(exchange, true); + getAsyncProcessor().process(exchange, callback); + } + + return total; + } + + protected void processCommit(Exchange exchange) { + if (!getEndpoint().isDeleteAfterRead()) { + return; + } + try { + String receiptHandle = exchange.getIn().getHeader(MNSHeaders.RECEIPT_HANDLE, String.class); + if (ObjectHelper.isEmpty(receiptHandle)) { + return; + } + CloudQueue queue = getEndpoint().getMnsClient().getQueueRef(getEndpoint().getQueueName()); + queue.deleteMessage(receiptHandle); + } catch (Exception e) { + getExceptionHandler().handleException("Error occurred during deleting MNS message. This exception is ignored.", + exchange, e); + } + } + + protected void processRollback(Exchange exchange) { + Exception cause = exchange.getException(); + if (ObjectHelper.isNotEmpty(cause)) { + getExceptionHandler().handleException( + "Error during processing MNS exchange. Will attempt to process the message on next poll.", exchange, + cause); + } + } + + @Override + public MNSEndpoint getEndpoint() { + return (MNSEndpoint) super.getEndpoint(); + } +} diff --git a/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSEndpoint.java b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSEndpoint.java new file mode 100644 index 0000000000000..107956840d9e3 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSEndpoint.java @@ -0,0 +1,242 @@ +/* + * 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.alibaba.mns; + +import com.aliyun.mns.client.MNSClient; +import org.apache.camel.Category; +import org.apache.camel.Consumer; +import org.apache.camel.Processor; +import org.apache.camel.Producer; +import org.apache.camel.component.alibaba.common.models.ServiceKeys; +import org.apache.camel.component.alibaba.mns.constants.MNSHeaders; +import org.apache.camel.component.alibaba.mns.constants.MNSOperations; +import org.apache.camel.spi.Metadata; +import org.apache.camel.spi.UriEndpoint; +import org.apache.camel.spi.UriParam; +import org.apache.camel.spi.UriPath; +import org.apache.camel.support.ScheduledPollEndpoint; + +/** + * Send and receive messages to/from Alibaba Cloud Message Service (MNS). + */ +@UriEndpoint(firstVersion = "4.22.0", scheme = "alibaba-mns", title = "Alibaba Message Service (MNS)", + syntax = "alibaba-mns:queueName", category = { Category.CLOUD, Category.MESSAGING }, + headersClass = MNSHeaders.class) +public class MNSEndpoint extends ScheduledPollEndpoint { + + @UriPath(description = "Queue name, or topic name when using the topic URI syntax", displayName = "Queue Name") + @Metadata(required = true) + private String queueName; + + @UriParam(description = "Operation to perform", displayName = "Operation", + enums = "sendMessage,receiveMessage,deleteMessage,publishMessage") + private String operation; + + @UriParam(description = "Alibaba Cloud region", displayName = "Region") + @Metadata(required = true) + private String region; + + @UriParam(description = "MNS account endpoint, for example https://123456.mns.cn-hangzhou.aliyuncs.com", + displayName = "Account Endpoint") + @Metadata(required = true) + private String accountEndpoint; + + @UriParam(description = "Access key for the cloud user", displayName = "Access Key", secret = true) + private String accessKey; + + @UriParam(description = "Secret key for the cloud user", displayName = "Secret Key", secret = true) + private String secretKey; + + @UriParam(description = "Configuration object for cloud service authentication", displayName = "Service Keys", + security = "secret") + private ServiceKeys serviceKeys; + + @UriParam(description = "Topic name for publishMessage operations", displayName = "Topic Name") + private String topicName; + + @UriParam(description = "Long polling wait time in seconds when receiving messages", displayName = "Wait Seconds", + defaultValue = "0") + private int waitSeconds; + + @UriParam(description = "Delete message from the queue after it has been processed", displayName = "Delete After Read", + defaultValue = "true", label = "consumer") + private boolean deleteAfterRead = true; + + @UriParam(description = "Maximum number of messages to receive per poll", displayName = "Max Messages Per Poll", + defaultValue = "1", label = "consumer") + private int maxMessagesPerPoll = 1; + + @UriParam(description = "Autowire an existing MNSClient instance", displayName = "MNS Client", label = "advanced") + @Metadata(autowired = true) + private MNSClient mnsClient; + + private boolean topicEndpoint; + + public MNSEndpoint() { + } + + public MNSEndpoint(String uri, MNSComponent component) { + super(uri, component); + } + + @Override + public Producer createProducer() throws Exception { + return new MNSProducer(this); + } + + @Override + public Consumer createConsumer(Processor processor) throws Exception { + if (topicEndpoint) { + throw new IllegalArgumentException("Topic endpoints do not support consumers"); + } + MNSConsumer consumer = new MNSConsumer(this, processor); + configureConsumer(consumer); + consumer.setMaxMessagesPerPoll(maxMessagesPerPoll); + return consumer; + } + + public void initClient() { + if (mnsClient != null) { + return; + } + mnsClient = MNSUtils.createClient(this); + } + + public boolean isTopicEndpoint() { + return topicEndpoint; + } + + public void setTopicEndpoint(boolean topicEndpoint) { + this.topicEndpoint = topicEndpoint; + } + + public String getQueueName() { + return queueName; + } + + public void setQueueName(String queueName) { + this.queueName = queueName; + } + + public String getOperation() { + return operation; + } + + public void setOperation(String operation) { + this.operation = operation; + } + + public String getRegion() { + return region; + } + + public void setRegion(String region) { + this.region = region; + } + + public String getAccountEndpoint() { + return accountEndpoint; + } + + public void setAccountEndpoint(String accountEndpoint) { + this.accountEndpoint = accountEndpoint; + } + + public String getAccessKey() { + return accessKey; + } + + public void setAccessKey(String accessKey) { + this.accessKey = accessKey; + } + + public String getSecretKey() { + return secretKey; + } + + public void setSecretKey(String secretKey) { + this.secretKey = secretKey; + } + + public ServiceKeys getServiceKeys() { + return serviceKeys; + } + + public void setServiceKeys(ServiceKeys serviceKeys) { + this.serviceKeys = serviceKeys; + } + + public String getTopicName() { + return topicName; + } + + public void setTopicName(String topicName) { + this.topicName = topicName; + } + + public int getWaitSeconds() { + return waitSeconds; + } + + public void setWaitSeconds(int waitSeconds) { + this.waitSeconds = waitSeconds; + } + + public boolean isDeleteAfterRead() { + return deleteAfterRead; + } + + public void setDeleteAfterRead(boolean deleteAfterRead) { + this.deleteAfterRead = deleteAfterRead; + } + + public int getMaxMessagesPerPoll() { + return maxMessagesPerPoll; + } + + public void setMaxMessagesPerPoll(int maxMessagesPerPoll) { + this.maxMessagesPerPoll = maxMessagesPerPoll; + } + + public MNSClient getMnsClient() { + return mnsClient; + } + + public void setMnsClient(MNSClient mnsClient) { + this.mnsClient = mnsClient; + } + + public String resolveOperation() { + if (operation != null) { + return operation; + } + if (topicEndpoint) { + return MNSOperations.PUBLISH_MESSAGE; + } + return MNSOperations.RECEIVE_MESSAGE; + } + + public String resolveTopicName() { + if (topicName != null) { + return topicName; + } + if (topicEndpoint) { + return queueName; + } + return null; + } +} diff --git a/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSProducer.java b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSProducer.java new file mode 100644 index 0000000000000..bfad30118a68e --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSProducer.java @@ -0,0 +1,126 @@ +/* + * 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.alibaba.mns; + +import com.aliyun.mns.client.CloudQueue; +import com.aliyun.mns.client.CloudTopic; +import com.aliyun.mns.model.Base64TopicMessage; +import com.aliyun.mns.model.BaseMessage; +import com.aliyun.mns.model.Message; +import com.aliyun.mns.model.TopicMessage; +import org.apache.camel.Exchange; +import org.apache.camel.component.alibaba.mns.constants.MNSHeaders; +import org.apache.camel.component.alibaba.mns.constants.MNSOperations; +import org.apache.camel.component.alibaba.mns.constants.MNSProperties; +import org.apache.camel.component.alibaba.mns.models.ClientConfigurations; +import org.apache.camel.support.DefaultProducer; +import org.apache.camel.util.ObjectHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MNSProducer extends DefaultProducer { + + private static final Logger LOG = LoggerFactory.getLogger(MNSProducer.class); + + public MNSProducer(MNSEndpoint endpoint) { + super(endpoint); + } + + @Override + public void process(Exchange exchange) throws Exception { + MNSEndpoint endpoint = getEndpoint(); + endpoint.initClient(); + + ClientConfigurations configuration = MNSUtils.createClientConfigurations(endpoint, exchange); + String operation = configuration.getOperation(); + + switch (operation) { + case MNSOperations.SEND_MESSAGE -> sendMessage(endpoint, exchange, configuration); + case MNSOperations.DELETE_MESSAGE -> deleteMessage(endpoint, exchange, configuration); + case MNSOperations.PUBLISH_MESSAGE -> publishMessage(endpoint, exchange, configuration); + default -> throw new UnsupportedOperationException("Unsupported operation: " + operation); + } + } + + private void sendMessage(MNSEndpoint endpoint, Exchange exchange, ClientConfigurations configuration) throws Exception { + CloudQueue queue = endpoint.getMnsClient().getQueueRef(configuration.getQueueName()); + Message message = new Message(); + message.setMessageBody(MNSUtils.resolveMessageBody(exchange)); + + Integer delaySeconds = exchange.getIn().getHeader(MNSHeaders.DELAY_SECONDS, Integer.class); + if (delaySeconds != null) { + message.setDelaySeconds(delaySeconds); + } + + Integer priority = exchange.getIn().getHeader(MNSHeaders.PRIORITY, Integer.class); + if (priority != null) { + message.setPriority(priority); + } + + Message response = queue.putMessage(message); + setMessageResponseProperties(exchange, response); + } + + private void deleteMessage(MNSEndpoint endpoint, Exchange exchange, ClientConfigurations configuration) throws Exception { + String receiptHandle = MNSUtils.resolveReceiptHandle(exchange); + if (ObjectHelper.isEmpty(receiptHandle)) { + throw new IllegalArgumentException("Receipt handle is required for deleteMessage operation"); + } + + CloudQueue queue = endpoint.getMnsClient().getQueueRef(configuration.getQueueName()); + queue.deleteMessage(receiptHandle); + } + + private void publishMessage(MNSEndpoint endpoint, Exchange exchange, ClientConfigurations configuration) throws Exception { + String topic = configuration.getTopicName(); + if (ObjectHelper.isEmpty(topic)) { + throw new IllegalArgumentException("Topic name is required for publishMessage operation"); + } + + CloudTopic cloudTopic = endpoint.getMnsClient().getTopicRef(topic); + TopicMessage topicMessage = new Base64TopicMessage(); + topicMessage.setMessageBody(MNSUtils.resolveMessageBody(exchange)); + + String messageTag = exchange.getIn().getHeader(MNSHeaders.MESSAGE_TAG, String.class); + if (messageTag != null) { + topicMessage.setMessageTag(messageTag); + } + + TopicMessage response = cloudTopic.publishMessage(topicMessage); + setMessageResponseProperties(exchange, response); + } + + private void setMessageResponseProperties(Exchange exchange, BaseMessage response) { + if (response == null) { + return; + } + if (ObjectHelper.isNotEmpty(response.getMessageId())) { + exchange.setProperty(MNSProperties.MESSAGE_ID, response.getMessageId()); + } + if (ObjectHelper.isNotEmpty(response.getRequestId())) { + exchange.setProperty(MNSProperties.REQUEST_ID, response.getRequestId()); + } + if (ObjectHelper.isNotEmpty(response.getMessageBodyMD5())) { + exchange.setProperty(MNSProperties.MESSAGE_BODY_MD5, response.getMessageBodyMD5()); + } + } + + @Override + public MNSEndpoint getEndpoint() { + return (MNSEndpoint) super.getEndpoint(); + } +} diff --git a/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSUtils.java b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSUtils.java new file mode 100644 index 0000000000000..486dcf98d4276 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSUtils.java @@ -0,0 +1,149 @@ +/* + * 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.alibaba.mns; + +import com.aliyun.mns.client.MNSClient; +import com.aliyun.mns.client.MNSClientBuilder; +import org.apache.camel.Exchange; +import org.apache.camel.component.alibaba.common.models.ServiceKeys; +import org.apache.camel.component.alibaba.mns.constants.MNSHeaders; +import org.apache.camel.component.alibaba.mns.constants.MNSProperties; +import org.apache.camel.component.alibaba.mns.models.ClientConfigurations; +import org.apache.camel.util.ObjectHelper; + +public final class MNSUtils { + + private static final String TOPIC_PATH_PREFIX = "topic:"; + + private MNSUtils() { + } + + public static void configurePath(String remaining, MNSEndpoint endpoint) { + if (remaining != null && remaining.startsWith(TOPIC_PATH_PREFIX)) { + endpoint.setTopicEndpoint(true); + endpoint.setTopicName(remaining.substring(TOPIC_PATH_PREFIX.length())); + endpoint.setQueueName(remaining.substring(TOPIC_PATH_PREFIX.length())); + } else { + endpoint.setQueueName(remaining); + } + } + + public static MNSClient createClient(MNSEndpoint endpoint) { + String accessKey = resolveAccessKey(endpoint); + String secretKey = resolveSecretKey(endpoint); + + if (ObjectHelper.isEmpty(endpoint.getAccountEndpoint())) { + throw new IllegalArgumentException("accountEndpoint is required"); + } + if (ObjectHelper.isEmpty(endpoint.getRegion())) { + throw new IllegalArgumentException("region is required"); + } + + return MNSClientBuilder.create() + .accessKeyId(accessKey) + .accessKeySecret(secretKey) + .accountEndpoint(endpoint.getAccountEndpoint()) + .region(endpoint.getRegion()) + .build(); + } + + public static ClientConfigurations createClientConfigurations(MNSEndpoint endpoint, Exchange exchange) { + ClientConfigurations configuration = new ClientConfigurations(); + configuration.setOperation(resolveOperation(endpoint, exchange)); + configuration.setAccessKey(resolveAccessKey(endpoint)); + configuration.setSecretKey(resolveSecretKey(endpoint)); + configuration.setRegion(endpoint.getRegion()); + configuration.setAccountEndpoint(endpoint.getAccountEndpoint()); + configuration.setQueueName(resolveQueueName(endpoint, exchange)); + configuration.setTopicName(resolveTopicName(endpoint, exchange)); + return configuration; + } + + public static String resolveOperation(MNSEndpoint endpoint, Exchange exchange) { + String operation = exchange.getProperty(MNSProperties.OPERATION, String.class); + if (ObjectHelper.isEmpty(operation)) { + operation = exchange.getIn().getHeader(MNSProperties.OPERATION, String.class); + } + if (ObjectHelper.isEmpty(operation)) { + operation = endpoint.resolveOperation(); + } + return operation; + } + + public static String resolveQueueName(MNSEndpoint endpoint, Exchange exchange) { + String queueName = exchange.getProperty(MNSProperties.QUEUE_NAME, String.class); + if (ObjectHelper.isEmpty(queueName)) { + queueName = endpoint.getQueueName(); + } + return queueName; + } + + public static String resolveTopicName(MNSEndpoint endpoint, Exchange exchange) { + String topicName = exchange.getProperty(MNSProperties.TOPIC_NAME, String.class); + if (ObjectHelper.isEmpty(topicName)) { + topicName = exchange.getIn().getHeader(MNSProperties.TOPIC_NAME, String.class); + } + if (ObjectHelper.isEmpty(topicName)) { + topicName = endpoint.resolveTopicName(); + } + return topicName; + } + + public static String resolveReceiptHandle(Exchange exchange) { + String receiptHandle = exchange.getProperty(MNSProperties.RECEIPT_HANDLE, String.class); + if (ObjectHelper.isEmpty(receiptHandle)) { + receiptHandle = exchange.getIn().getHeader(MNSProperties.RECEIPT_HANDLE, String.class); + } + if (ObjectHelper.isEmpty(receiptHandle)) { + receiptHandle = exchange.getIn().getHeader(MNSHeaders.RECEIPT_HANDLE, String.class); + } + return receiptHandle; + } + + public static String resolveMessageBody(Exchange exchange) { + Object body = exchange.getMessage().getBody(); + if (body == null) { + throw new IllegalArgumentException("exchange body cannot be null / empty"); + } + if (body instanceof String stringBody) { + return stringBody; + } + return exchange.getMessage().getBody(String.class); + } + + private static String resolveAccessKey(MNSEndpoint endpoint) { + if (ObjectHelper.isNotEmpty(endpoint.getAccessKey())) { + return endpoint.getAccessKey(); + } + ServiceKeys serviceKeys = endpoint.getServiceKeys(); + if (serviceKeys != null && ObjectHelper.isNotEmpty(serviceKeys.getAccessKey())) { + return serviceKeys.getAccessKey(); + } + throw new IllegalArgumentException("authentication parameter 'access key (AK)' not found"); + } + + private static String resolveSecretKey(MNSEndpoint endpoint) { + if (ObjectHelper.isNotEmpty(endpoint.getSecretKey())) { + return endpoint.getSecretKey(); + } + ServiceKeys serviceKeys = endpoint.getServiceKeys(); + if (serviceKeys != null && ObjectHelper.isNotEmpty(serviceKeys.getSecretKey())) { + return serviceKeys.getSecretKey(); + } + throw new IllegalArgumentException("authentication parameter 'secret key (SK)' not found"); + } +} diff --git a/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/constants/MNSHeaders.java b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/constants/MNSHeaders.java new file mode 100644 index 0000000000000..1e1ec9948c53d --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/constants/MNSHeaders.java @@ -0,0 +1,55 @@ +/* + * 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.alibaba.mns.constants; + +import org.apache.camel.spi.Metadata; + +public final class MNSHeaders { + + @Metadata(label = "common", description = "The MNS message id", javaType = "String") + public static final String MESSAGE_ID = "CamelAlibabaMnsMessageId"; + + @Metadata(label = "common", description = "The MNS receipt handle", javaType = "String") + public static final String RECEIPT_HANDLE = "CamelAlibabaMnsReceiptHandle"; + + @Metadata(label = "common", description = "The MD5 digest of the message body", javaType = "String") + public static final String MESSAGE_BODY_MD5 = "CamelAlibabaMnsMessageBodyMd5"; + + @Metadata(label = "producer", description = "Delay in seconds before the message becomes visible", javaType = "Integer") + public static final String DELAY_SECONDS = "CamelAlibabaMnsDelaySeconds"; + + @Metadata(label = "producer", description = "Message priority", javaType = "Integer") + public static final String PRIORITY = "CamelAlibabaMnsPriority"; + + @Metadata(label = "producer", description = "Message tag for topic publish operations", javaType = "String") + public static final String MESSAGE_TAG = "CamelAlibabaMnsMessageTag"; + + @Metadata(label = "consumer", description = "Number of times the message has been dequeued", javaType = "Integer") + public static final String DEQUEUE_COUNT = "CamelAlibabaMnsDequeueCount"; + + @Metadata(label = "consumer", description = "Time when the message was enqueued", javaType = "java.util.Date") + public static final String ENQUEUE_TIME = "CamelAlibabaMnsEnqueueTime"; + + @Metadata(label = "consumer", description = "Next time the message becomes visible", javaType = "java.util.Date") + public static final String NEXT_VISIBLE_TIME = "CamelAlibabaMnsNextVisibleTime"; + + @Metadata(label = "consumer", description = "Time when the message was first dequeued", javaType = "java.util.Date") + public static final String FIRST_DEQUEUE_TIME = "CamelAlibabaMnsFirstDequeueTime"; + + private MNSHeaders() { + } +} diff --git a/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/constants/MNSOperations.java b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/constants/MNSOperations.java new file mode 100644 index 0000000000000..6f3d0a0b53041 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/constants/MNSOperations.java @@ -0,0 +1,28 @@ +/* + * 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.alibaba.mns.constants; + +public final class MNSOperations { + + public static final String SEND_MESSAGE = "sendMessage"; + public static final String RECEIVE_MESSAGE = "receiveMessage"; + public static final String DELETE_MESSAGE = "deleteMessage"; + public static final String PUBLISH_MESSAGE = "publishMessage"; + + private MNSOperations() { + } +} diff --git a/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/constants/MNSProperties.java b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/constants/MNSProperties.java new file mode 100644 index 0000000000000..fa8c2cfc7865c --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/constants/MNSProperties.java @@ -0,0 +1,32 @@ +/* + * 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.alibaba.mns.constants; + +public final class MNSProperties { + + public static final String OPERATION = "CamelAlibabaMnsOperation"; + public static final String QUEUE_NAME = "CamelAlibabaMnsQueueName"; + public static final String TOPIC_NAME = "CamelAlibabaMnsTopicName"; + public static final String RECEIPT_HANDLE = "CamelAlibabaMnsReceiptHandle"; + + public static final String MESSAGE_ID = "CamelAlibabaMnsMessageId"; + public static final String REQUEST_ID = "CamelAlibabaMnsRequestId"; + public static final String MESSAGE_BODY_MD5 = "CamelAlibabaMnsMessageBodyMd5"; + + private MNSProperties() { + } +} diff --git a/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/models/ClientConfigurations.java b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/models/ClientConfigurations.java new file mode 100644 index 0000000000000..850a52fedb081 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/models/ClientConfigurations.java @@ -0,0 +1,84 @@ +/* + * 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.alibaba.mns.models; + +public class ClientConfigurations { + + private String operation; + private String accessKey; + private String secretKey; + private String region; + private String accountEndpoint; + private String queueName; + private String topicName; + + public String getOperation() { + return operation; + } + + public void setOperation(String operation) { + this.operation = operation; + } + + public String getAccessKey() { + return accessKey; + } + + public void setAccessKey(String accessKey) { + this.accessKey = accessKey; + } + + public String getSecretKey() { + return secretKey; + } + + public void setSecretKey(String secretKey) { + this.secretKey = secretKey; + } + + public String getRegion() { + return region; + } + + public void setRegion(String region) { + this.region = region; + } + + public String getAccountEndpoint() { + return accountEndpoint; + } + + public void setAccountEndpoint(String accountEndpoint) { + this.accountEndpoint = accountEndpoint; + } + + public String getQueueName() { + return queueName; + } + + public void setQueueName(String queueName) { + this.queueName = queueName; + } + + public String getTopicName() { + return topicName; + } + + public void setTopicName(String topicName) { + this.topicName = topicName; + } +} diff --git a/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/PublishMessageTest.java b/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/PublishMessageTest.java new file mode 100644 index 0000000000000..beae467c6da66 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/PublishMessageTest.java @@ -0,0 +1,86 @@ +/* + * 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.alibaba.mns; + +import com.aliyun.mns.client.CloudTopic; +import com.aliyun.mns.client.MNSClient; +import com.aliyun.mns.model.Base64TopicMessage; +import com.aliyun.mns.model.TopicMessage; +import org.apache.camel.BindToRegistry; +import org.apache.camel.Exchange; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.alibaba.mns.constants.MNSProperties; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.junit6.CamelTestSupport; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +class PublishMessageTest extends CamelTestSupport { + + private final TestConfiguration testConfiguration = new TestConfiguration(); + + @BindToRegistry("mnsClient") + MNSClient mnsClient = mock(MNSClient.class); + + CloudTopic cloudTopic = mock(CloudTopic.class); + + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + from("direct:publish") + .to("alibaba-mns:topic:" + testConfiguration.getProperty("topic") + + "?operation=publishMessage" + + "®ion=" + testConfiguration.getProperty("region") + + "&accountEndpoint=" + testConfiguration.getProperty("accountEndpoint") + + "&accessKey=" + testConfiguration.getProperty("accessKey") + + "&secretKey=" + testConfiguration.getProperty("secretKey") + + "&mnsClient=#mnsClient") + .to("mock:result"); + } + }; + } + + @Test + void testPublishMessage() throws Exception { + TopicMessage response = new Base64TopicMessage(); + response.setMessageId("topic-message-id"); + response.setRequestId("topic-request-id"); + + when(mnsClient.getTopicRef(testConfiguration.getProperty("topic"))).thenReturn(cloudTopic); + when(cloudTopic.publishMessage(any(TopicMessage.class))).thenReturn(response); + + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMinimumMessageCount(1); + + template.sendBody("direct:publish", "hello topic"); + + mock.assertIsSatisfied(); + + Exchange exchange = mock.getExchanges().get(0); + assertThat(exchange.getProperty(MNSProperties.MESSAGE_ID)).isEqualTo("topic-message-id"); + assertThat(exchange.getProperty(MNSProperties.REQUEST_ID)).isEqualTo("topic-request-id"); + + verify(cloudTopic).publishMessage(any(TopicMessage.class)); + } +} diff --git a/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/ReceiveMessageConsumerTest.java b/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/ReceiveMessageConsumerTest.java new file mode 100644 index 0000000000000..0a5f255bcf678 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/ReceiveMessageConsumerTest.java @@ -0,0 +1,90 @@ +/* + * 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.alibaba.mns; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.TimeUnit; + +import com.aliyun.mns.client.CloudQueue; +import com.aliyun.mns.client.MNSClient; +import com.aliyun.mns.model.Message; +import org.apache.camel.BindToRegistry; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.alibaba.mns.constants.MNSHeaders; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.junit6.CamelTestSupport; +import org.junit.jupiter.api.Test; + +import static org.awaitility.Awaitility.await; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +class ReceiveMessageConsumerTest extends CamelTestSupport { + + private final TestConfiguration testConfiguration = new TestConfiguration(); + + @BindToRegistry("mnsClient") + MNSClient mnsClient = mock(MNSClient.class); + + CloudQueue cloudQueue = mock(CloudQueue.class); + + @Override + protected RouteBuilder createRouteBuilder() { + String accountEndpoint = URLEncoder.encode(testConfiguration.getProperty("accountEndpoint"), + StandardCharsets.UTF_8); + return new RouteBuilder() { + @Override + public void configure() { + from("alibaba-mns:" + testConfiguration.getProperty("queue") + + "?region=" + testConfiguration.getProperty("region") + + "&accountEndpoint=" + accountEndpoint + + "&accessKey=" + testConfiguration.getProperty("accessKey") + + "&secretKey=" + testConfiguration.getProperty("secretKey") + + "&deleteAfterRead=true" + + "&initialDelay=100" + + "&delay=200" + + "&useFixedDelay=true" + + "&mnsClient=#mnsClient") + .to("mock:result"); + } + }; + } + + @Test + void testReceiveMessageAndDeleteAfterRead() throws Exception { + Message message = new Message("received body"); + message.setMessageId("received-id"); + message.setReceiptHandle("receipt-handle-123"); + message.setMessageBodyMD5("received-md5"); + + when(mnsClient.getQueueRef(testConfiguration.getProperty("queue"))).thenReturn(cloudQueue); + when(cloudQueue.popMessage()).thenReturn(message).thenReturn(null); + + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMessageCount(1); + mock.expectedHeaderReceived(MNSHeaders.MESSAGE_ID, "received-id"); + mock.expectedHeaderReceived(MNSHeaders.RECEIPT_HANDLE, "receipt-handle-123"); + mock.expectedBodiesReceived("received body"); + + MockEndpoint.assertIsSatisfied(context, 20, TimeUnit.SECONDS); + + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> verify(cloudQueue).deleteMessage(eq("receipt-handle-123"))); + } +} diff --git a/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/SendMessageTest.java b/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/SendMessageTest.java new file mode 100644 index 0000000000000..98d11f885b986 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/SendMessageTest.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.alibaba.mns; + +import com.aliyun.mns.client.CloudQueue; +import com.aliyun.mns.client.MNSClient; +import com.aliyun.mns.model.Message; +import org.apache.camel.BindToRegistry; +import org.apache.camel.Exchange; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.alibaba.mns.constants.MNSProperties; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.junit6.CamelTestSupport; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +class SendMessageTest extends CamelTestSupport { + + private final TestConfiguration testConfiguration = new TestConfiguration(); + + @BindToRegistry("mnsClient") + MNSClient mnsClient = mock(MNSClient.class); + + CloudQueue cloudQueue = mock(CloudQueue.class); + + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + from("direct:send") + .to("alibaba-mns:" + testConfiguration.getProperty("queue") + + "?operation=sendMessage" + + "®ion=" + testConfiguration.getProperty("region") + + "&accountEndpoint=" + testConfiguration.getProperty("accountEndpoint") + + "&accessKey=" + testConfiguration.getProperty("accessKey") + + "&secretKey=" + testConfiguration.getProperty("secretKey") + + "&mnsClient=#mnsClient") + .to("mock:result"); + } + }; + } + + @Test + void testSendMessage() throws Exception { + Message response = new Message("response"); + response.setMessageId("message-id-123"); + response.setRequestId("request-id-456"); + response.setMessageBodyMD5("md5-value"); + + when(mnsClient.getQueueRef(testConfiguration.getProperty("queue"))).thenReturn(cloudQueue); + when(cloudQueue.putMessage(any(Message.class))).thenReturn(response); + + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMinimumMessageCount(1); + + template.sendBody("direct:send", "hello mns"); + + mock.assertIsSatisfied(); + + Exchange exchange = mock.getExchanges().get(0); + assertThat(exchange.getProperty(MNSProperties.MESSAGE_ID)).isEqualTo("message-id-123"); + assertThat(exchange.getProperty(MNSProperties.REQUEST_ID)).isEqualTo("request-id-456"); + assertThat(exchange.getProperty(MNSProperties.MESSAGE_BODY_MD5)).isEqualTo("md5-value"); + + verify(cloudQueue).putMessage(any(Message.class)); + } +} diff --git a/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/TestConfiguration.java b/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/TestConfiguration.java new file mode 100644 index 0000000000000..c49da0d696171 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/TestConfiguration.java @@ -0,0 +1,57 @@ +/* + * 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.alibaba.mns; + +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import org.apache.camel.test.junit6.TestSupport; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +class TestConfiguration { + + private static final Logger LOGGER = LoggerFactory.getLogger(TestConfiguration.class); + private static Map propertyMap; + + TestConfiguration() { + initPropertyMap(); + } + + void initPropertyMap() { + if (propertyMap == null) { + propertyMap = new HashMap<>(); + String propertyFileName = "testconfiguration.properties"; + try { + Properties properties = TestSupport.loadExternalProperties(getClass().getClassLoader(), propertyFileName); + for (String key : properties.stringPropertyNames()) { + propertyMap.put(key, properties.getProperty(key)); + } + } catch (Exception e) { + LOGGER.error("Cannot load property file {}, reason {}", propertyFileName, e.getMessage()); + } + } + } + + String getProperty(String key) { + if (propertyMap == null) { + initPropertyMap(); + } + return propertyMap.get(key); + } +} diff --git a/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/constants/MNSOperationsTest.java b/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/constants/MNSOperationsTest.java new file mode 100644 index 0000000000000..04b05e564b943 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/constants/MNSOperationsTest.java @@ -0,0 +1,32 @@ +/* + * 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.alibaba.mns.constants; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class MNSOperationsTest { + + @Test + void testOperationNames() { + assertThat(MNSOperations.SEND_MESSAGE).isEqualTo("sendMessage"); + assertThat(MNSOperations.RECEIVE_MESSAGE).isEqualTo("receiveMessage"); + assertThat(MNSOperations.DELETE_MESSAGE).isEqualTo("deleteMessage"); + assertThat(MNSOperations.PUBLISH_MESSAGE).isEqualTo("publishMessage"); + } +} diff --git a/components/camel-alibaba/camel-alibaba-mns/src/test/resources/log4j2.properties b/components/camel-alibaba/camel-alibaba-mns/src/test/resources/log4j2.properties new file mode 100644 index 0000000000000..c3df5b0a8b22a --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/test/resources/log4j2.properties @@ -0,0 +1,29 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- + +appender.file.type = File +appender.file.name = file +appender.file.fileName = target/camel-alibaba-mns-test.log +appender.file.layout.type = PatternLayout +appender.file.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n +appender.out.type = Console +appender.out.name = out +appender.out.layout.type = PatternLayout +appender.out.layout.pattern = [%30.30t] %-30.30c{1} %-5p %m%n + +rootLogger.level = INFO +rootLogger.appenderRef.file.ref = file diff --git a/components/camel-alibaba/camel-alibaba-mns/src/test/resources/testconfiguration.properties b/components/camel-alibaba/camel-alibaba-mns/src/test/resources/testconfiguration.properties new file mode 100644 index 0000000000000..15d8d8675c6d1 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/test/resources/testconfiguration.properties @@ -0,0 +1,23 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- + +accessKey=dummy_access_key +secretKey=dummy_secret_key +region=cn-hangzhou +accountEndpoint=https://123456.mns.cn-hangzhou.aliyuncs.com +queue=test-queue +topic=test-topic diff --git a/parent/pom.xml b/parent/pom.xml index da651323c6444..71aad63da96ca 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -723,6 +723,21 @@ camel-ai-tool ${project.version} + + org.apache.camel + camel-alibaba-common + ${project.version} + + + org.apache.camel + camel-alibaba-mns + ${project.version} + + + org.apache.camel + camel-alibaba-oss + ${project.version} + org.apache.camel camel-amqp From 9a70677c5a402ab996e7f2708b9c3d85b16a55d5 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 10 Aug 2026 17:44:08 +0000 Subject: [PATCH 03/12] CAMEL-24373: Wire camel-alibaba modules into build and add ClientRegistry Add BOM/coverage entries, SDK version properties, fix MojoHelper to list component modules only, and add AlibabaClientRegistry with tests. Co-authored-by: Omar Atie --- bom/camel-bom/pom.xml | 15 +++++++ .../camel-alibaba-common/pom.xml | 2 +- .../alibaba/common/AlibabaClientRegistry.java | 42 +++++++++++++++++++ .../common/AlibabaClientRegistryTest.java | 40 ++++++++++++++++++ .../camel-alibaba/camel-alibaba-mns/pom.xml | 2 +- .../camel-alibaba/camel-alibaba-oss/pom.xml | 2 +- coverage/pom.xml | 15 +++++++ parent/pom.xml | 2 + .../camel/maven/packaging/MojoHelper.java | 3 +- 9 files changed, 118 insertions(+), 5 deletions(-) create mode 100644 components/camel-alibaba/camel-alibaba-common/src/main/java/org/apache/camel/component/alibaba/common/AlibabaClientRegistry.java create mode 100644 components/camel-alibaba/camel-alibaba-common/src/test/java/org/apache/camel/component/alibaba/common/AlibabaClientRegistryTest.java diff --git a/bom/camel-bom/pom.xml b/bom/camel-bom/pom.xml index d2419f9f74aed..83065451a0cbd 100644 --- a/bom/camel-bom/pom.xml +++ b/bom/camel-bom/pom.xml @@ -66,6 +66,21 @@ camel-ai-tool 4.23.0-SNAPSHOT + + org.apache.camel + camel-alibaba-common + 4.22.0-SNAPSHOT + + + org.apache.camel + camel-alibaba-mns + 4.22.0-SNAPSHOT + + + org.apache.camel + camel-alibaba-oss + 4.22.0-SNAPSHOT + org.apache.camel camel-amqp diff --git a/components/camel-alibaba/camel-alibaba-common/pom.xml b/components/camel-alibaba/camel-alibaba-common/pom.xml index f3adc4b52f08e..fcdee7eff3fc3 100644 --- a/components/camel-alibaba/camel-alibaba-common/pom.xml +++ b/components/camel-alibaba/camel-alibaba-common/pom.xml @@ -44,7 +44,7 @@ com.aliyun alibabacloud-oss-v2 - 0.4.1 + ${alibabacloud-oss-version} org.apache.camel diff --git a/components/camel-alibaba/camel-alibaba-common/src/main/java/org/apache/camel/component/alibaba/common/AlibabaClientRegistry.java b/components/camel-alibaba/camel-alibaba-common/src/main/java/org/apache/camel/component/alibaba/common/AlibabaClientRegistry.java new file mode 100644 index 0000000000000..17eb24f48b6f3 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-common/src/main/java/org/apache/camel/component/alibaba/common/AlibabaClientRegistry.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.alibaba.common; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Supplier; + +/** + * Simple client registry for reusing Alibaba Cloud SDK clients within a Camel context. + */ +public final class AlibabaClientRegistry { + + private final Map clients = new ConcurrentHashMap<>(); + + public T getOrCreate(String key, Supplier supplier) { + @SuppressWarnings("unchecked") + T client = (T) clients.get(key); + if (client != null) { + return client; + } + return clients.computeIfAbsent(key, k -> supplier.get()); + } + + public void clear() { + clients.clear(); + } +} diff --git a/components/camel-alibaba/camel-alibaba-common/src/test/java/org/apache/camel/component/alibaba/common/AlibabaClientRegistryTest.java b/components/camel-alibaba/camel-alibaba-common/src/test/java/org/apache/camel/component/alibaba/common/AlibabaClientRegistryTest.java new file mode 100644 index 0000000000000..4f8a74661efdc --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-common/src/test/java/org/apache/camel/component/alibaba/common/AlibabaClientRegistryTest.java @@ -0,0 +1,40 @@ +/* + * 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.alibaba.common; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class AlibabaClientRegistryTest { + + @Test + void reusesClientForSameKey() { + AlibabaClientRegistry registry = new AlibabaClientRegistry(); + Object first = registry.getOrCreate("oss:ak:region", () -> new Object()); + Object second = registry.getOrCreate("oss:ak:region", () -> new Object()); + assertThat(second).isSameAs(first); + } + + @Test + void createsDistinctClientsForDifferentKeys() { + AlibabaClientRegistry registry = new AlibabaClientRegistry(); + Object first = registry.getOrCreate("oss:ak:cn-hangzhou", () -> new Object()); + Object second = registry.getOrCreate("oss:ak:cn-beijing", () -> new Object()); + assertThat(second).isNotSameAs(first); + } +} diff --git a/components/camel-alibaba/camel-alibaba-mns/pom.xml b/components/camel-alibaba/camel-alibaba-mns/pom.xml index db5851a68fd06..47820f1912e61 100644 --- a/components/camel-alibaba/camel-alibaba-mns/pom.xml +++ b/components/camel-alibaba/camel-alibaba-mns/pom.xml @@ -51,7 +51,7 @@ com.aliyun.mns aliyun-sdk-mns - 2.0.0 + ${aliyun-sdk-mns-version} diff --git a/components/camel-alibaba/camel-alibaba-oss/pom.xml b/components/camel-alibaba/camel-alibaba-oss/pom.xml index 08f8d7e9196da..2cc1389376563 100644 --- a/components/camel-alibaba/camel-alibaba-oss/pom.xml +++ b/components/camel-alibaba/camel-alibaba-oss/pom.xml @@ -52,7 +52,7 @@ com.aliyun alibabacloud-oss-v2 - 0.4.1 + ${alibabacloud-oss-version} diff --git a/coverage/pom.xml b/coverage/pom.xml index 091662322f987..cac05d60ffa8f 100644 --- a/coverage/pom.xml +++ b/coverage/pom.xml @@ -221,6 +221,21 @@ camel-activemq6 ${project.version} + + org.apache.camel + camel-alibaba-common + ${project.version} + + + org.apache.camel + camel-alibaba-mns + ${project.version} + + + org.apache.camel + camel-alibaba-oss + ${project.version} + org.apache.camel camel-amqp diff --git a/parent/pom.xml b/parent/pom.xml index 71aad63da96ca..a9eb89f61577b 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -64,6 +64,8 @@ 3.14.1 3.2.1 0.3.0 + 0.4.1 + 2.0.0 3.5.1 2.0.5 2.0.0.AM27 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 aa25bfb794369..d32d722c50009 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 @@ -143,8 +143,7 @@ public static List getComponentPath(Path dir) { dir.resolve("camel-vertx-http"), dir.resolve("camel-vertx-websocket")); case "camel-alibaba": - return Arrays.asList(dir.resolve("camel-alibaba-common"), - dir.resolve("camel-alibaba-oss"), + return Arrays.asList(dir.resolve("camel-alibaba-oss"), dir.resolve("camel-alibaba-mns")); case "camel-huawei": return Arrays.asList(dir.resolve("camel-huaweicloud-frs"), From 6d840b58fa6c786ffeea433a76d8d25f79a02eb8 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 10 Aug 2026 17:44:36 +0000 Subject: [PATCH 04/12] CAMEL-24373: Fix AlibabaClientRegistry generic compilation Co-authored-by: Omar Atie --- .../alibaba/common/AlibabaClientRegistry.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/components/camel-alibaba/camel-alibaba-common/src/main/java/org/apache/camel/component/alibaba/common/AlibabaClientRegistry.java b/components/camel-alibaba/camel-alibaba-common/src/main/java/org/apache/camel/component/alibaba/common/AlibabaClientRegistry.java index 17eb24f48b6f3..35f1b6c0e9552 100644 --- a/components/camel-alibaba/camel-alibaba-common/src/main/java/org/apache/camel/component/alibaba/common/AlibabaClientRegistry.java +++ b/components/camel-alibaba/camel-alibaba-common/src/main/java/org/apache/camel/component/alibaba/common/AlibabaClientRegistry.java @@ -28,12 +28,15 @@ public final class AlibabaClientRegistry { private final Map clients = new ConcurrentHashMap<>(); public T getOrCreate(String key, Supplier supplier) { - @SuppressWarnings("unchecked") - T client = (T) clients.get(key); - if (client != null) { + Object existing = clients.get(key); + if (existing != null) { + @SuppressWarnings("unchecked") + T client = (T) existing; return client; } - return clients.computeIfAbsent(key, k -> supplier.get()); + T created = supplier.get(); + clients.put(key, created); + return created; } public void clear() { From af31f70dd915e070dc624c0dc3de9cde640065c9 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 10 Aug 2026 17:58:18 +0000 Subject: [PATCH 05/12] CAMEL-24373: Address review findings and regenerate catalog - Default MNS queue producer to sendMessage; add test - Validate OSS bucket name for all putObject body types - Advance OSS consumer continuation token only after successful batch - Remove non-existent Spring Boot starter from MNS docs - Regenerate catalog entries for alibaba-oss and alibaba-mns Co-authored-by: Omar Atie --- .../camel/catalog/components.properties | 2 + .../camel/catalog/components/alibaba-mns.json | 79 +++++++++++ .../camel/catalog/components/alibaba-oss.json | 79 +++++++++++ .../org/apache/camel/catalog/docs.properties | 2 + .../catalog/docs/alibaba-mns-component.adoc | 124 ++++++++++++++++++ .../catalog/docs/alibaba-oss-component.adoc | 102 ++++++++++++++ .../src/main/docs/alibaba-mns-component.adoc | 23 ---- .../component/alibaba/mns/MNSEndpoint.java | 7 + .../mns/SendMessageDefaultOperationTest.java | 75 +++++++++++ .../component/alibaba/oss/OSSConsumer.java | 11 +- .../component/alibaba/oss/OSSProducer.java | 9 +- .../apache/camel/main/components.properties | 2 + 12 files changed, 485 insertions(+), 30 deletions(-) create mode 100644 catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-mns.json create mode 100644 catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-oss.json create mode 100644 catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/alibaba-mns-component.adoc create mode 100644 catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/alibaba-oss-component.adoc create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/SendMessageDefaultOperationTest.java diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties index e8a80790f9c4c..f0cd17702e552 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties @@ -2,6 +2,8 @@ a2a activemq activemq6 ai-tool +alibaba-mns +alibaba-oss amqp arangodb as2 diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-mns.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-mns.json new file mode 100644 index 0000000000000..d78d4c416999c --- /dev/null +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-mns.json @@ -0,0 +1,79 @@ +{ + "component": { + "kind": "component", + "name": "alibaba-mns", + "title": "Alibaba Message Service (MNS)", + "description": "Send and receive messages to\/from Alibaba Cloud Message Service (MNS).", + "deprecated": false, + "firstVersion": "4.22.0", + "label": "cloud,messaging", + "javaType": "org.apache.camel.component.alibaba.mns.MNSComponent", + "supportLevel": "Preview", + "groupId": "org.apache.camel", + "artifactId": "camel-alibaba-mns", + "version": "4.22.0-SNAPSHOT", + "scheme": "alibaba-mns", + "extendsScheme": "", + "syntax": "alibaba-mns:queueName", + "async": false, + "api": false, + "consumerOnly": false, + "producerOnly": false, + "lenientProperties": false, + "browsable": false, + "remote": true + }, + "componentProperties": { + "bridgeErrorHandler": { "index": 0, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, + "lazyStartProducer": { "index": 1, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." }, + "autowiredEnabled": { "index": 2, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching type, which then gets configured on the component. This can be used for automatic configuring JDBC data sources, JMS connection factories, AWS Clients, etc." }, + "healthCheckConsumerEnabled": { "index": 3, "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": 4, "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 producer checks globally by setting camel.health.producersEnabled=true." } + }, + "headers": { + "CamelAlibabaMnsMessageId": { "index": 0, "kind": "header", "displayName": "", "group": "common", "label": "common", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The MNS message id", "constantName": "org.apache.camel.component.alibaba.mns.constants.MNSHeaders#MESSAGE_ID" }, + "CamelAlibabaMnsReceiptHandle": { "index": 1, "kind": "header", "displayName": "", "group": "common", "label": "common", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The MNS receipt handle", "constantName": "org.apache.camel.component.alibaba.mns.constants.MNSHeaders#RECEIPT_HANDLE" }, + "CamelAlibabaMnsMessageBodyMd5": { "index": 2, "kind": "header", "displayName": "", "group": "common", "label": "common", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The MD5 digest of the message body", "constantName": "org.apache.camel.component.alibaba.mns.constants.MNSHeaders#MESSAGE_BODY_MD5" }, + "CamelAlibabaMnsDelaySeconds": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Delay in seconds before the message becomes visible", "constantName": "org.apache.camel.component.alibaba.mns.constants.MNSHeaders#DELAY_SECONDS" }, + "CamelAlibabaMnsPriority": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Message priority", "constantName": "org.apache.camel.component.alibaba.mns.constants.MNSHeaders#PRIORITY" }, + "CamelAlibabaMnsMessageTag": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Message tag for topic publish operations", "constantName": "org.apache.camel.component.alibaba.mns.constants.MNSHeaders#MESSAGE_TAG" }, + "CamelAlibabaMnsDequeueCount": { "index": 6, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Number of times the message has been dequeued", "constantName": "org.apache.camel.component.alibaba.mns.constants.MNSHeaders#DEQUEUE_COUNT" }, + "CamelAlibabaMnsEnqueueTime": { "index": 7, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "java.util.Date", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Time when the message was enqueued", "constantName": "org.apache.camel.component.alibaba.mns.constants.MNSHeaders#ENQUEUE_TIME" }, + "CamelAlibabaMnsNextVisibleTime": { "index": 8, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "java.util.Date", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Next time the message becomes visible", "constantName": "org.apache.camel.component.alibaba.mns.constants.MNSHeaders#NEXT_VISIBLE_TIME" }, + "CamelAlibabaMnsFirstDequeueTime": { "index": 9, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "java.util.Date", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Time when the message was first dequeued", "constantName": "org.apache.camel.component.alibaba.mns.constants.MNSHeaders#FIRST_DEQUEUE_TIME" } + }, + "properties": { + "queueName": { "index": 0, "kind": "path", "displayName": "Queue Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Queue name, or topic name when using the topic URI syntax" }, + "accessKey": { "index": 1, "kind": "parameter", "displayName": "Access Key", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "security": "secret", "description": "Access key for the cloud user" }, + "accountEndpoint": { "index": 2, "kind": "parameter", "displayName": "Account Endpoint", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "MNS account endpoint, for example https:\/\/123456.mns.cn-hangzhou.aliyuncs.com" }, + "operation": { "index": 3, "kind": "parameter", "displayName": "Operation", "group": "common", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "sendMessage", "receiveMessage", "deleteMessage", "publishMessage" ], "deprecated": false, "autowired": false, "secret": false, "description": "Operation to perform" }, + "region": { "index": 4, "kind": "parameter", "displayName": "Region", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Alibaba Cloud region" }, + "secretKey": { "index": 5, "kind": "parameter", "displayName": "Secret Key", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "security": "secret", "description": "Secret key for the cloud user" }, + "serviceKeys": { "index": 6, "kind": "parameter", "displayName": "Service Keys", "group": "common", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.alibaba.common.models.ServiceKeys", "deprecated": false, "autowired": false, "secret": true, "security": "secret", "description": "Configuration object for cloud service authentication" }, + "topicName": { "index": 7, "kind": "parameter", "displayName": "Topic Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Topic name for publishMessage operations" }, + "waitSeconds": { "index": 8, "kind": "parameter", "displayName": "Wait Seconds", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "Long polling wait time in seconds when receiving messages" }, + "deleteAfterRead": { "index": 9, "kind": "parameter", "displayName": "Delete After Read", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Delete message from the queue after it has been processed" }, + "maxMessagesPerPoll": { "index": 10, "kind": "parameter", "displayName": "Max Messages Per Poll", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Maximum number of messages to receive per poll" }, + "sendEmptyMessageWhenIdle": { "index": 11, "kind": "parameter", "displayName": "Send Empty Message When Idle", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead." }, + "bridgeErrorHandler": { "index": 12, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, + "exceptionHandler": { "index": 13, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, + "exchangePattern": { "index": 14, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." }, + "pollStrategy": { "index": 15, "kind": "parameter", "displayName": "Poll Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.PollingConsumerPollStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "A pluggable org.apache.camel.PollingConsumerPollingStrategy allowing you to provide your custom implementation to control error handling usually occurred during the poll operation before an Exchange have been created and being routed in Camel." }, + "lazyStartProducer": { "index": 16, "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 producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." }, + "mnsClient": { "index": 17, "kind": "parameter", "displayName": "MNS Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "com.aliyun.mns.client.MNSClient", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "description": "Autowire an existing MNSClient instance" }, + "backoffErrorThreshold": { "index": 18, "kind": "parameter", "displayName": "Backoff Error Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent error polls (failed due some error) that should happen before the backoffMultipler should kick-in." }, + "backoffIdleThreshold": { "index": 19, "kind": "parameter", "displayName": "Backoff Idle Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent idle polls that should happen before the backoffMultipler should kick-in." }, + "backoffMultiplier": { "index": 20, "kind": "parameter", "displayName": "Backoff Multiplier", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "To let the scheduled polling consumer backoff if there has been a number of subsequent idles\/errors in a row. The multiplier is then the number of polls that will be skipped before the next actual attempt is happening again. When this option is in use then backoffIdleThreshold and\/or backoffErrorThreshold must also be configured." }, + "delay": { "index": 21, "kind": "parameter", "displayName": "Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 500, "description": "Milliseconds before the next poll." }, + "greedy": { "index": 22, "kind": "parameter", "displayName": "Greedy", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If greedy is enabled, then the ScheduledPollConsumer will run immediately again, if the previous run polled 1 or more messages." }, + "initialDelay": { "index": 23, "kind": "parameter", "displayName": "Initial Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "Milliseconds before the first poll starts." }, + "repeatCount": { "index": 24, "kind": "parameter", "displayName": "Repeat Count", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "Specifies a maximum limit of number of fires. So if you set it to 1, the scheduler will only fire once. If you set it to 5, it will only fire five times. A value of zero or negative means fire forever." }, + "runLoggingLevel": { "index": 25, "kind": "parameter", "displayName": "Run Logging Level", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "enum", "javaType": "org.apache.camel.LoggingLevel", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "TRACE", "description": "The consumer logs a start\/complete log line when it polls. This option allows you to configure the logging level for that." }, + "scheduledExecutorService": { "index": 26, "kind": "parameter", "displayName": "Scheduled Executor Service", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.concurrent.ScheduledExecutorService", "deprecated": false, "autowired": false, "secret": false, "description": "Allows for configuring a custom\/shared thread pool to use for the consumer. By default each consumer has its own single threaded thread pool." }, + "scheduler": { "index": 27, "kind": "parameter", "displayName": "Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.lang.Object", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "none", "description": "To use a cron scheduler from either camel-spring or camel-quartz component. Use value spring or quartz for built in scheduler" }, + "schedulerProperties": { "index": 28, "kind": "parameter", "displayName": "Scheduler Properties", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.Map", "prefix": "scheduler.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "To configure additional properties when using a custom scheduler or any of the Quartz, Spring based scheduler. This is a multi-value option with prefix: scheduler." }, + "startScheduler": { "index": 29, "kind": "parameter", "displayName": "Start Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether the scheduler should be auto started." }, + "timeUnit": { "index": 30, "kind": "parameter", "displayName": "Time Unit", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "enum", "javaType": "java.util.concurrent.TimeUnit", "enum": [ "NANOSECONDS", "MICROSECONDS", "MILLISECONDS", "SECONDS", "MINUTES", "HOURS", "DAYS" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "MILLISECONDS", "description": "Time unit for initialDelay and delay options." }, + "useFixedDelay": { "index": 31, "kind": "parameter", "displayName": "Use Fixed Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in JDK for details." } + } +} diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-oss.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-oss.json new file mode 100644 index 0000000000000..de6f70f530bfb --- /dev/null +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-oss.json @@ -0,0 +1,79 @@ +{ + "component": { + "kind": "component", + "name": "alibaba-oss", + "title": "Alibaba Object Storage Service (OSS)", + "description": "Alibaba Cloud Object Storage Service (OSS) component", + "deprecated": false, + "firstVersion": "4.22.0", + "label": "cloud", + "javaType": "org.apache.camel.component.alibaba.oss.OSSComponent", + "supportLevel": "Preview", + "groupId": "org.apache.camel", + "artifactId": "camel-alibaba-oss", + "version": "4.22.0-SNAPSHOT", + "scheme": "alibaba-oss", + "extendsScheme": "", + "syntax": "alibaba-oss:operation", + "async": false, + "api": false, + "consumerOnly": false, + "producerOnly": false, + "lenientProperties": false, + "browsable": false, + "remote": true + }, + "componentProperties": { + "bridgeErrorHandler": { "index": 0, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, + "lazyStartProducer": { "index": 1, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." }, + "autowiredEnabled": { "index": 2, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching type, which then gets configured on the component. This can be used for automatic configuring JDBC data sources, JMS connection factories, AWS Clients, etc." }, + "healthCheckConsumerEnabled": { "index": 3, "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": 4, "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 producer checks globally by setting camel.health.producersEnabled=true." } + }, + "headers": { + "CamelAlibabaOssBucketName": { "index": 0, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the bucket where object is contained", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#BUCKET_NAME" }, + "CamelAlibabaOssObjectKey": { "index": 1, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The key that the object is stored under", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#OBJECT_KEY" }, + "CamelAlibabaOssLastModified": { "index": 2, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The date and time that the object was last modified", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#LAST_MODIFIED" }, + "CamelAlibabaOssETag": { "index": 3, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The 128-bit MD5 digest of the object content", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#ETAG" }, + "CamelAlibabaOssContentMD5": { "index": 4, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The 128-bit Base64-encoded digest of the object", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#CONTENT_MD5" }, + "CamelAlibabaOssObjectType": { "index": 5, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Shows whether the object is a file or a folder", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#OBJECT_TYPE" }, + "Content-Length": { "index": 6, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The size of the object body in bytes", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#CONTENT_LENGTH" }, + "Content-Type": { "index": 7, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The type of content stored in the object", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#CONTENT_TYPE" }, + "CamelFileName": { "index": 8, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the object with which the operation is to be performed", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#FILE_NAME" } + }, + "properties": { + "operation": { "index": 0, "kind": "path", "displayName": "Operation", "group": "producer", "label": "producer", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Operation to be performed" }, + "bucketName": { "index": 1, "kind": "parameter", "displayName": "Bucket Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "endpointIdentity": true, "description": "Name of bucket to perform operation on" }, + "endpoint": { "index": 2, "kind": "parameter", "displayName": "Endpoint url", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "OSS endpoint URL. Carries higher precedence than region based client initialization" }, + "objectName": { "index": 3, "kind": "parameter", "displayName": "Object Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of object to perform operation with" }, + "region": { "index": 4, "kind": "parameter", "displayName": "Service region", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "OSS service region" }, + "deleteAfterRead": { "index": 5, "kind": "parameter", "displayName": "Delete after read", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Determines if objects should be deleted after they have been retrieved" }, + "maxMessagesPerPoll": { "index": 6, "kind": "parameter", "displayName": "Maximum messages per poll", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 10, "description": "The maximum number of messages to poll at each polling" }, + "prefix": { "index": 7, "kind": "parameter", "displayName": "Prefix", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The object name prefix used for filtering objects to be listed" }, + "sendEmptyMessageWhenIdle": { "index": 8, "kind": "parameter", "displayName": "Send Empty Message When Idle", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead." }, + "bridgeErrorHandler": { "index": 9, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, + "exceptionHandler": { "index": 10, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, + "exchangePattern": { "index": 11, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." }, + "pollStrategy": { "index": 12, "kind": "parameter", "displayName": "Poll Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.PollingConsumerPollStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "A pluggable org.apache.camel.PollingConsumerPollingStrategy allowing you to provide your custom implementation to control error handling usually occurred during the poll operation before an Exchange have been created and being routed in Camel." }, + "maxKeys": { "index": 13, "kind": "parameter", "displayName": "Max Keys", "group": "producer", "label": "consumer,producer", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "description": "The maximum number of keys returned when listing objects" }, + "lazyStartProducer": { "index": 14, "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 producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." }, + "ossClient": { "index": 15, "kind": "parameter", "displayName": "OSS Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "com.aliyun.sdk.service.oss2.OSSClient", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "description": "An autowired OSS client" }, + "backoffErrorThreshold": { "index": 16, "kind": "parameter", "displayName": "Backoff Error Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent error polls (failed due some error) that should happen before the backoffMultipler should kick-in." }, + "backoffIdleThreshold": { "index": 17, "kind": "parameter", "displayName": "Backoff Idle Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent idle polls that should happen before the backoffMultipler should kick-in." }, + "backoffMultiplier": { "index": 18, "kind": "parameter", "displayName": "Backoff Multiplier", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "To let the scheduled polling consumer backoff if there has been a number of subsequent idles\/errors in a row. The multiplier is then the number of polls that will be skipped before the next actual attempt is happening again. When this option is in use then backoffIdleThreshold and\/or backoffErrorThreshold must also be configured." }, + "delay": { "index": 19, "kind": "parameter", "displayName": "Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 500, "description": "Milliseconds before the next poll." }, + "greedy": { "index": 20, "kind": "parameter", "displayName": "Greedy", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If greedy is enabled, then the ScheduledPollConsumer will run immediately again, if the previous run polled 1 or more messages." }, + "initialDelay": { "index": 21, "kind": "parameter", "displayName": "Initial Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "Milliseconds before the first poll starts." }, + "repeatCount": { "index": 22, "kind": "parameter", "displayName": "Repeat Count", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "Specifies a maximum limit of number of fires. So if you set it to 1, the scheduler will only fire once. If you set it to 5, it will only fire five times. A value of zero or negative means fire forever." }, + "runLoggingLevel": { "index": 23, "kind": "parameter", "displayName": "Run Logging Level", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "enum", "javaType": "org.apache.camel.LoggingLevel", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "TRACE", "description": "The consumer logs a start\/complete log line when it polls. This option allows you to configure the logging level for that." }, + "scheduledExecutorService": { "index": 24, "kind": "parameter", "displayName": "Scheduled Executor Service", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.concurrent.ScheduledExecutorService", "deprecated": false, "autowired": false, "secret": false, "description": "Allows for configuring a custom\/shared thread pool to use for the consumer. By default each consumer has its own single threaded thread pool." }, + "scheduler": { "index": 25, "kind": "parameter", "displayName": "Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.lang.Object", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "none", "description": "To use a cron scheduler from either camel-spring or camel-quartz component. Use value spring or quartz for built in scheduler" }, + "schedulerProperties": { "index": 26, "kind": "parameter", "displayName": "Scheduler Properties", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.Map", "prefix": "scheduler.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "To configure additional properties when using a custom scheduler or any of the Quartz, Spring based scheduler. This is a multi-value option with prefix: scheduler." }, + "startScheduler": { "index": 27, "kind": "parameter", "displayName": "Start Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether the scheduler should be auto started." }, + "timeUnit": { "index": 28, "kind": "parameter", "displayName": "Time Unit", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "enum", "javaType": "java.util.concurrent.TimeUnit", "enum": [ "NANOSECONDS", "MICROSECONDS", "MILLISECONDS", "SECONDS", "MINUTES", "HOURS", "DAYS" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "MILLISECONDS", "description": "Time unit for initialDelay and delay options." }, + "useFixedDelay": { "index": 29, "kind": "parameter", "displayName": "Use Fixed Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in JDK for details." }, + "accessKey": { "index": 30, "kind": "parameter", "displayName": "API access key (AK)", "group": "security", "label": "security", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": true, "security": "secret", "description": "Access key for the cloud user" }, + "secretKey": { "index": 31, "kind": "parameter", "displayName": "API secret key (SK)", "group": "security", "label": "security", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": true, "security": "secret", "description": "Secret key for the cloud user" }, + "serviceKeys": { "index": 32, "kind": "parameter", "displayName": "Service Configuration", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.component.alibaba.common.models.ServiceKeys", "deprecated": false, "autowired": false, "secret": true, "security": "secret", "description": "Configuration object for cloud service authentication" } + } +} diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs.properties b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs.properties index 03163011cb014..f1afa700fe0ea 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs.properties +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs.properties @@ -7,6 +7,8 @@ activemq6-component aggregate-eip ai-patterns ai-tool-component +alibaba-mns-component +alibaba-oss-component amqp-component arangodb-component as2-component diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/alibaba-mns-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/alibaba-mns-component.adoc new file mode 100644 index 0000000000000..5b57281d823c3 --- /dev/null +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/alibaba-mns-component.adoc @@ -0,0 +1,124 @@ += Alibaba Message Service (MNS) Component +:doctitle: Alibaba Message Service (MNS) +:shortname: alibaba-mns +:artifactid: camel-alibaba-mns +:description: Send and receive messages to/from Alibaba Cloud Message Service (MNS). +:since: 4.22 +:supportlevel: Preview +:tabs-sync-option: +:component-header: Both producer and consumer are supported +//Manually maintained attributes +:group: Alibaba Cloud + +*Since Camel {since}* + +*{component-header}* + +The Alibaba Cloud Message Service (MNS) component allows you to integrate with +https://www.alibabacloud.com/product/mns[Alibaba Cloud MNS] for queue and topic messaging. + +Maven users will need to add the following dependency to their `pom.xml` +for this component: + +[source,xml] +---- + + org.apache.camel + camel-alibaba-mns + x.x.x + + +---- + +== URI format + +Queue endpoints: + +[source] +---- +alibaba-mns:queueName[?options] +---- + +Topic endpoints: + +[source] +---- +alibaba-mns:topic:topicName[?options] +---- + +// component options: START +include::partial$component-configure-options.adoc[] +include::partial$component-endpoint-options.adoc[] +include::partial$component-endpoint-headers.adoc[] +// component options: END + +== Usage + +=== Operations + +The component supports the following operations: + +* `sendMessage` - send a message to a queue (producer) +* `receiveMessage` - receive messages from a queue (consumer) +* `deleteMessage` - delete a message from a queue using its receipt handle (producer) +* `publishMessage` - publish a message to a topic (producer) + +=== Queue producer example + +[source,java] +---- +from("direct:start") + .setBody(constant("Hello MNS")) + .to("alibaba-mns:myQueue?operation=sendMessage®ion=cn-hangzhou&accountEndpoint=https://123456.mns.cn-hangzhou.aliyuncs.com&accessKey=RAW(accessKey)&secretKey=RAW(secretKey)"); +---- + +=== Topic producer example + +[source,java] +---- +from("direct:start") + .setBody(constant("Hello Topic")) + .to("alibaba-mns:topic:myTopic?operation=publishMessage®ion=cn-hangzhou&accountEndpoint=https://123456.mns.cn-hangzhou.aliyuncs.com&accessKey=RAW(accessKey)&secretKey=RAW(secretKey)"); +---- + +=== Queue consumer example + +[source,java] +---- +from("alibaba-mns:myQueue?region=cn-hangzhou&accountEndpoint=https://123456.mns.cn-hangzhou.aliyuncs.com&accessKey=RAW(accessKey)&secretKey=RAW(secretKey)&deleteAfterRead=true") + .to("bean:processMessage"); +---- + +=== Exchange properties evaluated by the producer + +[width="100%",cols="10%,10%,80%",options="header",] +|======================================================================= +|Property |Type |Description + +|`CamelAlibabaMnsOperation` |`String` |Operation to perform + +|`CamelAlibabaMnsQueueName` |`String` |Queue name override + +|`CamelAlibabaMnsTopicName` |`String` |Topic name for publish operations + +|`CamelAlibabaMnsReceiptHandle` |`String` |Receipt handle for delete operations + +|======================================================================= + +=== Exchange properties set by the producer + +[width="100%",cols="10%,10%,80%",options="header",] +|======================================================================= +|Property |Type |Description + +|`CamelAlibabaMnsMessageId` |`String` |Message id returned by MNS + +|`CamelAlibabaMnsRequestId` |`String` |Request id returned by MNS + +|`CamelAlibabaMnsMessageBodyMd5` |`String` |MD5 digest of the message body + +|======================================================================= + +== Examples + +For more examples, see the unit tests in the `camel-alibaba-mns` module. diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/alibaba-oss-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/alibaba-oss-component.adoc new file mode 100644 index 0000000000000..97891f33c6375 --- /dev/null +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/alibaba-oss-component.adoc @@ -0,0 +1,102 @@ += Alibaba Object Storage Service (OSS) Component +:doctitle: Alibaba Object Storage Service (OSS) +:shortname: alibaba-oss +:artifactid: camel-alibaba-oss +:description: Alibaba Cloud Object Storage Service (OSS) component +:since: 4.22 +:supportlevel: Preview +:tabs-sync-option: +:component-header: Both producer and consumer are supported +//Manually maintained attributes +:group: Alibaba Cloud + +*Since Camel {since}* + +*{component-header}* + +The Alibaba Cloud Object Storage Service (OSS) component allows you to integrate with https://www.alibabacloud.com/product/object-storage-service[Alibaba Cloud OSS]. + +Maven users will need to add the following dependency to their `pom.xml` for this component: + +[source,xml] +---- + + org.apache.camel + camel-alibaba-oss + x.x.x + + +---- + +== URI Format + +---- +alibaba-oss:operation[?options] +---- + +// component options: START +include::partial$component-configure-options.adoc[] +include::partial$component-endpoint-options.adoc[] +include::partial$component-endpoint-headers.adoc[] +// component options: END + +== Usage + +=== Message properties evaluated by the OSS producer + +[width="100%",cols="10%,10%,80%",options="header",] +|======================================================================= +|Header |Type |Description + +|`CamelAlibabaOssOperation` |`String` | Name of operation to invoke + +|`CamelAlibabaOssBucketName` |`String` | Bucket name to invoke operation on + +|`CamelAlibabaOssObjectName` |`String` | Name of the object to be used in operation + +|`CamelAlibabaOssSourceBucketName` |`String` | Source bucket name for copy operations + +|`CamelAlibabaOssSourceObjectName` |`String` | Source object name for copy operations + +|`CamelAlibabaOssPrefix` |`String` | Prefix filter when listing objects + +|`CamelAlibabaOssMaxKeys` |`Integer` | Maximum number of keys returned when listing objects + +|======================================================================= + +If any of the above properties are set, they will override their corresponding query parameter. + +=== List of Supported OSS Operations + +- listBuckets +- listObjects - `bucketName` parameter is *required* +- putObject - `bucketName` and `objectName` parameters are *required* (unless uploading a `File`) +- getObject - `bucketName` and `objectName` parameters are *required* +- deleteObject - `bucketName` and `objectName` parameters are *required* +- copyObject - source and destination bucket/object names are *required* +- headObject - `bucketName` and `objectName` parameters are *required* + +=== Consumer + +The consumer polls objects from a bucket using `listObjectsV2`, downloads each object body, and optionally deletes objects after they have been processed when `deleteAfterRead` is enabled. + +== Examples + +=== Put an object + +[source,java] +---- +from("direct:start") + .setBody(constant("Hello OSS")) + .setProperty("CamelAlibabaOssBucketName", constant("my-bucket")) + .setProperty("CamelAlibabaOssObjectName", constant("hello.txt")) + .to("alibaba-oss:putObject?region=cn-hangzhou&accessKey=xxx&secretKey=yyy"); +---- + +=== Consume objects from a bucket + +[source,java] +---- +from("alibaba-oss:consumer?bucketName=my-bucket®ion=cn-hangzhou&accessKey=xxx&secretKey=yyy&deleteAfterRead=true") + .to("log:output"); +---- diff --git a/components/camel-alibaba/camel-alibaba-mns/src/main/docs/alibaba-mns-component.adoc b/components/camel-alibaba/camel-alibaba-mns/src/main/docs/alibaba-mns-component.adoc index 1567e661cad22..5b57281d823c3 100644 --- a/components/camel-alibaba/camel-alibaba-mns/src/main/docs/alibaba-mns-component.adoc +++ b/components/camel-alibaba/camel-alibaba-mns/src/main/docs/alibaba-mns-component.adoc @@ -119,29 +119,6 @@ from("alibaba-mns:myQueue?region=cn-hangzhou&accountEndpoint=https://123456.mns. |======================================================================= -== Spring Boot auto-configuration - -When using `alibaba-mns` with Spring Boot, add the following dependency: - -[source,xml] ----- - - org.apache.camel.springboot - camel-alibaba-mns-starter - x.x.x - - ----- - -The component supports 0 options, which are listed below. - -include::partial$starter-configure-options.adoc[] - -== Spring Boot Auto-Configuration - -When using Spring Boot, the component is auto-configured. Refer to the -xref:manual::spring-boot.adoc[Spring Boot documentation] for more details. - == Examples For more examples, see the unit tests in the `camel-alibaba-mns` module. diff --git a/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSEndpoint.java b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSEndpoint.java index 107956840d9e3..de75060f1d3d9 100644 --- a/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSEndpoint.java +++ b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSEndpoint.java @@ -227,6 +227,13 @@ public String resolveOperation() { if (topicEndpoint) { return MNSOperations.PUBLISH_MESSAGE; } + return MNSOperations.SEND_MESSAGE; + } + + public String resolveConsumerOperation() { + if (operation != null) { + return operation; + } return MNSOperations.RECEIVE_MESSAGE; } diff --git a/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/SendMessageDefaultOperationTest.java b/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/SendMessageDefaultOperationTest.java new file mode 100644 index 0000000000000..cbcb7980efd21 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/SendMessageDefaultOperationTest.java @@ -0,0 +1,75 @@ +/* + * 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.alibaba.mns; + +import com.aliyun.mns.client.CloudQueue; +import com.aliyun.mns.client.MNSClient; +import com.aliyun.mns.model.Message; +import org.apache.camel.BindToRegistry; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.junit6.CamelTestSupport; +import org.junit.jupiter.api.Test; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +class SendMessageDefaultOperationTest extends CamelTestSupport { + + private final TestConfiguration testConfiguration = new TestConfiguration(); + + @BindToRegistry("mnsClient") + MNSClient mnsClient = mock(MNSClient.class); + + CloudQueue cloudQueue = mock(CloudQueue.class); + + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + from("direct:send") + .to("alibaba-mns:" + testConfiguration.getProperty("queue") + + "?region=" + testConfiguration.getProperty("region") + + "&accountEndpoint=" + testConfiguration.getProperty("accountEndpoint") + + "&accessKey=" + testConfiguration.getProperty("accessKey") + + "&secretKey=" + testConfiguration.getProperty("secretKey") + + "&mnsClient=#mnsClient") + .to("mock:result"); + } + }; + } + + @Test + void queueProducerDefaultsToSendMessage() throws Exception { + Message response = new Message("response"); + response.setMessageId("message-id-default"); + + when(mnsClient.getQueueRef(testConfiguration.getProperty("queue"))).thenReturn(cloudQueue); + when(cloudQueue.putMessage(any(Message.class))).thenReturn(response); + + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMinimumMessageCount(1); + + template.sendBody("direct:send", "hello mns"); + + mock.assertIsSatisfied(); + verify(cloudQueue).putMessage(any(Message.class)); + } +} diff --git a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSConsumer.java b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSConsumer.java index 4398e88a3fc6a..4c285604ead4c 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSConsumer.java +++ b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSConsumer.java @@ -88,14 +88,17 @@ protected int poll() throws Exception { forceConsumerAsReady(); + String nextToken = null; if (Boolean.TRUE.equals(listing.isTruncated()) && listing.nextContinuationToken() != null) { - continuationToken = listing.nextContinuationToken(); - } else { - continuationToken = null; + nextToken = listing.nextContinuationToken(); } Queue exchanges = createExchanges(bucketName, listing.contents()); - return processBatch(CastUtils.cast(exchanges)); + int processed = processBatch(CastUtils.cast(exchanges)); + if (processed >= 0) { + continuationToken = nextToken; + } + return processed; } @Override diff --git a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSProducer.java b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSProducer.java index dc16b2c4fbbad..555e7fa851b85 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSProducer.java +++ b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSProducer.java @@ -111,13 +111,16 @@ public void process(Exchange exchange) throws Exception { private void putObject(Exchange exchange, ClientConfigurations clientConfigurations) throws Exception { Object body = exchange.getMessage().getBody(); + if (ObjectHelper.isEmpty(clientConfigurations.getBucketName())) { + throw new IllegalArgumentException("Bucket name is mandatory to put objects into bucket"); + } + if (body instanceof WrappedFile wf) { body = wf.getFile(); } - if ((ObjectHelper.isEmpty(clientConfigurations.getBucketName()) - || ObjectHelper.isEmpty(clientConfigurations.getObjectName())) && !(body instanceof File)) { - throw new IllegalArgumentException("Bucket and object names are mandatory to put objects into bucket"); + if (ObjectHelper.isEmpty(clientConfigurations.getObjectName()) && !(body instanceof File)) { + throw new IllegalArgumentException("Object name is mandatory when body is not a file"); } PutObjectRequest.Builder requestBuilder = PutObjectRequest.newBuilder() diff --git a/core/camel-main/src/generated/resources/org/apache/camel/main/components.properties b/core/camel-main/src/generated/resources/org/apache/camel/main/components.properties index e8a80790f9c4c..f0cd17702e552 100644 --- a/core/camel-main/src/generated/resources/org/apache/camel/main/components.properties +++ b/core/camel-main/src/generated/resources/org/apache/camel/main/components.properties @@ -2,6 +2,8 @@ a2a activemq activemq6 ai-tool +alibaba-mns +alibaba-oss amqp arangodb as2 From e9b2c99e3fb96886c510e87234b7c8525e6edf6e Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 11 Aug 2026 06:17:58 +0000 Subject: [PATCH 06/12] CAMEL-24373: Address PR review feedback for camel-alibaba phase 1 - Resolve parent/pom.xml merge conflict and keep aws-java-sdk2 2.50.3 - Move OSS client builder from common to OSSUtils in camel-alibaba-oss - Remove unused AlibabaClientRegistry and OSS SDK dependency from common - Cache OSS client on endpoint and close on shutdown when not autowired - Rename OSS content headers to CamelAlibabaOss* convention - Add @Override on OSSComponent.createEndpoint() - Document MNS deprecation guidance in component docs Co-authored-by: Cursor Agent --- .../camel-alibaba-common/pom.xml | 15 ----- .../common/AlibabaClientBuilderUtil.java | 61 ------------------- .../alibaba/common/AlibabaClientRegistry.java | 45 -------------- .../common/AlibabaClientRegistryTest.java | 40 ------------ .../src/main/docs/alibaba-mns-component.adoc | 4 ++ .../component/alibaba/oss/alibaba-oss.json | 4 +- .../component/alibaba/oss/OSSComponent.java | 1 + .../component/alibaba/oss/OSSEndpoint.java | 30 ++++----- .../camel/component/alibaba/oss/OSSUtils.java | 50 +++++++++++++++ .../alibaba/oss/constants/OSSHeaders.java | 4 +- .../component/alibaba/oss/GetObjectTest.java | 4 +- .../component/alibaba/oss/OSSUtilsTest.java} | 39 ++++++++---- parent/pom.xml | 6 ++ 13 files changed, 110 insertions(+), 193 deletions(-) delete mode 100644 components/camel-alibaba/camel-alibaba-common/src/main/java/org/apache/camel/component/alibaba/common/AlibabaClientBuilderUtil.java delete mode 100644 components/camel-alibaba/camel-alibaba-common/src/main/java/org/apache/camel/component/alibaba/common/AlibabaClientRegistry.java delete mode 100644 components/camel-alibaba/camel-alibaba-common/src/test/java/org/apache/camel/component/alibaba/common/AlibabaClientRegistryTest.java rename components/camel-alibaba/{camel-alibaba-common/src/test/java/org/apache/camel/component/alibaba/common/AlibabaClientBuilderUtilTest.java => camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/OSSUtilsTest.java} (55%) diff --git a/components/camel-alibaba/camel-alibaba-common/pom.xml b/components/camel-alibaba/camel-alibaba-common/pom.xml index fcdee7eff3fc3..79633f28c6f3a 100644 --- a/components/camel-alibaba/camel-alibaba-common/pom.xml +++ b/components/camel-alibaba/camel-alibaba-common/pom.xml @@ -41,21 +41,6 @@ org.apache.camel camel-support - - com.aliyun - alibabacloud-oss-v2 - ${alibabacloud-oss-version} - - - org.apache.camel - camel-test-junit6 - test - - - org.assertj - assertj-core - test - diff --git a/components/camel-alibaba/camel-alibaba-common/src/main/java/org/apache/camel/component/alibaba/common/AlibabaClientBuilderUtil.java b/components/camel-alibaba/camel-alibaba-common/src/main/java/org/apache/camel/component/alibaba/common/AlibabaClientBuilderUtil.java deleted file mode 100644 index 6a687b02e4651..0000000000000 --- a/components/camel-alibaba/camel-alibaba-common/src/main/java/org/apache/camel/component/alibaba/common/AlibabaClientBuilderUtil.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.camel.component.alibaba.common; - -import com.aliyun.sdk.service.oss2.OSSClient; -import com.aliyun.sdk.service.oss2.OSSClientBuilder; -import com.aliyun.sdk.service.oss2.credentials.StaticCredentialsProvider; -import org.apache.camel.util.ObjectHelper; - -public final class AlibabaClientBuilderUtil { - - private AlibabaClientBuilderUtil() { - } - - /** - * Create an OSS client using static credentials. - * - * @param accessKey access key id - * @param secretKey secret access key - * @param region OSS region - * @param endpoint optional custom endpoint - * @return configured OSS client - */ - public static OSSClient createOssClient(String accessKey, String secretKey, String region, String endpoint) { - if (ObjectHelper.isEmpty(accessKey)) { - throw new IllegalArgumentException("Authentication parameter 'access key (AK)' not found"); - } - if (ObjectHelper.isEmpty(secretKey)) { - throw new IllegalArgumentException("Authentication parameter 'secret key (SK)' not found"); - } - if (ObjectHelper.isEmpty(region) && ObjectHelper.isEmpty(endpoint)) { - throw new IllegalArgumentException("Region/endpoint not found"); - } - - OSSClientBuilder clientBuilder = OSSClient.newBuilder() - .credentialsProvider(new StaticCredentialsProvider(accessKey, secretKey)); - - if (ObjectHelper.isNotEmpty(region)) { - clientBuilder.region(region); - } - if (ObjectHelper.isNotEmpty(endpoint)) { - clientBuilder.endpoint(endpoint); - } - - return clientBuilder.build(); - } -} diff --git a/components/camel-alibaba/camel-alibaba-common/src/main/java/org/apache/camel/component/alibaba/common/AlibabaClientRegistry.java b/components/camel-alibaba/camel-alibaba-common/src/main/java/org/apache/camel/component/alibaba/common/AlibabaClientRegistry.java deleted file mode 100644 index 35f1b6c0e9552..0000000000000 --- a/components/camel-alibaba/camel-alibaba-common/src/main/java/org/apache/camel/component/alibaba/common/AlibabaClientRegistry.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.camel.component.alibaba.common; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Supplier; - -/** - * Simple client registry for reusing Alibaba Cloud SDK clients within a Camel context. - */ -public final class AlibabaClientRegistry { - - private final Map clients = new ConcurrentHashMap<>(); - - public T getOrCreate(String key, Supplier supplier) { - Object existing = clients.get(key); - if (existing != null) { - @SuppressWarnings("unchecked") - T client = (T) existing; - return client; - } - T created = supplier.get(); - clients.put(key, created); - return created; - } - - public void clear() { - clients.clear(); - } -} diff --git a/components/camel-alibaba/camel-alibaba-common/src/test/java/org/apache/camel/component/alibaba/common/AlibabaClientRegistryTest.java b/components/camel-alibaba/camel-alibaba-common/src/test/java/org/apache/camel/component/alibaba/common/AlibabaClientRegistryTest.java deleted file mode 100644 index 4f8a74661efdc..0000000000000 --- a/components/camel-alibaba/camel-alibaba-common/src/test/java/org/apache/camel/component/alibaba/common/AlibabaClientRegistryTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.camel.component.alibaba.common; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -class AlibabaClientRegistryTest { - - @Test - void reusesClientForSameKey() { - AlibabaClientRegistry registry = new AlibabaClientRegistry(); - Object first = registry.getOrCreate("oss:ak:region", () -> new Object()); - Object second = registry.getOrCreate("oss:ak:region", () -> new Object()); - assertThat(second).isSameAs(first); - } - - @Test - void createsDistinctClientsForDifferentKeys() { - AlibabaClientRegistry registry = new AlibabaClientRegistry(); - Object first = registry.getOrCreate("oss:ak:cn-hangzhou", () -> new Object()); - Object second = registry.getOrCreate("oss:ak:cn-beijing", () -> new Object()); - assertThat(second).isNotSameAs(first); - } -} diff --git a/components/camel-alibaba/camel-alibaba-mns/src/main/docs/alibaba-mns-component.adoc b/components/camel-alibaba/camel-alibaba-mns/src/main/docs/alibaba-mns-component.adoc index 5b57281d823c3..9e5b0e00dbf50 100644 --- a/components/camel-alibaba/camel-alibaba-mns/src/main/docs/alibaba-mns-component.adoc +++ b/components/camel-alibaba/camel-alibaba-mns/src/main/docs/alibaba-mns-component.adoc @@ -17,6 +17,10 @@ The Alibaba Cloud Message Service (MNS) component allows you to integrate with https://www.alibabacloud.com/product/mns[Alibaba Cloud MNS] for queue and topic messaging. +NOTE: Alibaba Cloud recommends RocketMQ for new messaging workloads. MNS remains supported, +but evaluate https://www.alibabacloud.com/product/rocketmq[RocketMQ] or the Camel RocketMQ +component for greenfield projects. + Maven users will need to add the following dependency to their `pom.xml` for this component: diff --git a/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/org/apache/camel/component/alibaba/oss/alibaba-oss.json b/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/org/apache/camel/component/alibaba/oss/alibaba-oss.json index de6f70f530bfb..8b945a5510b45 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/org/apache/camel/component/alibaba/oss/alibaba-oss.json +++ b/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/org/apache/camel/component/alibaba/oss/alibaba-oss.json @@ -37,8 +37,8 @@ "CamelAlibabaOssETag": { "index": 3, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The 128-bit MD5 digest of the object content", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#ETAG" }, "CamelAlibabaOssContentMD5": { "index": 4, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The 128-bit Base64-encoded digest of the object", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#CONTENT_MD5" }, "CamelAlibabaOssObjectType": { "index": 5, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Shows whether the object is a file or a folder", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#OBJECT_TYPE" }, - "Content-Length": { "index": 6, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The size of the object body in bytes", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#CONTENT_LENGTH" }, - "Content-Type": { "index": 7, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The type of content stored in the object", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#CONTENT_TYPE" }, + "CamelAlibabaOssContentLength": { "index": 6, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The size of the object body in bytes", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#CONTENT_LENGTH" }, + "CamelAlibabaOssContentType": { "index": 7, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The type of content stored in the object", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#CONTENT_TYPE" }, "CamelFileName": { "index": 8, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the object with which the operation is to be performed", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#FILE_NAME" } }, "properties": { diff --git a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSComponent.java b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSComponent.java index da092c20673d3..b35b35ecd14b3 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSComponent.java +++ b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSComponent.java @@ -25,6 +25,7 @@ @Component("alibaba-oss") public class OSSComponent extends HealthCheckComponent { + @Override protected Endpoint createEndpoint(String uri, String remaining, Map parameters) throws Exception { Endpoint endpoint = new OSSEndpoint(uri, remaining, this); setProperties(endpoint, parameters); diff --git a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSEndpoint.java b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSEndpoint.java index d025027ff89f4..9fc9820b8ff57 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSEndpoint.java +++ b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSEndpoint.java @@ -21,7 +21,6 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; -import org.apache.camel.component.alibaba.common.AlibabaClientBuilderUtil; import org.apache.camel.component.alibaba.common.models.ServiceKeys; import org.apache.camel.component.alibaba.oss.constants.OSSHeaders; import org.apache.camel.spi.Metadata; @@ -29,7 +28,6 @@ import org.apache.camel.spi.UriParam; import org.apache.camel.spi.UriPath; import org.apache.camel.support.ScheduledPollEndpoint; -import org.apache.camel.util.ObjectHelper; /** * Alibaba Cloud Object Storage Service (OSS) component @@ -91,6 +89,8 @@ public class OSSEndpoint extends ScheduledPollEndpoint { @Metadata(autowired = true) private OSSClient ossClient; + private boolean autowiredOssClient; + public OSSEndpoint() { } @@ -99,10 +99,12 @@ public OSSEndpoint(String uri, String operation, OSSComponent component) { this.operation = operation; } + @Override public Producer createProducer() throws Exception { return new OSSProducer(this); } + @Override public Consumer createConsumer(Processor processor) throws Exception { OSSConsumer consumer = new OSSConsumer(this, processor); configureConsumer(consumer); @@ -118,20 +120,17 @@ public OSSClient initClient() { return ossClient; } - if (ObjectHelper.isEmpty(getServiceKeys()) && ObjectHelper.isEmpty(getAccessKey())) { - throw new IllegalArgumentException("Authentication parameter 'access key (AK)' not found"); - } - if (ObjectHelper.isEmpty(getServiceKeys()) && ObjectHelper.isEmpty(getSecretKey())) { - throw new IllegalArgumentException("Authentication parameter 'secret key (SK)' not found"); - } - if (ObjectHelper.isEmpty(getRegion()) && ObjectHelper.isEmpty(getEndpoint())) { - throw new IllegalArgumentException("Region/endpoint not found"); - } - - String auth = getServiceKeys() != null ? getServiceKeys().getAccessKey() : getAccessKey(); - String secret = getServiceKeys() != null ? getServiceKeys().getSecretKey() : getSecretKey(); + ossClient = OSSUtils.createClient(this); + return ossClient; + } - return AlibabaClientBuilderUtil.createOssClient(auth, secret, region, endpoint); + @Override + protected void doStop() throws Exception { + if (ossClient != null && !autowiredOssClient) { + ossClient.close(); + ossClient = null; + } + super.doStop(); } public String getOperation() { @@ -236,5 +235,6 @@ public OSSClient getOssClient() { public void setOssClient(OSSClient ossClient) { this.ossClient = ossClient; + this.autowiredOssClient = ossClient != null; } } diff --git a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSUtils.java b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSUtils.java index 81b2981834bc1..3846c2a05a7b6 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSUtils.java +++ b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSUtils.java @@ -19,13 +19,18 @@ import java.io.IOException; import java.io.InputStream; +import com.aliyun.sdk.service.oss2.OSSClient; +import com.aliyun.sdk.service.oss2.OSSClientBuilder; +import com.aliyun.sdk.service.oss2.credentials.StaticCredentialsProvider; import com.aliyun.sdk.service.oss2.models.GetObjectResult; import com.aliyun.sdk.service.oss2.utils.IOUtils; import org.apache.camel.Exchange; import org.apache.camel.Message; import org.apache.camel.RuntimeCamelException; +import org.apache.camel.component.alibaba.common.models.ServiceKeys; import org.apache.camel.component.alibaba.oss.constants.OSSConstants; import org.apache.camel.component.alibaba.oss.constants.OSSHeaders; +import org.apache.camel.util.ObjectHelper; public final class OSSUtils { private OSSUtils() { @@ -83,4 +88,49 @@ public static void mapOssObject( public static RuntimeCamelException wrapIOException(IOException e) { return new RuntimeCamelException(e); } + + public static OSSClient createClient(OSSEndpoint endpoint) { + String accessKey = resolveAccessKey(endpoint); + String secretKey = resolveSecretKey(endpoint); + String region = endpoint.getRegion(); + String endpointUrl = endpoint.getEndpoint(); + + if (ObjectHelper.isEmpty(region) && ObjectHelper.isEmpty(endpointUrl)) { + throw new IllegalArgumentException("Region/endpoint not found"); + } + + OSSClientBuilder clientBuilder = OSSClient.newBuilder() + .credentialsProvider(new StaticCredentialsProvider(accessKey, secretKey)); + + if (ObjectHelper.isNotEmpty(region)) { + clientBuilder.region(region); + } + if (ObjectHelper.isNotEmpty(endpointUrl)) { + clientBuilder.endpoint(endpointUrl); + } + + return clientBuilder.build(); + } + + private static String resolveAccessKey(OSSEndpoint endpoint) { + ServiceKeys serviceKeys = endpoint.getServiceKeys(); + if (serviceKeys != null) { + return serviceKeys.getAccessKey(); + } + if (ObjectHelper.isEmpty(endpoint.getAccessKey())) { + throw new IllegalArgumentException("Authentication parameter 'access key (AK)' not found"); + } + return endpoint.getAccessKey(); + } + + private static String resolveSecretKey(OSSEndpoint endpoint) { + ServiceKeys serviceKeys = endpoint.getServiceKeys(); + if (serviceKeys != null) { + return serviceKeys.getSecretKey(); + } + if (ObjectHelper.isEmpty(endpoint.getSecretKey())) { + throw new IllegalArgumentException("Authentication parameter 'secret key (SK)' not found"); + } + return endpoint.getSecretKey(); + } } diff --git a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/constants/OSSHeaders.java b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/constants/OSSHeaders.java index dbb1753dec93a..ff74e1ece27ce 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/constants/OSSHeaders.java +++ b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/constants/OSSHeaders.java @@ -36,9 +36,9 @@ public final class OSSHeaders { @Metadata(label = "consumer", description = "Shows whether the object is a `file` or a `folder`", javaType = "String") public static final String OBJECT_TYPE = "CamelAlibabaOssObjectType"; @Metadata(label = "consumer", description = "The size of the object body in bytes", javaType = "Long") - public static final String CONTENT_LENGTH = Exchange.CONTENT_LENGTH; + public static final String CONTENT_LENGTH = "CamelAlibabaOssContentLength"; @Metadata(label = "consumer", description = "The type of content stored in the object", javaType = "String") - public static final String CONTENT_TYPE = Exchange.CONTENT_TYPE; + public static final String CONTENT_TYPE = "CamelAlibabaOssContentType"; @Metadata(label = "consumer", description = "Name of the object with which the operation is to be performed", javaType = "String") public static final String FILE_NAME = Exchange.FILE_NAME; diff --git a/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/GetObjectTest.java b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/GetObjectTest.java index 532fe1906d638..dd75099c6028b 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/GetObjectTest.java +++ b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/GetObjectTest.java @@ -88,8 +88,8 @@ void testGetObject() throws Exception { mock.assertIsSatisfied(); - assertThat(responseExchange.getIn().getHeader(Exchange.CONTENT_LENGTH)).isEqualTo(9L); - assertThat(responseExchange.getIn().getHeader(Exchange.CONTENT_TYPE)).isEqualTo("text/plain"); + assertThat(responseExchange.getIn().getHeader(OSSHeaders.CONTENT_LENGTH)).isEqualTo(9L); + assertThat(responseExchange.getIn().getHeader(OSSHeaders.CONTENT_TYPE)).isEqualTo("text/plain"); assertThat(responseExchange.getIn().getHeader(OSSHeaders.ETAG)).isEqualTo("eb733a00c0c9d336e65691a37ab54293"); assertThat(responseExchange.getIn().getHeader(OSSHeaders.CONTENT_MD5)).isEqualTo("63M6AMDJ0zbmVpGjerVCkw=="); assertThat(responseExchange.getIn().getHeader(OSSHeaders.LAST_MODIFIED)).isEqualTo("2024-01-01T00:00:00Z"); diff --git a/components/camel-alibaba/camel-alibaba-common/src/test/java/org/apache/camel/component/alibaba/common/AlibabaClientBuilderUtilTest.java b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/OSSUtilsTest.java similarity index 55% rename from components/camel-alibaba/camel-alibaba-common/src/test/java/org/apache/camel/component/alibaba/common/AlibabaClientBuilderUtilTest.java rename to components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/OSSUtilsTest.java index 7e7a7255b84c0..0e0a0b3c4b9eb 100644 --- a/components/camel-alibaba/camel-alibaba-common/src/test/java/org/apache/camel/component/alibaba/common/AlibabaClientBuilderUtilTest.java +++ b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/OSSUtilsTest.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.component.alibaba.common; +package org.apache.camel.component.alibaba.oss; import com.aliyun.sdk.service.oss2.OSSClient; import org.junit.jupiter.api.Test; @@ -22,33 +22,50 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -class AlibabaClientBuilderUtilTest { +class OSSUtilsTest { @Test - void createOssClientWithRegion() throws Exception { - try (OSSClient client = AlibabaClientBuilderUtil.createOssClient("ak", "sk", "cn-hangzhou", null)) { + void createClientWithRegion() throws Exception { + OSSEndpoint endpoint = new OSSEndpoint(); + endpoint.setAccessKey("ak"); + endpoint.setSecretKey("sk"); + endpoint.setRegion("cn-hangzhou"); + + try (OSSClient client = OSSUtils.createClient(endpoint)) { assertThat(client).isNotNull(); } } @Test - void createOssClientWithEndpoint() throws Exception { - try (OSSClient client = AlibabaClientBuilderUtil.createOssClient("ak", "sk", null, - "https://oss-cn-hangzhou.aliyuncs.com")) { + void createClientWithEndpoint() throws Exception { + OSSEndpoint endpoint = new OSSEndpoint(); + endpoint.setAccessKey("ak"); + endpoint.setSecretKey("sk"); + endpoint.setEndpoint("https://oss-cn-hangzhou.aliyuncs.com"); + + try (OSSClient client = OSSUtils.createClient(endpoint)) { assertThat(client).isNotNull(); } } @Test - void createOssClientMissingAccessKey() { - assertThatThrownBy(() -> AlibabaClientBuilderUtil.createOssClient(null, "sk", "cn-hangzhou", null)) + void createClientMissingAccessKey() { + OSSEndpoint endpoint = new OSSEndpoint(); + endpoint.setSecretKey("sk"); + endpoint.setRegion("cn-hangzhou"); + + assertThatThrownBy(() -> OSSUtils.createClient(endpoint)) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("access key"); } @Test - void createOssClientMissingRegionAndEndpoint() { - assertThatThrownBy(() -> AlibabaClientBuilderUtil.createOssClient("ak", "sk", null, null)) + void createClientMissingRegionAndEndpoint() { + OSSEndpoint endpoint = new OSSEndpoint(); + endpoint.setAccessKey("ak"); + endpoint.setSecretKey("sk"); + + assertThatThrownBy(() -> OSSUtils.createClient(endpoint)) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("Region/endpoint"); } diff --git a/parent/pom.xml b/parent/pom.xml index a9eb89f61577b..e6aa11ac61dff 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -82,7 +82,13 @@ 1.12.1 1.12.1 4.3.0 +<<<<<<< HEAD 2.51.3 +======= + 0.4.1 + 2.0.0 + 2.50.3 +>>>>>>> da84d76e898 (CAMEL-24373: Address PR review feedback for camel-alibaba phase 1) 1.3.3 12.0.0-beta.39 3.2.1 From f9fdef7fab3abda12f849bbf0ab0bb80a32de331 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 11 Aug 2026 06:21:52 +0000 Subject: [PATCH 07/12] CAMEL-24373: Regenerate catalog after OSS header and MNS doc updates Co-authored-by: Cursor Agent --- .../org/apache/camel/catalog/components/alibaba-oss.json | 4 ++-- .../org/apache/camel/catalog/docs/alibaba-mns-component.adoc | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-oss.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-oss.json index de6f70f530bfb..8b945a5510b45 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-oss.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-oss.json @@ -37,8 +37,8 @@ "CamelAlibabaOssETag": { "index": 3, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The 128-bit MD5 digest of the object content", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#ETAG" }, "CamelAlibabaOssContentMD5": { "index": 4, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The 128-bit Base64-encoded digest of the object", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#CONTENT_MD5" }, "CamelAlibabaOssObjectType": { "index": 5, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Shows whether the object is a file or a folder", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#OBJECT_TYPE" }, - "Content-Length": { "index": 6, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The size of the object body in bytes", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#CONTENT_LENGTH" }, - "Content-Type": { "index": 7, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The type of content stored in the object", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#CONTENT_TYPE" }, + "CamelAlibabaOssContentLength": { "index": 6, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The size of the object body in bytes", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#CONTENT_LENGTH" }, + "CamelAlibabaOssContentType": { "index": 7, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The type of content stored in the object", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#CONTENT_TYPE" }, "CamelFileName": { "index": 8, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the object with which the operation is to be performed", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#FILE_NAME" } }, "properties": { diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/alibaba-mns-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/alibaba-mns-component.adoc index 5b57281d823c3..9e5b0e00dbf50 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/alibaba-mns-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/alibaba-mns-component.adoc @@ -17,6 +17,10 @@ The Alibaba Cloud Message Service (MNS) component allows you to integrate with https://www.alibabacloud.com/product/mns[Alibaba Cloud MNS] for queue and topic messaging. +NOTE: Alibaba Cloud recommends RocketMQ for new messaging workloads. MNS remains supported, +but evaluate https://www.alibabacloud.com/product/rocketmq[RocketMQ] or the Camel RocketMQ +component for greenfield projects. + Maven users will need to add the following dependency to their `pom.xml` for this component: From f291010c411607c457d4ffe9f6e14878012fc155 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 11 Aug 2026 06:30:57 +0000 Subject: [PATCH 08/12] CAMEL-24373: Fix credential resolution, listObjects cap, and MNS client lifecycle - Prefer endpoint accessKey/secretKey over empty ServiceKeys bean (OSS) - Cap listObjects results at maxKeys instead of scanning entire bucket - Close MNS client on endpoint stop when not autowired Co-authored-by: Cursor Agent --- .../component/alibaba/mns/MNSEndpoint.java | 12 +++++++++++ .../component/alibaba/oss/OSSProducer.java | 9 +++++++++ .../camel/component/alibaba/oss/OSSUtils.java | 20 +++++++++---------- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSEndpoint.java b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSEndpoint.java index de75060f1d3d9..772fe2d165f5c 100644 --- a/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSEndpoint.java +++ b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSEndpoint.java @@ -84,6 +84,8 @@ public class MNSEndpoint extends ScheduledPollEndpoint { @Metadata(autowired = true) private MNSClient mnsClient; + private boolean autowiredMnsClient; + private boolean topicEndpoint; public MNSEndpoint() { @@ -116,6 +118,15 @@ public void initClient() { mnsClient = MNSUtils.createClient(this); } + @Override + protected void doStop() throws Exception { + if (mnsClient != null && !autowiredMnsClient) { + mnsClient.close(); + mnsClient = null; + } + super.doStop(); + } + public boolean isTopicEndpoint() { return topicEndpoint; } @@ -218,6 +229,7 @@ public MNSClient getMnsClient() { public void setMnsClient(MNSClient mnsClient) { this.mnsClient = mnsClient; + this.autowiredMnsClient = mnsClient != null; } public String resolveOperation() { diff --git a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSProducer.java b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSProducer.java index 555e7fa851b85..4f7b1bd78d0b5 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSProducer.java +++ b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSProducer.java @@ -223,10 +223,16 @@ private void listObjects(Exchange exchange, ClientConfigurations clientConfigura List> objects = new ArrayList<>(); ListObjectsResult result; ListObjectsRequest request = requestBuilder.build(); + long maxKeysLimit = clientConfigurations.getMaxKeys() != null + ? clientConfigurations.getMaxKeys().longValue() + : Long.MAX_VALUE; do { result = ossClient.listObjects(request); if (result.contents() != null) { for (ObjectSummary summary : result.contents()) { + if (objects.size() >= maxKeysLimit) { + break; + } Map objectMap = new HashMap<>(); objectMap.put("bucketName", clientConfigurations.getBucketName()); objectMap.put("objectKey", summary.key()); @@ -236,6 +242,9 @@ private void listObjects(Exchange exchange, ClientConfigurations clientConfigura objects.add(objectMap); } } + if (objects.size() >= maxKeysLimit) { + break; + } if (Boolean.TRUE.equals(result.isTruncated()) && result.nextMarker() != null) { request = request.toBuilder().marker(result.nextMarker()).build(); } else { diff --git a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSUtils.java b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSUtils.java index 3846c2a05a7b6..8d96afb404b0f 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSUtils.java +++ b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSUtils.java @@ -113,24 +113,24 @@ public static OSSClient createClient(OSSEndpoint endpoint) { } private static String resolveAccessKey(OSSEndpoint endpoint) { + if (ObjectHelper.isNotEmpty(endpoint.getAccessKey())) { + return endpoint.getAccessKey(); + } ServiceKeys serviceKeys = endpoint.getServiceKeys(); - if (serviceKeys != null) { + if (serviceKeys != null && ObjectHelper.isNotEmpty(serviceKeys.getAccessKey())) { return serviceKeys.getAccessKey(); } - if (ObjectHelper.isEmpty(endpoint.getAccessKey())) { - throw new IllegalArgumentException("Authentication parameter 'access key (AK)' not found"); - } - return endpoint.getAccessKey(); + throw new IllegalArgumentException("Authentication parameter 'access key (AK)' not found"); } private static String resolveSecretKey(OSSEndpoint endpoint) { + if (ObjectHelper.isNotEmpty(endpoint.getSecretKey())) { + return endpoint.getSecretKey(); + } ServiceKeys serviceKeys = endpoint.getServiceKeys(); - if (serviceKeys != null) { + if (serviceKeys != null && ObjectHelper.isNotEmpty(serviceKeys.getSecretKey())) { return serviceKeys.getSecretKey(); } - if (ObjectHelper.isEmpty(endpoint.getSecretKey())) { - throw new IllegalArgumentException("Authentication parameter 'secret key (SK)' not found"); - } - return endpoint.getSecretKey(); + throw new IllegalArgumentException("Authentication parameter 'secret key (SK)' not found"); } } From 619294f9e9065b85666ff7b2bba94c0fb2fe847d Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 11 Aug 2026 06:32:38 +0000 Subject: [PATCH 09/12] CAMEL-24373: Add endpoint lifecycle and credential precedence tests Co-authored-by: Cursor Agent --- .../alibaba/mns/MNSEndpointTest.java | 58 +++++++++++++++ .../alibaba/oss/OSSEndpointTest.java | 71 +++++++++++++++++++ .../component/alibaba/oss/OSSUtilsTest.java | 14 ++++ 3 files changed, 143 insertions(+) create mode 100644 components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/MNSEndpointTest.java create mode 100644 components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/OSSEndpointTest.java diff --git a/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/MNSEndpointTest.java b/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/MNSEndpointTest.java new file mode 100644 index 0000000000000..95dfa7712d097 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/MNSEndpointTest.java @@ -0,0 +1,58 @@ +/* + * 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.alibaba.mns; + +import com.aliyun.mns.client.MNSClient; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +class MNSEndpointTest { + + @Test + void doStopSkipsCloseForAutowiredClient() throws Exception { + MNSEndpoint endpoint = new MNSEndpoint(); + MNSClient client = mock(MNSClient.class); + endpoint.setMnsClient(client); + + endpoint.doStop(); + + verify(client, never()).close(); + } + + @Test + void doStopClosesOwnedClient() throws Exception { + MNSEndpoint endpoint = new MNSEndpoint(); + MNSClient client = mock(MNSClient.class); + + var clientField = MNSEndpoint.class.getDeclaredField("mnsClient"); + clientField.setAccessible(true); + clientField.set(endpoint, client); + + var autowiredField = MNSEndpoint.class.getDeclaredField("autowiredMnsClient"); + autowiredField.setAccessible(true); + autowiredField.setBoolean(endpoint, false); + + endpoint.doStop(); + + verify(client).close(); + assertThat(endpoint.getMnsClient()).isNull(); + } +} diff --git a/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/OSSEndpointTest.java b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/OSSEndpointTest.java new file mode 100644 index 0000000000000..252028abd92f3 --- /dev/null +++ b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/OSSEndpointTest.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.alibaba.oss; + +import com.aliyun.sdk.service.oss2.OSSClient; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +class OSSEndpointTest { + + @Test + void initClientReturnsCachedInstance() { + OSSEndpoint endpoint = new OSSEndpoint(); + endpoint.setAccessKey("ak"); + endpoint.setSecretKey("sk"); + endpoint.setRegion("cn-hangzhou"); + + OSSClient first = endpoint.initClient(); + OSSClient second = endpoint.initClient(); + + assertThat(first).isSameAs(second); + } + + @Test + void doStopSkipsCloseForAutowiredClient() throws Exception { + OSSEndpoint endpoint = new OSSEndpoint(); + OSSClient client = mock(OSSClient.class); + endpoint.setOssClient(client); + + endpoint.doStop(); + + verify(client, never()).close(); + } + + @Test + void doStopClosesOwnedClient() throws Exception { + OSSEndpoint endpoint = new OSSEndpoint(); + OSSClient client = mock(OSSClient.class); + + var clientField = OSSEndpoint.class.getDeclaredField("ossClient"); + clientField.setAccessible(true); + clientField.set(endpoint, client); + + var autowiredField = OSSEndpoint.class.getDeclaredField("autowiredOssClient"); + autowiredField.setAccessible(true); + autowiredField.setBoolean(endpoint, false); + + endpoint.doStop(); + + verify(client).close(); + assertThat(endpoint.getOssClient()).isNull(); + } +} diff --git a/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/OSSUtilsTest.java b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/OSSUtilsTest.java index 0e0a0b3c4b9eb..4459e87d7ec04 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/OSSUtilsTest.java +++ b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/OSSUtilsTest.java @@ -17,6 +17,7 @@ package org.apache.camel.component.alibaba.oss; import com.aliyun.sdk.service.oss2.OSSClient; +import org.apache.camel.component.alibaba.common.models.ServiceKeys; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @@ -69,4 +70,17 @@ void createClientMissingRegionAndEndpoint() { .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("Region/endpoint"); } + + @Test + void createClientPrefersEndpointCredentialsOverEmptyServiceKeys() throws Exception { + OSSEndpoint endpoint = new OSSEndpoint(); + endpoint.setAccessKey("uri-ak"); + endpoint.setSecretKey("uri-sk"); + endpoint.setRegion("cn-hangzhou"); + endpoint.setServiceKeys(new ServiceKeys("", "")); + + try (OSSClient client = OSSUtils.createClient(endpoint)) { + assertThat(client).isNotNull(); + } + } } From 3adb63803df401ee852d01646287f034312830fe Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 11 Aug 2026 16:42:22 +0000 Subject: [PATCH 10/12] CAMEL-24373: Rebase on main and bump component version to 4.23.0 - Rebased on upstream main (4.23.0-SNAPSHOT) - Updated firstVersion and docs to 4.23 - Resolved parent/pom.xml conflicts; alibaba SDK versions in alpha order - Regenerated catalog and component metadata Co-authored-by: Cursor Agent --- .../org/apache/camel/catalog/components/alibaba-mns.json | 4 ++-- .../org/apache/camel/catalog/components/alibaba-oss.json | 4 ++-- .../apache/camel/catalog/docs/alibaba-mns-component.adoc | 2 +- .../apache/camel/catalog/docs/alibaba-oss-component.adoc | 2 +- components/camel-alibaba/camel-alibaba-common/pom.xml | 4 ++-- .../META-INF/services/org/apache/camel/other.properties | 2 +- .../src/generated/resources/alibaba-common.json | 4 ++-- components/camel-alibaba/camel-alibaba-mns/pom.xml | 4 ++-- .../org/apache/camel/component/alibaba/mns/alibaba-mns.json | 4 ++-- .../META-INF/services/org/apache/camel/component.properties | 2 +- .../src/main/docs/alibaba-mns-component.adoc | 2 +- .../org/apache/camel/component/alibaba/mns/MNSEndpoint.java | 2 +- components/camel-alibaba/camel-alibaba-oss/pom.xml | 4 ++-- .../org/apache/camel/component/alibaba/oss/alibaba-oss.json | 4 ++-- .../META-INF/services/org/apache/camel/component.properties | 2 +- .../src/main/docs/alibaba-oss-component.adoc | 2 +- .../org/apache/camel/component/alibaba/oss/OSSEndpoint.java | 2 +- components/camel-alibaba/pom.xml | 2 +- parent/pom.xml | 6 ------ 19 files changed, 26 insertions(+), 32 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-mns.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-mns.json index d78d4c416999c..a4cd31282b82a 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-mns.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-mns.json @@ -5,13 +5,13 @@ "title": "Alibaba Message Service (MNS)", "description": "Send and receive messages to\/from Alibaba Cloud Message Service (MNS).", "deprecated": false, - "firstVersion": "4.22.0", + "firstVersion": "4.23.0", "label": "cloud,messaging", "javaType": "org.apache.camel.component.alibaba.mns.MNSComponent", "supportLevel": "Preview", "groupId": "org.apache.camel", "artifactId": "camel-alibaba-mns", - "version": "4.22.0-SNAPSHOT", + "version": "4.23.0-SNAPSHOT", "scheme": "alibaba-mns", "extendsScheme": "", "syntax": "alibaba-mns:queueName", diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-oss.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-oss.json index 8b945a5510b45..1aca9c88089b3 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-oss.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-oss.json @@ -5,13 +5,13 @@ "title": "Alibaba Object Storage Service (OSS)", "description": "Alibaba Cloud Object Storage Service (OSS) component", "deprecated": false, - "firstVersion": "4.22.0", + "firstVersion": "4.23.0", "label": "cloud", "javaType": "org.apache.camel.component.alibaba.oss.OSSComponent", "supportLevel": "Preview", "groupId": "org.apache.camel", "artifactId": "camel-alibaba-oss", - "version": "4.22.0-SNAPSHOT", + "version": "4.23.0-SNAPSHOT", "scheme": "alibaba-oss", "extendsScheme": "", "syntax": "alibaba-oss:operation", diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/alibaba-mns-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/alibaba-mns-component.adoc index 9e5b0e00dbf50..86820b7e56ffd 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/alibaba-mns-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/alibaba-mns-component.adoc @@ -3,7 +3,7 @@ :shortname: alibaba-mns :artifactid: camel-alibaba-mns :description: Send and receive messages to/from Alibaba Cloud Message Service (MNS). -:since: 4.22 +:since: 4.23 :supportlevel: Preview :tabs-sync-option: :component-header: Both producer and consumer are supported diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/alibaba-oss-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/alibaba-oss-component.adoc index 97891f33c6375..f4aa8ee196639 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/alibaba-oss-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/alibaba-oss-component.adoc @@ -3,7 +3,7 @@ :shortname: alibaba-oss :artifactid: camel-alibaba-oss :description: Alibaba Cloud Object Storage Service (OSS) component -:since: 4.22 +:since: 4.23 :supportlevel: Preview :tabs-sync-option: :component-header: Both producer and consumer are supported diff --git a/components/camel-alibaba/camel-alibaba-common/pom.xml b/components/camel-alibaba/camel-alibaba-common/pom.xml index 79633f28c6f3a..62023cae0f174 100644 --- a/components/camel-alibaba/camel-alibaba-common/pom.xml +++ b/components/camel-alibaba/camel-alibaba-common/pom.xml @@ -24,11 +24,11 @@ org.apache.camel camel-alibaba-parent - 4.22.0-SNAPSHOT + 4.23.0-SNAPSHOT - 4.22.0 + 4.23.0 camel-alibaba-common diff --git a/components/camel-alibaba/camel-alibaba-common/src/generated/resources/META-INF/services/org/apache/camel/other.properties b/components/camel-alibaba/camel-alibaba-common/src/generated/resources/META-INF/services/org/apache/camel/other.properties index 5b5950b30c120..aec20ac9d5f94 100644 --- a/components/camel-alibaba/camel-alibaba-common/src/generated/resources/META-INF/services/org/apache/camel/other.properties +++ b/components/camel-alibaba/camel-alibaba-common/src/generated/resources/META-INF/services/org/apache/camel/other.properties @@ -2,6 +2,6 @@ name=alibaba-common groupId=org.apache.camel artifactId=camel-alibaba-common -version=4.22.0-SNAPSHOT +version=4.23.0-SNAPSHOT projectName=Camel :: Alibaba Cloud :: Common projectDescription=Common utilities for Camel Alibaba Cloud components diff --git a/components/camel-alibaba/camel-alibaba-common/src/generated/resources/alibaba-common.json b/components/camel-alibaba/camel-alibaba-common/src/generated/resources/alibaba-common.json index eaeb8ad093c5d..b0e29d769095f 100644 --- a/components/camel-alibaba/camel-alibaba-common/src/generated/resources/alibaba-common.json +++ b/components/camel-alibaba/camel-alibaba-common/src/generated/resources/alibaba-common.json @@ -5,10 +5,10 @@ "title": "Alibaba Common", "description": "Common utilities for Camel Alibaba Cloud components", "deprecated": false, - "firstVersion": "4.22.0", + "firstVersion": "4.23.0", "supportLevel": "Preview", "groupId": "org.apache.camel", "artifactId": "camel-alibaba-common", - "version": "4.22.0-SNAPSHOT" + "version": "4.23.0-SNAPSHOT" } } diff --git a/components/camel-alibaba/camel-alibaba-mns/pom.xml b/components/camel-alibaba/camel-alibaba-mns/pom.xml index 47820f1912e61..c5c1ab046901f 100644 --- a/components/camel-alibaba/camel-alibaba-mns/pom.xml +++ b/components/camel-alibaba/camel-alibaba-mns/pom.xml @@ -24,11 +24,11 @@ org.apache.camel camel-alibaba-parent - 4.22.0-SNAPSHOT + 4.23.0-SNAPSHOT - 4.22.0 + 4.23.0 camel-alibaba-mns diff --git a/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/org/apache/camel/component/alibaba/mns/alibaba-mns.json b/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/org/apache/camel/component/alibaba/mns/alibaba-mns.json index d78d4c416999c..a4cd31282b82a 100644 --- a/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/org/apache/camel/component/alibaba/mns/alibaba-mns.json +++ b/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/org/apache/camel/component/alibaba/mns/alibaba-mns.json @@ -5,13 +5,13 @@ "title": "Alibaba Message Service (MNS)", "description": "Send and receive messages to\/from Alibaba Cloud Message Service (MNS).", "deprecated": false, - "firstVersion": "4.22.0", + "firstVersion": "4.23.0", "label": "cloud,messaging", "javaType": "org.apache.camel.component.alibaba.mns.MNSComponent", "supportLevel": "Preview", "groupId": "org.apache.camel", "artifactId": "camel-alibaba-mns", - "version": "4.22.0-SNAPSHOT", + "version": "4.23.0-SNAPSHOT", "scheme": "alibaba-mns", "extendsScheme": "", "syntax": "alibaba-mns:queueName", diff --git a/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/services/org/apache/camel/component.properties b/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/services/org/apache/camel/component.properties index d0fa7a95e870b..6968f368335fe 100644 --- a/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/services/org/apache/camel/component.properties +++ b/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/services/org/apache/camel/component.properties @@ -2,6 +2,6 @@ components=alibaba-mns groupId=org.apache.camel artifactId=camel-alibaba-mns -version=4.22.0-SNAPSHOT +version=4.23.0-SNAPSHOT projectName=Camel :: Alibaba Cloud :: Message Service (MNS) projectDescription=Camel Alibaba Cloud Message Service (MNS) component diff --git a/components/camel-alibaba/camel-alibaba-mns/src/main/docs/alibaba-mns-component.adoc b/components/camel-alibaba/camel-alibaba-mns/src/main/docs/alibaba-mns-component.adoc index 9e5b0e00dbf50..86820b7e56ffd 100644 --- a/components/camel-alibaba/camel-alibaba-mns/src/main/docs/alibaba-mns-component.adoc +++ b/components/camel-alibaba/camel-alibaba-mns/src/main/docs/alibaba-mns-component.adoc @@ -3,7 +3,7 @@ :shortname: alibaba-mns :artifactid: camel-alibaba-mns :description: Send and receive messages to/from Alibaba Cloud Message Service (MNS). -:since: 4.22 +:since: 4.23 :supportlevel: Preview :tabs-sync-option: :component-header: Both producer and consumer are supported diff --git a/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSEndpoint.java b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSEndpoint.java index 772fe2d165f5c..134636c5f9471 100644 --- a/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSEndpoint.java +++ b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSEndpoint.java @@ -33,7 +33,7 @@ /** * Send and receive messages to/from Alibaba Cloud Message Service (MNS). */ -@UriEndpoint(firstVersion = "4.22.0", scheme = "alibaba-mns", title = "Alibaba Message Service (MNS)", +@UriEndpoint(firstVersion = "4.23.0", scheme = "alibaba-mns", title = "Alibaba Message Service (MNS)", syntax = "alibaba-mns:queueName", category = { Category.CLOUD, Category.MESSAGING }, headersClass = MNSHeaders.class) public class MNSEndpoint extends ScheduledPollEndpoint { diff --git a/components/camel-alibaba/camel-alibaba-oss/pom.xml b/components/camel-alibaba/camel-alibaba-oss/pom.xml index 2cc1389376563..98f0a5e19a6f6 100644 --- a/components/camel-alibaba/camel-alibaba-oss/pom.xml +++ b/components/camel-alibaba/camel-alibaba-oss/pom.xml @@ -24,11 +24,11 @@ org.apache.camel camel-alibaba-parent - 4.22.0-SNAPSHOT + 4.23.0-SNAPSHOT - 4.22.0 + 4.23.0 camel-alibaba-oss diff --git a/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/org/apache/camel/component/alibaba/oss/alibaba-oss.json b/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/org/apache/camel/component/alibaba/oss/alibaba-oss.json index 8b945a5510b45..1aca9c88089b3 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/org/apache/camel/component/alibaba/oss/alibaba-oss.json +++ b/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/org/apache/camel/component/alibaba/oss/alibaba-oss.json @@ -5,13 +5,13 @@ "title": "Alibaba Object Storage Service (OSS)", "description": "Alibaba Cloud Object Storage Service (OSS) component", "deprecated": false, - "firstVersion": "4.22.0", + "firstVersion": "4.23.0", "label": "cloud", "javaType": "org.apache.camel.component.alibaba.oss.OSSComponent", "supportLevel": "Preview", "groupId": "org.apache.camel", "artifactId": "camel-alibaba-oss", - "version": "4.22.0-SNAPSHOT", + "version": "4.23.0-SNAPSHOT", "scheme": "alibaba-oss", "extendsScheme": "", "syntax": "alibaba-oss:operation", diff --git a/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/services/org/apache/camel/component.properties b/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/services/org/apache/camel/component.properties index e04287e28ec5f..3f474d7aa8e7a 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/services/org/apache/camel/component.properties +++ b/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/services/org/apache/camel/component.properties @@ -2,6 +2,6 @@ components=alibaba-oss groupId=org.apache.camel artifactId=camel-alibaba-oss -version=4.22.0-SNAPSHOT +version=4.23.0-SNAPSHOT projectName=Camel :: Alibaba Cloud :: OSS projectDescription=Alibaba Cloud Object Storage Service (OSS) component diff --git a/components/camel-alibaba/camel-alibaba-oss/src/main/docs/alibaba-oss-component.adoc b/components/camel-alibaba/camel-alibaba-oss/src/main/docs/alibaba-oss-component.adoc index 97891f33c6375..f4aa8ee196639 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/main/docs/alibaba-oss-component.adoc +++ b/components/camel-alibaba/camel-alibaba-oss/src/main/docs/alibaba-oss-component.adoc @@ -3,7 +3,7 @@ :shortname: alibaba-oss :artifactid: camel-alibaba-oss :description: Alibaba Cloud Object Storage Service (OSS) component -:since: 4.22 +:since: 4.23 :supportlevel: Preview :tabs-sync-option: :component-header: Both producer and consumer are supported diff --git a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSEndpoint.java b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSEndpoint.java index 9fc9820b8ff57..dd6eb037ce8a2 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSEndpoint.java +++ b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSEndpoint.java @@ -32,7 +32,7 @@ /** * Alibaba Cloud Object Storage Service (OSS) component */ -@UriEndpoint(firstVersion = "4.22.0", scheme = "alibaba-oss", title = "Alibaba Object Storage Service (OSS)", +@UriEndpoint(firstVersion = "4.23.0", scheme = "alibaba-oss", title = "Alibaba Object Storage Service (OSS)", syntax = "alibaba-oss:operation", category = { Category.CLOUD }, headersClass = OSSHeaders.class) public class OSSEndpoint extends ScheduledPollEndpoint { diff --git a/components/camel-alibaba/pom.xml b/components/camel-alibaba/pom.xml index ee08cf0fec4cd..ff7f255a79d5d 100644 --- a/components/camel-alibaba/pom.xml +++ b/components/camel-alibaba/pom.xml @@ -24,7 +24,7 @@ org.apache.camel components - 4.22.0-SNAPSHOT + 4.23.0-SNAPSHOT camel-alibaba-parent diff --git a/parent/pom.xml b/parent/pom.xml index e6aa11ac61dff..a9eb89f61577b 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -82,13 +82,7 @@ 1.12.1 1.12.1 4.3.0 -<<<<<<< HEAD 2.51.3 -======= - 0.4.1 - 2.0.0 - 2.50.3 ->>>>>>> da84d76e898 (CAMEL-24373: Address PR review feedback for camel-alibaba phase 1) 1.3.3 12.0.0-beta.39 3.2.1 From eb936edc84830669890450d834a5511a1ef365a4 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 12 Aug 2026 15:37:12 +0000 Subject: [PATCH 11/12] CAMEL-24373: Address review feedback on alibaba OSS/MNS components - Fix BOM alibaba module versions to 4.23.0-SNAPSHOT - Redesign OSS URI: bucketName in path, operation as query param - Mark OSS/MNS credentials with secret=true and security label - OSS producer resolves runtime overrides from headers first - Return structured Map/List bodies instead of Gson JSON strings - Remove duplicate MNS receipt-handle/message constants from MNSProperties - Update tests, docs, and catalog metadata Co-authored-by: Cursor Agent --- bom/camel-bom/pom.xml | 6 +- .../camel/catalog/components/alibaba-mns.json | 62 ++++++------ .../camel/catalog/components/alibaba-oss.json | 30 +++--- .../catalog/docs/alibaba-oss-component.adoc | 19 ++-- .../component/alibaba/mns/alibaba-mns.json | 62 ++++++------ .../component/alibaba/mns/MNSEndpoint.java | 8 +- .../component/alibaba/mns/MNSProducer.java | 4 +- .../camel/component/alibaba/mns/MNSUtils.java | 7 +- .../alibaba/mns/constants/MNSProperties.java | 4 - .../alibaba/mns/PublishMessageTest.java | 3 +- .../alibaba/mns/SendMessageTest.java | 5 +- .../camel-alibaba/camel-alibaba-oss/pom.xml | 5 - .../alibaba/oss/OSSEndpointConfigurer.java | 9 +- .../alibaba/oss/OSSEndpointUriFactory.java | 8 +- .../component/alibaba/oss/alibaba-oss.json | 30 +++--- .../src/main/docs/alibaba-oss-component.adoc | 19 ++-- .../component/alibaba/oss/OSSEndpoint.java | 22 ++--- .../component/alibaba/oss/OSSProducer.java | 94 +++---------------- .../camel/component/alibaba/oss/OSSUtils.java | 71 ++++++++++++++ .../alibaba/oss/DeleteObjectTest.java | 17 ++-- .../component/alibaba/oss/GetObjectTest.java | 8 +- .../component/alibaba/oss/HeadObjectTest.java | 21 +++-- .../alibaba/oss/ListObjectsTest.java | 18 ++-- .../component/alibaba/oss/PutObjectTest.java | 19 ++-- 24 files changed, 280 insertions(+), 271 deletions(-) diff --git a/bom/camel-bom/pom.xml b/bom/camel-bom/pom.xml index 83065451a0cbd..52b9cdbee2bd2 100644 --- a/bom/camel-bom/pom.xml +++ b/bom/camel-bom/pom.xml @@ -69,17 +69,17 @@ org.apache.camel camel-alibaba-common - 4.22.0-SNAPSHOT + 4.23.0-SNAPSHOT org.apache.camel camel-alibaba-mns - 4.22.0-SNAPSHOT + 4.23.0-SNAPSHOT org.apache.camel camel-alibaba-oss - 4.22.0-SNAPSHOT + 4.23.0-SNAPSHOT org.apache.camel diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-mns.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-mns.json index a4cd31282b82a..76e09dff19bb1 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-mns.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-mns.json @@ -44,36 +44,36 @@ }, "properties": { "queueName": { "index": 0, "kind": "path", "displayName": "Queue Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Queue name, or topic name when using the topic URI syntax" }, - "accessKey": { "index": 1, "kind": "parameter", "displayName": "Access Key", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "security": "secret", "description": "Access key for the cloud user" }, - "accountEndpoint": { "index": 2, "kind": "parameter", "displayName": "Account Endpoint", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "MNS account endpoint, for example https:\/\/123456.mns.cn-hangzhou.aliyuncs.com" }, - "operation": { "index": 3, "kind": "parameter", "displayName": "Operation", "group": "common", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "sendMessage", "receiveMessage", "deleteMessage", "publishMessage" ], "deprecated": false, "autowired": false, "secret": false, "description": "Operation to perform" }, - "region": { "index": 4, "kind": "parameter", "displayName": "Region", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Alibaba Cloud region" }, - "secretKey": { "index": 5, "kind": "parameter", "displayName": "Secret Key", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "security": "secret", "description": "Secret key for the cloud user" }, - "serviceKeys": { "index": 6, "kind": "parameter", "displayName": "Service Keys", "group": "common", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.alibaba.common.models.ServiceKeys", "deprecated": false, "autowired": false, "secret": true, "security": "secret", "description": "Configuration object for cloud service authentication" }, - "topicName": { "index": 7, "kind": "parameter", "displayName": "Topic Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Topic name for publishMessage operations" }, - "waitSeconds": { "index": 8, "kind": "parameter", "displayName": "Wait Seconds", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "Long polling wait time in seconds when receiving messages" }, - "deleteAfterRead": { "index": 9, "kind": "parameter", "displayName": "Delete After Read", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Delete message from the queue after it has been processed" }, - "maxMessagesPerPoll": { "index": 10, "kind": "parameter", "displayName": "Max Messages Per Poll", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Maximum number of messages to receive per poll" }, - "sendEmptyMessageWhenIdle": { "index": 11, "kind": "parameter", "displayName": "Send Empty Message When Idle", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead." }, - "bridgeErrorHandler": { "index": 12, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, - "exceptionHandler": { "index": 13, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, - "exchangePattern": { "index": 14, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." }, - "pollStrategy": { "index": 15, "kind": "parameter", "displayName": "Poll Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.PollingConsumerPollStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "A pluggable org.apache.camel.PollingConsumerPollingStrategy allowing you to provide your custom implementation to control error handling usually occurred during the poll operation before an Exchange have been created and being routed in Camel." }, - "lazyStartProducer": { "index": 16, "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 producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." }, - "mnsClient": { "index": 17, "kind": "parameter", "displayName": "MNS Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "com.aliyun.mns.client.MNSClient", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "description": "Autowire an existing MNSClient instance" }, - "backoffErrorThreshold": { "index": 18, "kind": "parameter", "displayName": "Backoff Error Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent error polls (failed due some error) that should happen before the backoffMultipler should kick-in." }, - "backoffIdleThreshold": { "index": 19, "kind": "parameter", "displayName": "Backoff Idle Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent idle polls that should happen before the backoffMultipler should kick-in." }, - "backoffMultiplier": { "index": 20, "kind": "parameter", "displayName": "Backoff Multiplier", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "To let the scheduled polling consumer backoff if there has been a number of subsequent idles\/errors in a row. The multiplier is then the number of polls that will be skipped before the next actual attempt is happening again. When this option is in use then backoffIdleThreshold and\/or backoffErrorThreshold must also be configured." }, - "delay": { "index": 21, "kind": "parameter", "displayName": "Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 500, "description": "Milliseconds before the next poll." }, - "greedy": { "index": 22, "kind": "parameter", "displayName": "Greedy", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If greedy is enabled, then the ScheduledPollConsumer will run immediately again, if the previous run polled 1 or more messages." }, - "initialDelay": { "index": 23, "kind": "parameter", "displayName": "Initial Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "Milliseconds before the first poll starts." }, - "repeatCount": { "index": 24, "kind": "parameter", "displayName": "Repeat Count", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "Specifies a maximum limit of number of fires. So if you set it to 1, the scheduler will only fire once. If you set it to 5, it will only fire five times. A value of zero or negative means fire forever." }, - "runLoggingLevel": { "index": 25, "kind": "parameter", "displayName": "Run Logging Level", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "enum", "javaType": "org.apache.camel.LoggingLevel", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "TRACE", "description": "The consumer logs a start\/complete log line when it polls. This option allows you to configure the logging level for that." }, - "scheduledExecutorService": { "index": 26, "kind": "parameter", "displayName": "Scheduled Executor Service", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.concurrent.ScheduledExecutorService", "deprecated": false, "autowired": false, "secret": false, "description": "Allows for configuring a custom\/shared thread pool to use for the consumer. By default each consumer has its own single threaded thread pool." }, - "scheduler": { "index": 27, "kind": "parameter", "displayName": "Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.lang.Object", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "none", "description": "To use a cron scheduler from either camel-spring or camel-quartz component. Use value spring or quartz for built in scheduler" }, - "schedulerProperties": { "index": 28, "kind": "parameter", "displayName": "Scheduler Properties", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.Map", "prefix": "scheduler.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "To configure additional properties when using a custom scheduler or any of the Quartz, Spring based scheduler. This is a multi-value option with prefix: scheduler." }, - "startScheduler": { "index": 29, "kind": "parameter", "displayName": "Start Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether the scheduler should be auto started." }, - "timeUnit": { "index": 30, "kind": "parameter", "displayName": "Time Unit", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "enum", "javaType": "java.util.concurrent.TimeUnit", "enum": [ "NANOSECONDS", "MICROSECONDS", "MILLISECONDS", "SECONDS", "MINUTES", "HOURS", "DAYS" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "MILLISECONDS", "description": "Time unit for initialDelay and delay options." }, - "useFixedDelay": { "index": 31, "kind": "parameter", "displayName": "Use Fixed Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in JDK for details." } + "accountEndpoint": { "index": 1, "kind": "parameter", "displayName": "Account Endpoint", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "MNS account endpoint, for example https:\/\/123456.mns.cn-hangzhou.aliyuncs.com" }, + "operation": { "index": 2, "kind": "parameter", "displayName": "Operation", "group": "common", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "sendMessage", "receiveMessage", "deleteMessage", "publishMessage" ], "deprecated": false, "autowired": false, "secret": false, "description": "Operation to perform" }, + "region": { "index": 3, "kind": "parameter", "displayName": "Region", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Alibaba Cloud region" }, + "topicName": { "index": 4, "kind": "parameter", "displayName": "Topic Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Topic name for publishMessage operations" }, + "waitSeconds": { "index": 5, "kind": "parameter", "displayName": "Wait Seconds", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "Long polling wait time in seconds when receiving messages" }, + "deleteAfterRead": { "index": 6, "kind": "parameter", "displayName": "Delete After Read", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Delete message from the queue after it has been processed" }, + "maxMessagesPerPoll": { "index": 7, "kind": "parameter", "displayName": "Max Messages Per Poll", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Maximum number of messages to receive per poll" }, + "sendEmptyMessageWhenIdle": { "index": 8, "kind": "parameter", "displayName": "Send Empty Message When Idle", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead." }, + "bridgeErrorHandler": { "index": 9, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, + "exceptionHandler": { "index": 10, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, + "exchangePattern": { "index": 11, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." }, + "pollStrategy": { "index": 12, "kind": "parameter", "displayName": "Poll Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.PollingConsumerPollStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "A pluggable org.apache.camel.PollingConsumerPollingStrategy allowing you to provide your custom implementation to control error handling usually occurred during the poll operation before an Exchange have been created and being routed in Camel." }, + "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 producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." }, + "mnsClient": { "index": 14, "kind": "parameter", "displayName": "MNS Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "com.aliyun.mns.client.MNSClient", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "description": "Autowire an existing MNSClient instance" }, + "backoffErrorThreshold": { "index": 15, "kind": "parameter", "displayName": "Backoff Error Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent error polls (failed due some error) that should happen before the backoffMultipler should kick-in." }, + "backoffIdleThreshold": { "index": 16, "kind": "parameter", "displayName": "Backoff Idle Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent idle polls that should happen before the backoffMultipler should kick-in." }, + "backoffMultiplier": { "index": 17, "kind": "parameter", "displayName": "Backoff Multiplier", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "To let the scheduled polling consumer backoff if there has been a number of subsequent idles\/errors in a row. The multiplier is then the number of polls that will be skipped before the next actual attempt is happening again. When this option is in use then backoffIdleThreshold and\/or backoffErrorThreshold must also be configured." }, + "delay": { "index": 18, "kind": "parameter", "displayName": "Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 500, "description": "Milliseconds before the next poll." }, + "greedy": { "index": 19, "kind": "parameter", "displayName": "Greedy", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If greedy is enabled, then the ScheduledPollConsumer will run immediately again, if the previous run polled 1 or more messages." }, + "initialDelay": { "index": 20, "kind": "parameter", "displayName": "Initial Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "Milliseconds before the first poll starts." }, + "repeatCount": { "index": 21, "kind": "parameter", "displayName": "Repeat Count", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "Specifies a maximum limit of number of fires. So if you set it to 1, the scheduler will only fire once. If you set it to 5, it will only fire five times. A value of zero or negative means fire forever." }, + "runLoggingLevel": { "index": 22, "kind": "parameter", "displayName": "Run Logging Level", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "enum", "javaType": "org.apache.camel.LoggingLevel", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "TRACE", "description": "The consumer logs a start\/complete log line when it polls. This option allows you to configure the logging level for that." }, + "scheduledExecutorService": { "index": 23, "kind": "parameter", "displayName": "Scheduled Executor Service", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.concurrent.ScheduledExecutorService", "deprecated": false, "autowired": false, "secret": false, "description": "Allows for configuring a custom\/shared thread pool to use for the consumer. By default each consumer has its own single threaded thread pool." }, + "scheduler": { "index": 24, "kind": "parameter", "displayName": "Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.lang.Object", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "none", "description": "To use a cron scheduler from either camel-spring or camel-quartz component. Use value spring or quartz for built in scheduler" }, + "schedulerProperties": { "index": 25, "kind": "parameter", "displayName": "Scheduler Properties", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.Map", "prefix": "scheduler.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "To configure additional properties when using a custom scheduler or any of the Quartz, Spring based scheduler. This is a multi-value option with prefix: scheduler." }, + "startScheduler": { "index": 26, "kind": "parameter", "displayName": "Start Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether the scheduler should be auto started." }, + "timeUnit": { "index": 27, "kind": "parameter", "displayName": "Time Unit", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "enum", "javaType": "java.util.concurrent.TimeUnit", "enum": [ "NANOSECONDS", "MICROSECONDS", "MILLISECONDS", "SECONDS", "MINUTES", "HOURS", "DAYS" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "MILLISECONDS", "description": "Time unit for initialDelay and delay options." }, + "useFixedDelay": { "index": 28, "kind": "parameter", "displayName": "Use Fixed Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in JDK for details." }, + "accessKey": { "index": 29, "kind": "parameter", "displayName": "Access Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "security": "secret", "description": "Access key for the cloud user" }, + "secretKey": { "index": 30, "kind": "parameter", "displayName": "Secret Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "security": "secret", "description": "Secret key for the cloud user" }, + "serviceKeys": { "index": 31, "kind": "parameter", "displayName": "Service Keys", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.component.alibaba.common.models.ServiceKeys", "deprecated": false, "autowired": false, "secret": true, "security": "secret", "description": "Configuration object for cloud service authentication" } } } diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-oss.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-oss.json index 1aca9c88089b3..2a48300a4ba0d 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-oss.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/alibaba-oss.json @@ -14,7 +14,7 @@ "version": "4.23.0-SNAPSHOT", "scheme": "alibaba-oss", "extendsScheme": "", - "syntax": "alibaba-oss:operation", + "syntax": "alibaba-oss:bucketName", "async": false, "api": false, "consumerOnly": false, @@ -42,20 +42,20 @@ "CamelFileName": { "index": 8, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the object with which the operation is to be performed", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#FILE_NAME" } }, "properties": { - "operation": { "index": 0, "kind": "path", "displayName": "Operation", "group": "producer", "label": "producer", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Operation to be performed" }, - "bucketName": { "index": 1, "kind": "parameter", "displayName": "Bucket Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "endpointIdentity": true, "description": "Name of bucket to perform operation on" }, - "endpoint": { "index": 2, "kind": "parameter", "displayName": "Endpoint url", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "OSS endpoint URL. Carries higher precedence than region based client initialization" }, - "objectName": { "index": 3, "kind": "parameter", "displayName": "Object Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of object to perform operation with" }, - "region": { "index": 4, "kind": "parameter", "displayName": "Service region", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "OSS service region" }, - "deleteAfterRead": { "index": 5, "kind": "parameter", "displayName": "Delete after read", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Determines if objects should be deleted after they have been retrieved" }, - "maxMessagesPerPoll": { "index": 6, "kind": "parameter", "displayName": "Maximum messages per poll", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 10, "description": "The maximum number of messages to poll at each polling" }, - "prefix": { "index": 7, "kind": "parameter", "displayName": "Prefix", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The object name prefix used for filtering objects to be listed" }, - "sendEmptyMessageWhenIdle": { "index": 8, "kind": "parameter", "displayName": "Send Empty Message When Idle", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead." }, - "bridgeErrorHandler": { "index": 9, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, - "exceptionHandler": { "index": 10, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, - "exchangePattern": { "index": 11, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." }, - "pollStrategy": { "index": 12, "kind": "parameter", "displayName": "Poll Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.PollingConsumerPollStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "A pluggable org.apache.camel.PollingConsumerPollingStrategy allowing you to provide your custom implementation to control error handling usually occurred during the poll operation before an Exchange have been created and being routed in Camel." }, - "maxKeys": { "index": 13, "kind": "parameter", "displayName": "Max Keys", "group": "producer", "label": "consumer,producer", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "description": "The maximum number of keys returned when listing objects" }, + "bucketName": { "index": 0, "kind": "path", "displayName": "Bucket Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of bucket to perform operation on" }, + "endpoint": { "index": 1, "kind": "parameter", "displayName": "Endpoint url", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "OSS endpoint URL. Carries higher precedence than region based client initialization" }, + "objectName": { "index": 2, "kind": "parameter", "displayName": "Object Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of object to perform operation with" }, + "region": { "index": 3, "kind": "parameter", "displayName": "Service region", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "OSS service region" }, + "deleteAfterRead": { "index": 4, "kind": "parameter", "displayName": "Delete after read", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Determines if objects should be deleted after they have been retrieved" }, + "maxMessagesPerPoll": { "index": 5, "kind": "parameter", "displayName": "Maximum messages per poll", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 10, "description": "The maximum number of messages to poll at each polling" }, + "prefix": { "index": 6, "kind": "parameter", "displayName": "Prefix", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The object name prefix used for filtering objects to be listed" }, + "sendEmptyMessageWhenIdle": { "index": 7, "kind": "parameter", "displayName": "Send Empty Message When Idle", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead." }, + "bridgeErrorHandler": { "index": 8, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, + "exceptionHandler": { "index": 9, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, + "exchangePattern": { "index": 10, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." }, + "pollStrategy": { "index": 11, "kind": "parameter", "displayName": "Poll Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.PollingConsumerPollStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "A pluggable org.apache.camel.PollingConsumerPollingStrategy allowing you to provide your custom implementation to control error handling usually occurred during the poll operation before an Exchange have been created and being routed in Camel." }, + "maxKeys": { "index": 12, "kind": "parameter", "displayName": "Max Keys", "group": "producer", "label": "consumer,producer", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "description": "The maximum number of keys returned when listing objects" }, + "operation": { "index": 13, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "producer", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "listBuckets", "listObjects", "putObject", "getObject", "deleteObject", "copyObject", "headObject" ], "deprecated": false, "autowired": false, "secret": false, "description": "Operation to be performed" }, "lazyStartProducer": { "index": 14, "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 producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." }, "ossClient": { "index": 15, "kind": "parameter", "displayName": "OSS Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "com.aliyun.sdk.service.oss2.OSSClient", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "description": "An autowired OSS client" }, "backoffErrorThreshold": { "index": 16, "kind": "parameter", "displayName": "Backoff Error Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent error polls (failed due some error) that should happen before the backoffMultipler should kick-in." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/alibaba-oss-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/alibaba-oss-component.adoc index f4aa8ee196639..5c48d5b101acb 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/alibaba-oss-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/alibaba-oss-component.adoc @@ -31,9 +31,11 @@ Maven users will need to add the following dependency to their `pom.xml` for thi == URI Format ---- -alibaba-oss:operation[?options] +alibaba-oss:bucketName[?options] ---- +The `operation` query parameter selects the OSS operation to perform (for example `putObject`, `getObject`, `listObjects`). + // component options: START include::partial$component-configure-options.adoc[] include::partial$component-endpoint-options.adoc[] @@ -42,7 +44,7 @@ include::partial$component-endpoint-headers.adoc[] == Usage -=== Message properties evaluated by the OSS producer +=== Message headers evaluated by the OSS producer [width="100%",cols="10%,10%,80%",options="header",] |======================================================================= @@ -50,7 +52,7 @@ include::partial$component-endpoint-headers.adoc[] |`CamelAlibabaOssOperation` |`String` | Name of operation to invoke -|`CamelAlibabaOssBucketName` |`String` | Bucket name to invoke operation on +|`CamelAlibabaOssBucketName` |`String` | Bucket name to invoke operation on (overrides the URI path bucket name) |`CamelAlibabaOssObjectName` |`String` | Name of the object to be used in operation @@ -64,7 +66,7 @@ include::partial$component-endpoint-headers.adoc[] |======================================================================= -If any of the above properties are set, they will override their corresponding query parameter. +If any of the above headers are set, they will override their corresponding query parameter or URI path value. === List of Supported OSS Operations @@ -88,15 +90,16 @@ The consumer polls objects from a bucket using `listObjectsV2`, downloads each o ---- from("direct:start") .setBody(constant("Hello OSS")) - .setProperty("CamelAlibabaOssBucketName", constant("my-bucket")) - .setProperty("CamelAlibabaOssObjectName", constant("hello.txt")) - .to("alibaba-oss:putObject?region=cn-hangzhou&accessKey=xxx&secretKey=yyy"); + .setHeader("CamelAlibabaOssObjectName", constant("hello.txt")) + .to("alibaba-oss:my-bucket?operation=putObject®ion=cn-hangzhou&accessKey=xxx&secretKey=yyy"); ---- +Producer operations return structured response metadata in the message body (`Map` or `List` depending on the operation). + === Consume objects from a bucket [source,java] ---- -from("alibaba-oss:consumer?bucketName=my-bucket®ion=cn-hangzhou&accessKey=xxx&secretKey=yyy&deleteAfterRead=true") +from("alibaba-oss:my-bucket?region=cn-hangzhou&accessKey=xxx&secretKey=yyy&deleteAfterRead=true") .to("log:output"); ---- diff --git a/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/org/apache/camel/component/alibaba/mns/alibaba-mns.json b/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/org/apache/camel/component/alibaba/mns/alibaba-mns.json index a4cd31282b82a..76e09dff19bb1 100644 --- a/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/org/apache/camel/component/alibaba/mns/alibaba-mns.json +++ b/components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/org/apache/camel/component/alibaba/mns/alibaba-mns.json @@ -44,36 +44,36 @@ }, "properties": { "queueName": { "index": 0, "kind": "path", "displayName": "Queue Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Queue name, or topic name when using the topic URI syntax" }, - "accessKey": { "index": 1, "kind": "parameter", "displayName": "Access Key", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "security": "secret", "description": "Access key for the cloud user" }, - "accountEndpoint": { "index": 2, "kind": "parameter", "displayName": "Account Endpoint", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "MNS account endpoint, for example https:\/\/123456.mns.cn-hangzhou.aliyuncs.com" }, - "operation": { "index": 3, "kind": "parameter", "displayName": "Operation", "group": "common", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "sendMessage", "receiveMessage", "deleteMessage", "publishMessage" ], "deprecated": false, "autowired": false, "secret": false, "description": "Operation to perform" }, - "region": { "index": 4, "kind": "parameter", "displayName": "Region", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Alibaba Cloud region" }, - "secretKey": { "index": 5, "kind": "parameter", "displayName": "Secret Key", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "security": "secret", "description": "Secret key for the cloud user" }, - "serviceKeys": { "index": 6, "kind": "parameter", "displayName": "Service Keys", "group": "common", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.alibaba.common.models.ServiceKeys", "deprecated": false, "autowired": false, "secret": true, "security": "secret", "description": "Configuration object for cloud service authentication" }, - "topicName": { "index": 7, "kind": "parameter", "displayName": "Topic Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Topic name for publishMessage operations" }, - "waitSeconds": { "index": 8, "kind": "parameter", "displayName": "Wait Seconds", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "Long polling wait time in seconds when receiving messages" }, - "deleteAfterRead": { "index": 9, "kind": "parameter", "displayName": "Delete After Read", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Delete message from the queue after it has been processed" }, - "maxMessagesPerPoll": { "index": 10, "kind": "parameter", "displayName": "Max Messages Per Poll", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Maximum number of messages to receive per poll" }, - "sendEmptyMessageWhenIdle": { "index": 11, "kind": "parameter", "displayName": "Send Empty Message When Idle", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead." }, - "bridgeErrorHandler": { "index": 12, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, - "exceptionHandler": { "index": 13, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, - "exchangePattern": { "index": 14, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." }, - "pollStrategy": { "index": 15, "kind": "parameter", "displayName": "Poll Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.PollingConsumerPollStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "A pluggable org.apache.camel.PollingConsumerPollingStrategy allowing you to provide your custom implementation to control error handling usually occurred during the poll operation before an Exchange have been created and being routed in Camel." }, - "lazyStartProducer": { "index": 16, "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 producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." }, - "mnsClient": { "index": 17, "kind": "parameter", "displayName": "MNS Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "com.aliyun.mns.client.MNSClient", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "description": "Autowire an existing MNSClient instance" }, - "backoffErrorThreshold": { "index": 18, "kind": "parameter", "displayName": "Backoff Error Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent error polls (failed due some error) that should happen before the backoffMultipler should kick-in." }, - "backoffIdleThreshold": { "index": 19, "kind": "parameter", "displayName": "Backoff Idle Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent idle polls that should happen before the backoffMultipler should kick-in." }, - "backoffMultiplier": { "index": 20, "kind": "parameter", "displayName": "Backoff Multiplier", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "To let the scheduled polling consumer backoff if there has been a number of subsequent idles\/errors in a row. The multiplier is then the number of polls that will be skipped before the next actual attempt is happening again. When this option is in use then backoffIdleThreshold and\/or backoffErrorThreshold must also be configured." }, - "delay": { "index": 21, "kind": "parameter", "displayName": "Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 500, "description": "Milliseconds before the next poll." }, - "greedy": { "index": 22, "kind": "parameter", "displayName": "Greedy", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If greedy is enabled, then the ScheduledPollConsumer will run immediately again, if the previous run polled 1 or more messages." }, - "initialDelay": { "index": 23, "kind": "parameter", "displayName": "Initial Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "Milliseconds before the first poll starts." }, - "repeatCount": { "index": 24, "kind": "parameter", "displayName": "Repeat Count", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "Specifies a maximum limit of number of fires. So if you set it to 1, the scheduler will only fire once. If you set it to 5, it will only fire five times. A value of zero or negative means fire forever." }, - "runLoggingLevel": { "index": 25, "kind": "parameter", "displayName": "Run Logging Level", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "enum", "javaType": "org.apache.camel.LoggingLevel", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "TRACE", "description": "The consumer logs a start\/complete log line when it polls. This option allows you to configure the logging level for that." }, - "scheduledExecutorService": { "index": 26, "kind": "parameter", "displayName": "Scheduled Executor Service", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.concurrent.ScheduledExecutorService", "deprecated": false, "autowired": false, "secret": false, "description": "Allows for configuring a custom\/shared thread pool to use for the consumer. By default each consumer has its own single threaded thread pool." }, - "scheduler": { "index": 27, "kind": "parameter", "displayName": "Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.lang.Object", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "none", "description": "To use a cron scheduler from either camel-spring or camel-quartz component. Use value spring or quartz for built in scheduler" }, - "schedulerProperties": { "index": 28, "kind": "parameter", "displayName": "Scheduler Properties", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.Map", "prefix": "scheduler.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "To configure additional properties when using a custom scheduler or any of the Quartz, Spring based scheduler. This is a multi-value option with prefix: scheduler." }, - "startScheduler": { "index": 29, "kind": "parameter", "displayName": "Start Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether the scheduler should be auto started." }, - "timeUnit": { "index": 30, "kind": "parameter", "displayName": "Time Unit", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "enum", "javaType": "java.util.concurrent.TimeUnit", "enum": [ "NANOSECONDS", "MICROSECONDS", "MILLISECONDS", "SECONDS", "MINUTES", "HOURS", "DAYS" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "MILLISECONDS", "description": "Time unit for initialDelay and delay options." }, - "useFixedDelay": { "index": 31, "kind": "parameter", "displayName": "Use Fixed Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in JDK for details." } + "accountEndpoint": { "index": 1, "kind": "parameter", "displayName": "Account Endpoint", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "MNS account endpoint, for example https:\/\/123456.mns.cn-hangzhou.aliyuncs.com" }, + "operation": { "index": 2, "kind": "parameter", "displayName": "Operation", "group": "common", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "sendMessage", "receiveMessage", "deleteMessage", "publishMessage" ], "deprecated": false, "autowired": false, "secret": false, "description": "Operation to perform" }, + "region": { "index": 3, "kind": "parameter", "displayName": "Region", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Alibaba Cloud region" }, + "topicName": { "index": 4, "kind": "parameter", "displayName": "Topic Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Topic name for publishMessage operations" }, + "waitSeconds": { "index": 5, "kind": "parameter", "displayName": "Wait Seconds", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "Long polling wait time in seconds when receiving messages" }, + "deleteAfterRead": { "index": 6, "kind": "parameter", "displayName": "Delete After Read", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Delete message from the queue after it has been processed" }, + "maxMessagesPerPoll": { "index": 7, "kind": "parameter", "displayName": "Max Messages Per Poll", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Maximum number of messages to receive per poll" }, + "sendEmptyMessageWhenIdle": { "index": 8, "kind": "parameter", "displayName": "Send Empty Message When Idle", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead." }, + "bridgeErrorHandler": { "index": 9, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, + "exceptionHandler": { "index": 10, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, + "exchangePattern": { "index": 11, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." }, + "pollStrategy": { "index": 12, "kind": "parameter", "displayName": "Poll Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.PollingConsumerPollStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "A pluggable org.apache.camel.PollingConsumerPollingStrategy allowing you to provide your custom implementation to control error handling usually occurred during the poll operation before an Exchange have been created and being routed in Camel." }, + "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 producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." }, + "mnsClient": { "index": 14, "kind": "parameter", "displayName": "MNS Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "com.aliyun.mns.client.MNSClient", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "description": "Autowire an existing MNSClient instance" }, + "backoffErrorThreshold": { "index": 15, "kind": "parameter", "displayName": "Backoff Error Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent error polls (failed due some error) that should happen before the backoffMultipler should kick-in." }, + "backoffIdleThreshold": { "index": 16, "kind": "parameter", "displayName": "Backoff Idle Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent idle polls that should happen before the backoffMultipler should kick-in." }, + "backoffMultiplier": { "index": 17, "kind": "parameter", "displayName": "Backoff Multiplier", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "To let the scheduled polling consumer backoff if there has been a number of subsequent idles\/errors in a row. The multiplier is then the number of polls that will be skipped before the next actual attempt is happening again. When this option is in use then backoffIdleThreshold and\/or backoffErrorThreshold must also be configured." }, + "delay": { "index": 18, "kind": "parameter", "displayName": "Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 500, "description": "Milliseconds before the next poll." }, + "greedy": { "index": 19, "kind": "parameter", "displayName": "Greedy", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If greedy is enabled, then the ScheduledPollConsumer will run immediately again, if the previous run polled 1 or more messages." }, + "initialDelay": { "index": 20, "kind": "parameter", "displayName": "Initial Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "Milliseconds before the first poll starts." }, + "repeatCount": { "index": 21, "kind": "parameter", "displayName": "Repeat Count", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "Specifies a maximum limit of number of fires. So if you set it to 1, the scheduler will only fire once. If you set it to 5, it will only fire five times. A value of zero or negative means fire forever." }, + "runLoggingLevel": { "index": 22, "kind": "parameter", "displayName": "Run Logging Level", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "enum", "javaType": "org.apache.camel.LoggingLevel", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "TRACE", "description": "The consumer logs a start\/complete log line when it polls. This option allows you to configure the logging level for that." }, + "scheduledExecutorService": { "index": 23, "kind": "parameter", "displayName": "Scheduled Executor Service", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.concurrent.ScheduledExecutorService", "deprecated": false, "autowired": false, "secret": false, "description": "Allows for configuring a custom\/shared thread pool to use for the consumer. By default each consumer has its own single threaded thread pool." }, + "scheduler": { "index": 24, "kind": "parameter", "displayName": "Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.lang.Object", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "none", "description": "To use a cron scheduler from either camel-spring or camel-quartz component. Use value spring or quartz for built in scheduler" }, + "schedulerProperties": { "index": 25, "kind": "parameter", "displayName": "Scheduler Properties", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.Map", "prefix": "scheduler.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "To configure additional properties when using a custom scheduler or any of the Quartz, Spring based scheduler. This is a multi-value option with prefix: scheduler." }, + "startScheduler": { "index": 26, "kind": "parameter", "displayName": "Start Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether the scheduler should be auto started." }, + "timeUnit": { "index": 27, "kind": "parameter", "displayName": "Time Unit", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "enum", "javaType": "java.util.concurrent.TimeUnit", "enum": [ "NANOSECONDS", "MICROSECONDS", "MILLISECONDS", "SECONDS", "MINUTES", "HOURS", "DAYS" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "MILLISECONDS", "description": "Time unit for initialDelay and delay options." }, + "useFixedDelay": { "index": 28, "kind": "parameter", "displayName": "Use Fixed Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in JDK for details." }, + "accessKey": { "index": 29, "kind": "parameter", "displayName": "Access Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "security": "secret", "description": "Access key for the cloud user" }, + "secretKey": { "index": 30, "kind": "parameter", "displayName": "Secret Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "security": "secret", "description": "Secret key for the cloud user" }, + "serviceKeys": { "index": 31, "kind": "parameter", "displayName": "Service Keys", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.component.alibaba.common.models.ServiceKeys", "deprecated": false, "autowired": false, "secret": true, "security": "secret", "description": "Configuration object for cloud service authentication" } } } diff --git a/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSEndpoint.java b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSEndpoint.java index 134636c5f9471..43b5b37554012 100644 --- a/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSEndpoint.java +++ b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSEndpoint.java @@ -55,14 +55,16 @@ public class MNSEndpoint extends ScheduledPollEndpoint { @Metadata(required = true) private String accountEndpoint; - @UriParam(description = "Access key for the cloud user", displayName = "Access Key", secret = true) + @UriParam(description = "Access key for the cloud user", displayName = "Access Key", + secret = true, security = "secret", label = "security") private String accessKey; - @UriParam(description = "Secret key for the cloud user", displayName = "Secret Key", secret = true) + @UriParam(description = "Secret key for the cloud user", displayName = "Secret Key", + secret = true, security = "secret", label = "security") private String secretKey; @UriParam(description = "Configuration object for cloud service authentication", displayName = "Service Keys", - security = "secret") + secret = true, security = "secret", label = "security") private ServiceKeys serviceKeys; @UriParam(description = "Topic name for publishMessage operations", displayName = "Topic Name") diff --git a/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSProducer.java b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSProducer.java index bfad30118a68e..cc7056427e46c 100644 --- a/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSProducer.java +++ b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSProducer.java @@ -109,13 +109,13 @@ private void setMessageResponseProperties(Exchange exchange, BaseMessage respons return; } if (ObjectHelper.isNotEmpty(response.getMessageId())) { - exchange.setProperty(MNSProperties.MESSAGE_ID, response.getMessageId()); + exchange.setProperty(MNSHeaders.MESSAGE_ID, response.getMessageId()); } if (ObjectHelper.isNotEmpty(response.getRequestId())) { exchange.setProperty(MNSProperties.REQUEST_ID, response.getRequestId()); } if (ObjectHelper.isNotEmpty(response.getMessageBodyMD5())) { - exchange.setProperty(MNSProperties.MESSAGE_BODY_MD5, response.getMessageBodyMD5()); + exchange.setProperty(MNSHeaders.MESSAGE_BODY_MD5, response.getMessageBodyMD5()); } } diff --git a/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSUtils.java b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSUtils.java index 486dcf98d4276..1a428dcdb2752 100644 --- a/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSUtils.java +++ b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/MNSUtils.java @@ -104,12 +104,9 @@ public static String resolveTopicName(MNSEndpoint endpoint, Exchange exchange) { } public static String resolveReceiptHandle(Exchange exchange) { - String receiptHandle = exchange.getProperty(MNSProperties.RECEIPT_HANDLE, String.class); + String receiptHandle = exchange.getIn().getHeader(MNSHeaders.RECEIPT_HANDLE, String.class); if (ObjectHelper.isEmpty(receiptHandle)) { - receiptHandle = exchange.getIn().getHeader(MNSProperties.RECEIPT_HANDLE, String.class); - } - if (ObjectHelper.isEmpty(receiptHandle)) { - receiptHandle = exchange.getIn().getHeader(MNSHeaders.RECEIPT_HANDLE, String.class); + receiptHandle = exchange.getProperty(MNSHeaders.RECEIPT_HANDLE, String.class); } return receiptHandle; } diff --git a/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/constants/MNSProperties.java b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/constants/MNSProperties.java index fa8c2cfc7865c..7337c68fedcf1 100644 --- a/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/constants/MNSProperties.java +++ b/components/camel-alibaba/camel-alibaba-mns/src/main/java/org/apache/camel/component/alibaba/mns/constants/MNSProperties.java @@ -21,11 +21,7 @@ public final class MNSProperties { public static final String OPERATION = "CamelAlibabaMnsOperation"; public static final String QUEUE_NAME = "CamelAlibabaMnsQueueName"; public static final String TOPIC_NAME = "CamelAlibabaMnsTopicName"; - public static final String RECEIPT_HANDLE = "CamelAlibabaMnsReceiptHandle"; - - public static final String MESSAGE_ID = "CamelAlibabaMnsMessageId"; public static final String REQUEST_ID = "CamelAlibabaMnsRequestId"; - public static final String MESSAGE_BODY_MD5 = "CamelAlibabaMnsMessageBodyMd5"; private MNSProperties() { } diff --git a/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/PublishMessageTest.java b/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/PublishMessageTest.java index beae467c6da66..41de43587f029 100644 --- a/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/PublishMessageTest.java +++ b/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/PublishMessageTest.java @@ -23,6 +23,7 @@ import org.apache.camel.BindToRegistry; import org.apache.camel.Exchange; import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.alibaba.mns.constants.MNSHeaders; import org.apache.camel.component.alibaba.mns.constants.MNSProperties; import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.test.junit6.CamelTestSupport; @@ -78,7 +79,7 @@ void testPublishMessage() throws Exception { mock.assertIsSatisfied(); Exchange exchange = mock.getExchanges().get(0); - assertThat(exchange.getProperty(MNSProperties.MESSAGE_ID)).isEqualTo("topic-message-id"); + assertThat(exchange.getProperty(MNSHeaders.MESSAGE_ID)).isEqualTo("topic-message-id"); assertThat(exchange.getProperty(MNSProperties.REQUEST_ID)).isEqualTo("topic-request-id"); verify(cloudTopic).publishMessage(any(TopicMessage.class)); diff --git a/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/SendMessageTest.java b/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/SendMessageTest.java index 98d11f885b986..a8d5a7d9d08bc 100644 --- a/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/SendMessageTest.java +++ b/components/camel-alibaba/camel-alibaba-mns/src/test/java/org/apache/camel/component/alibaba/mns/SendMessageTest.java @@ -22,6 +22,7 @@ import org.apache.camel.BindToRegistry; import org.apache.camel.Exchange; import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.alibaba.mns.constants.MNSHeaders; import org.apache.camel.component.alibaba.mns.constants.MNSProperties; import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.test.junit6.CamelTestSupport; @@ -78,9 +79,9 @@ void testSendMessage() throws Exception { mock.assertIsSatisfied(); Exchange exchange = mock.getExchanges().get(0); - assertThat(exchange.getProperty(MNSProperties.MESSAGE_ID)).isEqualTo("message-id-123"); + assertThat(exchange.getProperty(MNSHeaders.MESSAGE_ID)).isEqualTo("message-id-123"); assertThat(exchange.getProperty(MNSProperties.REQUEST_ID)).isEqualTo("request-id-456"); - assertThat(exchange.getProperty(MNSProperties.MESSAGE_BODY_MD5)).isEqualTo("md5-value"); + assertThat(exchange.getProperty(MNSHeaders.MESSAGE_BODY_MD5)).isEqualTo("md5-value"); verify(cloudQueue).putMessage(any(Message.class)); } diff --git a/components/camel-alibaba/camel-alibaba-oss/pom.xml b/components/camel-alibaba/camel-alibaba-oss/pom.xml index 98f0a5e19a6f6..430caa77ff573 100644 --- a/components/camel-alibaba/camel-alibaba-oss/pom.xml +++ b/components/camel-alibaba/camel-alibaba-oss/pom.xml @@ -55,11 +55,6 @@ ${alibabacloud-oss-version} - - com.google.code.gson - gson - - org.apache.camel camel-test-junit6 diff --git a/components/camel-alibaba/camel-alibaba-oss/src/generated/java/org/apache/camel/component/alibaba/oss/OSSEndpointConfigurer.java b/components/camel-alibaba/camel-alibaba-oss/src/generated/java/org/apache/camel/component/alibaba/oss/OSSEndpointConfigurer.java index 809b2e0558296..13274286f1519 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/generated/java/org/apache/camel/component/alibaba/oss/OSSEndpointConfigurer.java +++ b/components/camel-alibaba/camel-alibaba-oss/src/generated/java/org/apache/camel/component/alibaba/oss/OSSEndpointConfigurer.java @@ -33,8 +33,6 @@ public boolean configure(CamelContext camelContext, Object obj, String name, Obj case "backoffMultiplier": target.setBackoffMultiplier(property(camelContext, int.class, value)); return true; case "bridgeerrorhandler": case "bridgeErrorHandler": target.setBridgeErrorHandler(property(camelContext, boolean.class, value)); return true; - case "bucketname": - case "bucketName": target.setBucketName(property(camelContext, java.lang.String.class, value)); return true; case "delay": target.setDelay(property(camelContext, long.class, value)); return true; case "deleteafterread": case "deleteAfterRead": target.setDeleteAfterRead(property(camelContext, boolean.class, value)); return true; @@ -54,6 +52,7 @@ public boolean configure(CamelContext camelContext, Object obj, String name, Obj case "maxMessagesPerPoll": target.setMaxMessagesPerPoll(property(camelContext, int.class, value)); return true; case "objectname": case "objectName": target.setObjectName(property(camelContext, java.lang.String.class, value)); return true; + case "operation": target.setOperation(property(camelContext, java.lang.String.class, value)); return true; case "ossclient": case "ossClient": target.setOssClient(property(camelContext, com.aliyun.sdk.service.oss2.OSSClient.class, value)); return true; case "pollstrategy": @@ -103,8 +102,6 @@ public Class getOptionType(String name, boolean ignoreCase) { case "backoffMultiplier": return int.class; case "bridgeerrorhandler": case "bridgeErrorHandler": return boolean.class; - case "bucketname": - case "bucketName": return java.lang.String.class; case "delay": return long.class; case "deleteafterread": case "deleteAfterRead": return boolean.class; @@ -124,6 +121,7 @@ public Class getOptionType(String name, boolean ignoreCase) { case "maxMessagesPerPoll": return int.class; case "objectname": case "objectName": return java.lang.String.class; + case "operation": return java.lang.String.class; case "ossclient": case "ossClient": return com.aliyun.sdk.service.oss2.OSSClient.class; case "pollstrategy": @@ -169,8 +167,6 @@ public Object getOptionValue(Object obj, String name, boolean ignoreCase) { case "backoffMultiplier": return target.getBackoffMultiplier(); case "bridgeerrorhandler": case "bridgeErrorHandler": return target.isBridgeErrorHandler(); - case "bucketname": - case "bucketName": return target.getBucketName(); case "delay": return target.getDelay(); case "deleteafterread": case "deleteAfterRead": return target.isDeleteAfterRead(); @@ -190,6 +186,7 @@ public Object getOptionValue(Object obj, String name, boolean ignoreCase) { case "maxMessagesPerPoll": return target.getMaxMessagesPerPoll(); case "objectname": case "objectName": return target.getObjectName(); + case "operation": return target.getOperation(); case "ossclient": case "ossClient": return target.getOssClient(); case "pollstrategy": diff --git a/components/camel-alibaba/camel-alibaba-oss/src/generated/java/org/apache/camel/component/alibaba/oss/OSSEndpointUriFactory.java b/components/camel-alibaba/camel-alibaba-oss/src/generated/java/org/apache/camel/component/alibaba/oss/OSSEndpointUriFactory.java index 58f5aa728f357..d2b53b40c9b8e 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/generated/java/org/apache/camel/component/alibaba/oss/OSSEndpointUriFactory.java +++ b/components/camel-alibaba/camel-alibaba-oss/src/generated/java/org/apache/camel/component/alibaba/oss/OSSEndpointUriFactory.java @@ -17,7 +17,7 @@ @Generated("org.apache.camel.maven.packaging.GenerateEndpointUriFactoryMojo") public class OSSEndpointUriFactory extends org.apache.camel.support.component.EndpointUriFactorySupport implements EndpointUriFactory { - private static final String BASE = ":operation"; + private static final String BASE = ":bucketName"; private static final Set PROPERTY_NAMES; private static final Set SECRET_PROPERTY_NAMES; @@ -64,9 +64,7 @@ public class OSSEndpointUriFactory extends org.apache.camel.support.component.En secretProps.add("secretKey"); secretProps.add("serviceKeys"); SECRET_PROPERTY_NAMES = Collections.unmodifiableSet(secretProps); - Set identityProps = new HashSet<>(1); - identityProps.add("bucketName"); - ENDPOINT_IDENTITY_PROPERTY_NAMES = Collections.unmodifiableSet(identityProps); + ENDPOINT_IDENTITY_PROPERTY_NAMES = Collections.emptySet(); Map prefixes = new HashMap<>(1); prefixes.put("schedulerProperties", "scheduler."); MULTI_VALUE_PREFIXES = Collections.unmodifiableMap(prefixes); @@ -84,7 +82,7 @@ public String buildUri(String scheme, Map properties, boolean en Map copy = new HashMap<>(properties); - uri = buildPathParameter(syntax, uri, "operation", null, true, copy); + uri = buildPathParameter(syntax, uri, "bucketName", null, false, copy); uri = buildQueryParameters(uri, copy, encode); return uri; } diff --git a/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/org/apache/camel/component/alibaba/oss/alibaba-oss.json b/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/org/apache/camel/component/alibaba/oss/alibaba-oss.json index 1aca9c88089b3..2a48300a4ba0d 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/org/apache/camel/component/alibaba/oss/alibaba-oss.json +++ b/components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/org/apache/camel/component/alibaba/oss/alibaba-oss.json @@ -14,7 +14,7 @@ "version": "4.23.0-SNAPSHOT", "scheme": "alibaba-oss", "extendsScheme": "", - "syntax": "alibaba-oss:operation", + "syntax": "alibaba-oss:bucketName", "async": false, "api": false, "consumerOnly": false, @@ -42,20 +42,20 @@ "CamelFileName": { "index": 8, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the object with which the operation is to be performed", "constantName": "org.apache.camel.component.alibaba.oss.constants.OSSHeaders#FILE_NAME" } }, "properties": { - "operation": { "index": 0, "kind": "path", "displayName": "Operation", "group": "producer", "label": "producer", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Operation to be performed" }, - "bucketName": { "index": 1, "kind": "parameter", "displayName": "Bucket Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "endpointIdentity": true, "description": "Name of bucket to perform operation on" }, - "endpoint": { "index": 2, "kind": "parameter", "displayName": "Endpoint url", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "OSS endpoint URL. Carries higher precedence than region based client initialization" }, - "objectName": { "index": 3, "kind": "parameter", "displayName": "Object Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of object to perform operation with" }, - "region": { "index": 4, "kind": "parameter", "displayName": "Service region", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "OSS service region" }, - "deleteAfterRead": { "index": 5, "kind": "parameter", "displayName": "Delete after read", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Determines if objects should be deleted after they have been retrieved" }, - "maxMessagesPerPoll": { "index": 6, "kind": "parameter", "displayName": "Maximum messages per poll", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 10, "description": "The maximum number of messages to poll at each polling" }, - "prefix": { "index": 7, "kind": "parameter", "displayName": "Prefix", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The object name prefix used for filtering objects to be listed" }, - "sendEmptyMessageWhenIdle": { "index": 8, "kind": "parameter", "displayName": "Send Empty Message When Idle", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead." }, - "bridgeErrorHandler": { "index": 9, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, - "exceptionHandler": { "index": 10, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, - "exchangePattern": { "index": 11, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." }, - "pollStrategy": { "index": 12, "kind": "parameter", "displayName": "Poll Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.PollingConsumerPollStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "A pluggable org.apache.camel.PollingConsumerPollingStrategy allowing you to provide your custom implementation to control error handling usually occurred during the poll operation before an Exchange have been created and being routed in Camel." }, - "maxKeys": { "index": 13, "kind": "parameter", "displayName": "Max Keys", "group": "producer", "label": "consumer,producer", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "description": "The maximum number of keys returned when listing objects" }, + "bucketName": { "index": 0, "kind": "path", "displayName": "Bucket Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of bucket to perform operation on" }, + "endpoint": { "index": 1, "kind": "parameter", "displayName": "Endpoint url", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "OSS endpoint URL. Carries higher precedence than region based client initialization" }, + "objectName": { "index": 2, "kind": "parameter", "displayName": "Object Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of object to perform operation with" }, + "region": { "index": 3, "kind": "parameter", "displayName": "Service region", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "OSS service region" }, + "deleteAfterRead": { "index": 4, "kind": "parameter", "displayName": "Delete after read", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Determines if objects should be deleted after they have been retrieved" }, + "maxMessagesPerPoll": { "index": 5, "kind": "parameter", "displayName": "Maximum messages per poll", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 10, "description": "The maximum number of messages to poll at each polling" }, + "prefix": { "index": 6, "kind": "parameter", "displayName": "Prefix", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The object name prefix used for filtering objects to be listed" }, + "sendEmptyMessageWhenIdle": { "index": 7, "kind": "parameter", "displayName": "Send Empty Message When Idle", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead." }, + "bridgeErrorHandler": { "index": 8, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, + "exceptionHandler": { "index": 9, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, + "exchangePattern": { "index": 10, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." }, + "pollStrategy": { "index": 11, "kind": "parameter", "displayName": "Poll Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.PollingConsumerPollStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "A pluggable org.apache.camel.PollingConsumerPollingStrategy allowing you to provide your custom implementation to control error handling usually occurred during the poll operation before an Exchange have been created and being routed in Camel." }, + "maxKeys": { "index": 12, "kind": "parameter", "displayName": "Max Keys", "group": "producer", "label": "consumer,producer", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "description": "The maximum number of keys returned when listing objects" }, + "operation": { "index": 13, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "producer", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "listBuckets", "listObjects", "putObject", "getObject", "deleteObject", "copyObject", "headObject" ], "deprecated": false, "autowired": false, "secret": false, "description": "Operation to be performed" }, "lazyStartProducer": { "index": 14, "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 producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." }, "ossClient": { "index": 15, "kind": "parameter", "displayName": "OSS Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "com.aliyun.sdk.service.oss2.OSSClient", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "description": "An autowired OSS client" }, "backoffErrorThreshold": { "index": 16, "kind": "parameter", "displayName": "Backoff Error Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent error polls (failed due some error) that should happen before the backoffMultipler should kick-in." }, diff --git a/components/camel-alibaba/camel-alibaba-oss/src/main/docs/alibaba-oss-component.adoc b/components/camel-alibaba/camel-alibaba-oss/src/main/docs/alibaba-oss-component.adoc index f4aa8ee196639..5c48d5b101acb 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/main/docs/alibaba-oss-component.adoc +++ b/components/camel-alibaba/camel-alibaba-oss/src/main/docs/alibaba-oss-component.adoc @@ -31,9 +31,11 @@ Maven users will need to add the following dependency to their `pom.xml` for thi == URI Format ---- -alibaba-oss:operation[?options] +alibaba-oss:bucketName[?options] ---- +The `operation` query parameter selects the OSS operation to perform (for example `putObject`, `getObject`, `listObjects`). + // component options: START include::partial$component-configure-options.adoc[] include::partial$component-endpoint-options.adoc[] @@ -42,7 +44,7 @@ include::partial$component-endpoint-headers.adoc[] == Usage -=== Message properties evaluated by the OSS producer +=== Message headers evaluated by the OSS producer [width="100%",cols="10%,10%,80%",options="header",] |======================================================================= @@ -50,7 +52,7 @@ include::partial$component-endpoint-headers.adoc[] |`CamelAlibabaOssOperation` |`String` | Name of operation to invoke -|`CamelAlibabaOssBucketName` |`String` | Bucket name to invoke operation on +|`CamelAlibabaOssBucketName` |`String` | Bucket name to invoke operation on (overrides the URI path bucket name) |`CamelAlibabaOssObjectName` |`String` | Name of the object to be used in operation @@ -64,7 +66,7 @@ include::partial$component-endpoint-headers.adoc[] |======================================================================= -If any of the above properties are set, they will override their corresponding query parameter. +If any of the above headers are set, they will override their corresponding query parameter or URI path value. === List of Supported OSS Operations @@ -88,15 +90,16 @@ The consumer polls objects from a bucket using `listObjectsV2`, downloads each o ---- from("direct:start") .setBody(constant("Hello OSS")) - .setProperty("CamelAlibabaOssBucketName", constant("my-bucket")) - .setProperty("CamelAlibabaOssObjectName", constant("hello.txt")) - .to("alibaba-oss:putObject?region=cn-hangzhou&accessKey=xxx&secretKey=yyy"); + .setHeader("CamelAlibabaOssObjectName", constant("hello.txt")) + .to("alibaba-oss:my-bucket?operation=putObject®ion=cn-hangzhou&accessKey=xxx&secretKey=yyy"); ---- +Producer operations return structured response metadata in the message body (`Map` or `List` depending on the operation). + === Consume objects from a bucket [source,java] ---- -from("alibaba-oss:consumer?bucketName=my-bucket®ion=cn-hangzhou&accessKey=xxx&secretKey=yyy&deleteAfterRead=true") +from("alibaba-oss:my-bucket?region=cn-hangzhou&accessKey=xxx&secretKey=yyy&deleteAfterRead=true") .to("log:output"); ---- diff --git a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSEndpoint.java b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSEndpoint.java index dd6eb037ce8a2..a40a3d573eb14 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSEndpoint.java +++ b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSEndpoint.java @@ -33,12 +33,15 @@ * Alibaba Cloud Object Storage Service (OSS) component */ @UriEndpoint(firstVersion = "4.23.0", scheme = "alibaba-oss", title = "Alibaba Object Storage Service (OSS)", - syntax = "alibaba-oss:operation", + syntax = "alibaba-oss:bucketName", category = { Category.CLOUD }, headersClass = OSSHeaders.class) public class OSSEndpoint extends ScheduledPollEndpoint { - @UriPath(description = "Operation to be performed", displayName = "Operation", label = "producer") - @Metadata(required = true) + @UriPath(description = "Name of bucket to perform operation on", displayName = "Bucket Name") + private String bucketName; + + @UriParam(description = "Operation to be performed", displayName = "Operation", label = "producer", + enums = "listBuckets,listObjects,putObject,getObject,deleteObject,copyObject,headObject") private String operation; @UriParam(description = "OSS service region", displayName = "Service region") @@ -50,22 +53,19 @@ public class OSSEndpoint extends ScheduledPollEndpoint { private String endpoint; @UriParam(description = "Configuration object for cloud service authentication", displayName = "Service Configuration", - security = "secret", label = "security") + secret = true, security = "secret", label = "security") private ServiceKeys serviceKeys; @UriParam(description = "Access key for the cloud user", displayName = "API access key (AK)", - security = "secret", label = "security") + secret = true, security = "secret", label = "security") @Metadata(required = true) private String accessKey; @UriParam(description = "Secret key for the cloud user", displayName = "API secret key (SK)", - security = "secret", label = "security") + secret = true, security = "secret", label = "security") @Metadata(required = true) private String secretKey; - @UriParam(description = "Name of bucket to perform operation on", displayName = "Bucket Name", endpointIdentity = true) - private String bucketName; - @UriParam(description = "Name of object to perform operation with", displayName = "Object Name") private String objectName; @@ -94,9 +94,9 @@ public class OSSEndpoint extends ScheduledPollEndpoint { public OSSEndpoint() { } - public OSSEndpoint(String uri, String operation, OSSComponent component) { + public OSSEndpoint(String uri, String bucketName, OSSComponent component) { super(uri, component); - this.operation = operation; + this.bucketName = bucketName; } @Override diff --git a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSProducer.java b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSProducer.java index 4f7b1bd78d0b5..07b02d0109804 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSProducer.java +++ b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSProducer.java @@ -41,11 +41,9 @@ import com.aliyun.sdk.service.oss2.models.PutObjectRequest; import com.aliyun.sdk.service.oss2.models.PutObjectResult; import com.aliyun.sdk.service.oss2.transport.BinaryData; -import com.google.gson.Gson; import org.apache.camel.Exchange; import org.apache.camel.WrappedFile; import org.apache.camel.component.alibaba.oss.constants.OSSOperations; -import org.apache.camel.component.alibaba.oss.constants.OSSProperties; import org.apache.camel.component.alibaba.oss.models.ClientConfigurations; import org.apache.camel.support.DefaultProducer; import org.apache.camel.util.ObjectHelper; @@ -57,29 +55,20 @@ public class OSSProducer extends DefaultProducer { private final OSSEndpoint endpoint; private OSSClient ossClient; - private Gson gson; public OSSProducer(OSSEndpoint endpoint) { super(endpoint); this.endpoint = endpoint; } - @Override - protected void doInit() throws Exception { - super.doInit(); - this.gson = new Gson(); - } - @Override public void process(Exchange exchange) throws Exception { - ClientConfigurations clientConfigurations = new ClientConfigurations(); + ClientConfigurations clientConfigurations = OSSUtils.createClientConfigurations(endpoint, exchange); if (ossClient == null) { this.ossClient = endpoint.initClient(); } - updateClientConfigs(exchange, clientConfigurations); - switch (clientConfigurations.getOperation()) { case OSSOperations.LIST_BUCKETS: listBuckets(exchange); @@ -133,32 +122,32 @@ private void putObject(Exchange exchange, ClientConfigurations clientConfigurati requestBuilder.key(objectName); PutObjectResult result = ossClient.putObjectFromFile(requestBuilder.build(), file); exchange.getMessage() - .setBody(gson.toJson(toPutObjectMap(result, clientConfigurations.getBucketName(), objectName))); + .setBody(toPutObjectMap(result, clientConfigurations.getBucketName(), objectName)); } else if (body instanceof String stringBody) { requestBuilder.key(clientConfigurations.getObjectName()) .body(BinaryData.fromString(stringBody)); PutObjectResult result = ossClient.putObject(requestBuilder.build()); - exchange.getMessage().setBody(gson.toJson(toPutObjectMap(result, clientConfigurations.getBucketName(), - clientConfigurations.getObjectName()))); + exchange.getMessage().setBody(toPutObjectMap(result, clientConfigurations.getBucketName(), + clientConfigurations.getObjectName())); } else if (body instanceof InputStream inputStream) { requestBuilder.key(clientConfigurations.getObjectName()) .body(BinaryData.fromStream(inputStream)); PutObjectResult result = ossClient.putObject(requestBuilder.build()); - exchange.getMessage().setBody(gson.toJson(toPutObjectMap(result, clientConfigurations.getBucketName(), - clientConfigurations.getObjectName()))); + exchange.getMessage().setBody(toPutObjectMap(result, clientConfigurations.getBucketName(), + clientConfigurations.getObjectName())); } else if (body instanceof byte[] bytes) { requestBuilder.key(clientConfigurations.getObjectName()) .body(BinaryData.fromBytes(bytes)); PutObjectResult result = ossClient.putObject(requestBuilder.build()); - exchange.getMessage().setBody(gson.toJson(toPutObjectMap(result, clientConfigurations.getBucketName(), - clientConfigurations.getObjectName()))); + exchange.getMessage().setBody(toPutObjectMap(result, clientConfigurations.getBucketName(), + clientConfigurations.getObjectName())); } else { InputStream is = exchange.getMessage().getMandatoryBody(InputStream.class); requestBuilder.key(clientConfigurations.getObjectName()) .body(BinaryData.fromStream(is)); PutObjectResult result = ossClient.putObject(requestBuilder.build()); - exchange.getMessage().setBody(gson.toJson(toPutObjectMap(result, clientConfigurations.getBucketName(), - clientConfigurations.getObjectName()))); + exchange.getMessage().setBody(toPutObjectMap(result, clientConfigurations.getBucketName(), + clientConfigurations.getObjectName())); } } @@ -202,7 +191,7 @@ private void listBuckets(Exchange exchange) { buckets.add(bucketMap); } } - exchange.getMessage().setBody(gson.toJson(buckets)); + exchange.getMessage().setBody(buckets); } private void listObjects(Exchange exchange, ClientConfigurations clientConfigurations) { @@ -252,7 +241,7 @@ private void listObjects(Exchange exchange, ClientConfigurations clientConfigura } } while (Boolean.TRUE.equals(result.isTruncated())); - exchange.getMessage().setBody(gson.toJson(objects)); + exchange.getMessage().setBody(objects); } private void deleteObject(Exchange exchange, ClientConfigurations clientConfigurations) { @@ -271,7 +260,7 @@ private void deleteObject(Exchange exchange, ClientConfigurations clientConfigur map.put("requestId", result.requestId()); map.put("deleteMarker", result.deleteMarker()); map.put("versionId", result.versionId()); - exchange.getMessage().setBody(gson.toJson(map)); + exchange.getMessage().setBody(map); } private void copyObject(Exchange exchange, ClientConfigurations clientConfigurations) { @@ -295,7 +284,7 @@ private void copyObject(Exchange exchange, ClientConfigurations clientConfigurat map.put("lastModified", result.lastModified()); map.put("statusCode", result.statusCode()); map.put("requestId", result.requestId()); - exchange.getMessage().setBody(gson.toJson(map)); + exchange.getMessage().setBody(map); } private void headObject(Exchange exchange, ClientConfigurations clientConfigurations) { @@ -319,59 +308,6 @@ private void headObject(Exchange exchange, ClientConfigurations clientConfigurat map.put("metadata", result.metadata()); map.put("statusCode", result.statusCode()); map.put("requestId", result.requestId()); - exchange.getMessage().setBody(gson.toJson(map)); - } - - private void updateClientConfigs(Exchange exchange, ClientConfigurations clientConfigurations) { - if (ObjectHelper.isEmpty(exchange.getProperty(OSSProperties.OPERATION)) - && ObjectHelper.isEmpty(endpoint.getOperation())) { - LOG.error("No operation name given. Cannot proceed with OSS operations."); - throw new IllegalArgumentException("Operation name not found"); - } else { - clientConfigurations.setOperation( - ObjectHelper.isNotEmpty(exchange.getProperty(OSSProperties.OPERATION)) - ? (String) exchange.getProperty(OSSProperties.OPERATION) - : endpoint.getOperation()); - } - - if (ObjectHelper.isNotEmpty(exchange.getProperty(OSSProperties.BUCKET_NAME)) - || ObjectHelper.isNotEmpty(endpoint.getBucketName())) { - clientConfigurations.setBucketName( - ObjectHelper.isNotEmpty(exchange.getProperty(OSSProperties.BUCKET_NAME)) - ? (String) exchange.getProperty(OSSProperties.BUCKET_NAME) - : endpoint.getBucketName()); - } - - if (ObjectHelper.isNotEmpty(exchange.getProperty(OSSProperties.OBJECT_NAME)) - || ObjectHelper.isNotEmpty(endpoint.getObjectName())) { - clientConfigurations.setObjectName( - ObjectHelper.isNotEmpty(exchange.getProperty(OSSProperties.OBJECT_NAME)) - ? (String) exchange.getProperty(OSSProperties.OBJECT_NAME) - : endpoint.getObjectName()); - } - - if (ObjectHelper.isNotEmpty(exchange.getProperty(OSSProperties.SOURCE_BUCKET_NAME))) { - clientConfigurations.setSourceBucketName((String) exchange.getProperty(OSSProperties.SOURCE_BUCKET_NAME)); - } - - if (ObjectHelper.isNotEmpty(exchange.getProperty(OSSProperties.SOURCE_OBJECT_NAME))) { - clientConfigurations.setSourceObjectName((String) exchange.getProperty(OSSProperties.SOURCE_OBJECT_NAME)); - } - - if (ObjectHelper.isNotEmpty(exchange.getProperty(OSSProperties.PREFIX)) - || ObjectHelper.isNotEmpty(endpoint.getPrefix())) { - clientConfigurations.setPrefix( - ObjectHelper.isNotEmpty(exchange.getProperty(OSSProperties.PREFIX)) - ? (String) exchange.getProperty(OSSProperties.PREFIX) - : endpoint.getPrefix()); - } - - if (ObjectHelper.isNotEmpty(exchange.getProperty(OSSProperties.MAX_KEYS)) - || ObjectHelper.isNotEmpty(endpoint.getMaxKeys())) { - clientConfigurations.setMaxKeys( - ObjectHelper.isNotEmpty(exchange.getProperty(OSSProperties.MAX_KEYS)) - ? (Integer) exchange.getProperty(OSSProperties.MAX_KEYS) - : endpoint.getMaxKeys()); - } + exchange.getMessage().setBody(map); } } diff --git a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSUtils.java b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSUtils.java index 8d96afb404b0f..d6986a5807839 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSUtils.java +++ b/components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSUtils.java @@ -30,12 +30,83 @@ import org.apache.camel.component.alibaba.common.models.ServiceKeys; import org.apache.camel.component.alibaba.oss.constants.OSSConstants; import org.apache.camel.component.alibaba.oss.constants.OSSHeaders; +import org.apache.camel.component.alibaba.oss.constants.OSSProperties; +import org.apache.camel.component.alibaba.oss.models.ClientConfigurations; import org.apache.camel.util.ObjectHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public final class OSSUtils { + private static final Logger LOG = LoggerFactory.getLogger(OSSUtils.class); + private OSSUtils() { } + public static ClientConfigurations createClientConfigurations(OSSEndpoint endpoint, Exchange exchange) { + ClientConfigurations clientConfigurations = new ClientConfigurations(); + + String operation = resolveString(exchange, OSSProperties.OPERATION, endpoint.getOperation()); + if (ObjectHelper.isEmpty(operation)) { + LOG.error("No operation name given. Cannot proceed with OSS operations."); + throw new IllegalArgumentException("Operation name not found"); + } + clientConfigurations.setOperation(operation); + + String bucketName = resolveString(exchange, OSSProperties.BUCKET_NAME, endpoint.getBucketName()); + if (ObjectHelper.isNotEmpty(bucketName)) { + clientConfigurations.setBucketName(bucketName); + } + + String objectName = resolveString(exchange, OSSProperties.OBJECT_NAME, endpoint.getObjectName()); + if (ObjectHelper.isNotEmpty(objectName)) { + clientConfigurations.setObjectName(objectName); + } + + String sourceBucketName = resolveString(exchange, OSSProperties.SOURCE_BUCKET_NAME, null); + if (ObjectHelper.isNotEmpty(sourceBucketName)) { + clientConfigurations.setSourceBucketName(sourceBucketName); + } + + String sourceObjectName = resolveString(exchange, OSSProperties.SOURCE_OBJECT_NAME, null); + if (ObjectHelper.isNotEmpty(sourceObjectName)) { + clientConfigurations.setSourceObjectName(sourceObjectName); + } + + String prefix = resolveString(exchange, OSSProperties.PREFIX, endpoint.getPrefix()); + if (ObjectHelper.isNotEmpty(prefix)) { + clientConfigurations.setPrefix(prefix); + } + + Integer maxKeys = resolveInteger(exchange, OSSProperties.MAX_KEYS, endpoint.getMaxKeys()); + if (maxKeys != null) { + clientConfigurations.setMaxKeys(maxKeys); + } + + return clientConfigurations; + } + + private static String resolveString(Exchange exchange, String name, String endpointValue) { + String value = exchange.getIn().getHeader(name, String.class); + if (ObjectHelper.isEmpty(value)) { + value = exchange.getProperty(name, String.class); + } + if (ObjectHelper.isEmpty(value)) { + value = endpointValue; + } + return value; + } + + private static Integer resolveInteger(Exchange exchange, String name, Integer endpointValue) { + Integer value = exchange.getIn().getHeader(name, Integer.class); + if (value == null) { + value = exchange.getProperty(name, Integer.class); + } + if (value == null) { + value = endpointValue; + } + return value; + } + /** * Maps the OSS object along with all its metadata into the exchange */ diff --git a/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/DeleteObjectTest.java b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/DeleteObjectTest.java index ae295d97e0a11..432a492c969a6 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/DeleteObjectTest.java +++ b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/DeleteObjectTest.java @@ -16,6 +16,8 @@ */ package org.apache.camel.component.alibaba.oss; +import java.util.Map; + import com.aliyun.sdk.service.oss2.OSSClient; import com.aliyun.sdk.service.oss2.models.DeleteObjectRequest; import com.aliyun.sdk.service.oss2.models.DeleteObjectResult; @@ -49,10 +51,9 @@ protected RouteBuilder createRouteBuilder() { @Override public void configure() { from("direct:delete_object") - .setProperty(OSSProperties.BUCKET_NAME, constant(testConfiguration.getProperty("bucketName"))) - .setProperty(OSSProperties.OBJECT_NAME, constant(testConfiguration.getProperty("objectName"))) - .to("alibaba-oss:deleteObject?" + - "serviceKeys=#serviceKeys" + + .setHeader(OSSProperties.OBJECT_NAME, constant(testConfiguration.getProperty("objectName"))) + .to("alibaba-oss:" + testConfiguration.getProperty("bucketName") + "?operation=deleteObject" + + "&serviceKeys=#serviceKeys" + "®ion=" + testConfiguration.getProperty("region") + "&ossClient=#ossClient") .to("mock:delete_object_result"); @@ -77,8 +78,10 @@ void testDeleteObject() throws Exception { mock.assertIsSatisfied(); - assertThat(responseExchange.getIn().getBody(String.class)) - .contains("\"statusCode\":204") - .contains("\"requestId\":\"request-id-123\""); + @SuppressWarnings("unchecked") + Map body = responseExchange.getIn().getBody(Map.class); + assertThat(body) + .containsEntry("statusCode", 204) + .containsEntry("requestId", "request-id-123"); } } diff --git a/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/GetObjectTest.java b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/GetObjectTest.java index dd75099c6028b..69766dd2f30f2 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/GetObjectTest.java +++ b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/GetObjectTest.java @@ -56,11 +56,9 @@ protected RouteBuilder createRouteBuilder() { @Override public void configure() { from("direct:get_object") - .setProperty(OSSProperties.BUCKET_NAME, constant(bucketName)) - .setProperty(OSSProperties.OBJECT_NAME, constant(objectName)) - .to("alibaba-oss:getObject?" + - "accessKey=" + testConfiguration.getProperty("accessKey") + - "&secretKey=" + testConfiguration.getProperty("secretKey") + + .setHeader(OSSProperties.OBJECT_NAME, constant(objectName)) + .to("alibaba-oss:" + bucketName + "?operation=getObject" + + "&serviceKeys=#serviceKeys" + "®ion=" + testConfiguration.getProperty("region") + "&ossClient=#ossClient") .to("mock:get_object_result"); diff --git a/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/HeadObjectTest.java b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/HeadObjectTest.java index 099e5d990592c..2ffe8c42ea0c7 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/HeadObjectTest.java +++ b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/HeadObjectTest.java @@ -16,6 +16,8 @@ */ package org.apache.camel.component.alibaba.oss; +import java.util.Map; + import com.aliyun.sdk.service.oss2.OSSClient; import com.aliyun.sdk.service.oss2.models.HeadObjectRequest; import com.aliyun.sdk.service.oss2.models.HeadObjectResult; @@ -49,10 +51,9 @@ protected RouteBuilder createRouteBuilder() { @Override public void configure() { from("direct:head_object") - .setProperty(OSSProperties.BUCKET_NAME, constant(testConfiguration.getProperty("bucketName"))) - .setProperty(OSSProperties.OBJECT_NAME, constant(testConfiguration.getProperty("objectName"))) - .to("alibaba-oss:headObject?" + - "serviceKeys=#serviceKeys" + + .setHeader(OSSProperties.OBJECT_NAME, constant(testConfiguration.getProperty("objectName"))) + .to("alibaba-oss:" + testConfiguration.getProperty("bucketName") + "?operation=headObject" + + "&serviceKeys=#serviceKeys" + "®ion=" + testConfiguration.getProperty("region") + "&ossClient=#ossClient") .to("mock:head_object_result"); @@ -82,10 +83,12 @@ void testHeadObject() throws Exception { mock.assertIsSatisfied(); - assertThat(responseExchange.getIn().getBody(String.class)) - .contains("\"eTag\":\"eb733a00c0c9d336e65691a37ab54293\"") - .contains("\"contentLength\":1024") - .contains("\"contentType\":\"text/plain\"") - .contains("\"storageClass\":\"Standard\""); + @SuppressWarnings("unchecked") + Map body = responseExchange.getIn().getBody(Map.class); + assertThat(body) + .containsEntry("eTag", "eb733a00c0c9d336e65691a37ab54293") + .containsEntry("contentLength", 1024L) + .containsEntry("contentType", "text/plain") + .containsEntry("storageClass", "Standard"); } } diff --git a/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/ListObjectsTest.java b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/ListObjectsTest.java index c289c10d6d4c7..c258f337af1a9 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/ListObjectsTest.java +++ b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/ListObjectsTest.java @@ -18,6 +18,7 @@ import java.time.Instant; import java.util.List; +import java.util.Map; import com.aliyun.sdk.service.oss2.OSSClient; import com.aliyun.sdk.service.oss2.models.ListObjectsRequest; @@ -27,7 +28,6 @@ import org.apache.camel.Exchange; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.alibaba.common.models.ServiceKeys; -import org.apache.camel.component.alibaba.oss.constants.OSSProperties; import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.test.junit6.CamelTestSupport; import org.junit.jupiter.api.Test; @@ -53,9 +53,8 @@ protected RouteBuilder createRouteBuilder() { @Override public void configure() { from("direct:list_objects") - .setProperty(OSSProperties.BUCKET_NAME, constant(testConfiguration.getProperty("bucketName"))) - .to("alibaba-oss:listObjects?" + - "serviceKeys=#serviceKeys" + + .to("alibaba-oss:" + testConfiguration.getProperty("bucketName") + "?operation=listObjects" + + "&serviceKeys=#serviceKeys" + "®ion=" + testConfiguration.getProperty("region") + "&ossClient=#ossClient") .to("mock:list_objects_result"); @@ -91,9 +90,12 @@ void testListObjects() throws Exception { mock.assertIsSatisfied(); - assertThat(responseExchange.getIn().getBody(String.class)) - .contains("\"objectKey\":\"Object 1\"") - .contains("\"objectKey\":\"Object 2\"") - .contains("\"bucketName\":\"dummy_bucket_name\""); + @SuppressWarnings("unchecked") + List> body = responseExchange.getIn().getBody(List.class); + assertThat(body).hasSize(2); + assertThat(body.get(0)) + .containsEntry("objectKey", "Object 1") + .containsEntry("bucketName", "dummy_bucket_name"); + assertThat(body.get(1)).containsEntry("objectKey", "Object 2"); } } diff --git a/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/PutObjectTest.java b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/PutObjectTest.java index 29bad18384f19..cc13342b4ddcb 100644 --- a/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/PutObjectTest.java +++ b/components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/PutObjectTest.java @@ -16,6 +16,8 @@ */ package org.apache.camel.component.alibaba.oss; +import java.util.Map; + import com.aliyun.sdk.service.oss2.OSSClient; import com.aliyun.sdk.service.oss2.models.PutObjectRequest; import com.aliyun.sdk.service.oss2.models.PutObjectResult; @@ -50,10 +52,9 @@ protected RouteBuilder createRouteBuilder() { public void configure() { from("direct:put_object") .setBody(constant("a test string")) - .setProperty(OSSProperties.OBJECT_NAME, constant("string_file.txt")) - .setProperty(OSSProperties.BUCKET_NAME, constant("test-bucket")) - .to("alibaba-oss:putObject?" + - "serviceKeys=#serviceKeys" + + .setHeader(OSSProperties.OBJECT_NAME, constant("string_file.txt")) + .to("alibaba-oss:test-bucket?operation=putObject" + + "&serviceKeys=#serviceKeys" + "®ion=" + testConfiguration.getProperty("region") + "&ossClient=#ossClient") .to("mock:put_object_result"); @@ -79,9 +80,11 @@ void putObjectStringTest() throws Exception { mock.assertIsSatisfied(); - assertThat(responseExchange.getIn().getBody(String.class)) - .contains("\"bucketName\":\"test-bucket\"") - .contains("\"objectKey\":\"string_file.txt\"") - .contains("\"eTag\":\"eb733a00c0c9d336e65691a37ab54293\""); + @SuppressWarnings("unchecked") + Map body = responseExchange.getIn().getBody(Map.class); + assertThat(body) + .containsEntry("bucketName", "test-bucket") + .containsEntry("objectKey", "string_file.txt") + .containsEntry("eTag", "eb733a00c0c9d336e65691a37ab54293"); } } From 8c1f5f465685897cdd934986ca56607ff0136666 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 12 Aug 2026 16:43:40 +0000 Subject: [PATCH 12/12] CAMEL-24373: Regenerate DSL, nav, and doc symlinks for alibaba components Commit generated files produced by the regen build so CI "Fail if there are uncommitted changes" passes. Co-authored-by: Cursor Agent --- .../ROOT/examples/json/alibaba-mns.json | 1 + .../ROOT/examples/json/alibaba-oss.json | 1 + docs/components/modules/ROOT/nav.adoc | 2 + .../ROOT/pages/alibaba-mns-component.adoc | 1 + .../ROOT/pages/alibaba-oss-component.adoc | 1 + .../others/examples/json/alibaba-common.json | 1 + .../component/ComponentsBuilderFactory.java | 26 + .../AlibabaMnsComponentBuilderFactory.java | 189 ++ .../AlibabaOssComponentBuilderFactory.java | 189 ++ .../endpoint/EndpointBuilderFactory.java | 2 + .../builder/endpoint/EndpointBuilders.java | 2 + .../endpoint/EndpointHeaderBuilders.java | 26 + .../endpoint/StaticEndpointBuilders.java | 80 + .../dsl/MNSEndpointBuilderFactory.java | 1581 +++++++++++++++++ .../dsl/OSSEndpointBuilderFactory.java | 1470 +++++++++++++++ ...el-component-known-dependencies.properties | 2 + 16 files changed, 3574 insertions(+) create mode 120000 docs/components/modules/ROOT/examples/json/alibaba-mns.json create mode 120000 docs/components/modules/ROOT/examples/json/alibaba-oss.json create mode 120000 docs/components/modules/ROOT/pages/alibaba-mns-component.adoc create mode 120000 docs/components/modules/ROOT/pages/alibaba-oss-component.adoc create mode 120000 docs/components/modules/others/examples/json/alibaba-common.json create mode 100644 dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/AlibabaMnsComponentBuilderFactory.java create mode 100644 dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/AlibabaOssComponentBuilderFactory.java create mode 100644 dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/MNSEndpointBuilderFactory.java create mode 100644 dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/OSSEndpointBuilderFactory.java diff --git a/docs/components/modules/ROOT/examples/json/alibaba-mns.json b/docs/components/modules/ROOT/examples/json/alibaba-mns.json new file mode 120000 index 0000000000000..42ecf71c523d5 --- /dev/null +++ b/docs/components/modules/ROOT/examples/json/alibaba-mns.json @@ -0,0 +1 @@ +../../../../../../components/camel-alibaba/camel-alibaba-mns/src/generated/resources/META-INF/org/apache/camel/component/alibaba/mns/alibaba-mns.json \ No newline at end of file diff --git a/docs/components/modules/ROOT/examples/json/alibaba-oss.json b/docs/components/modules/ROOT/examples/json/alibaba-oss.json new file mode 120000 index 0000000000000..7718ad8e320d1 --- /dev/null +++ b/docs/components/modules/ROOT/examples/json/alibaba-oss.json @@ -0,0 +1 @@ +../../../../../../components/camel-alibaba/camel-alibaba-oss/src/generated/resources/META-INF/org/apache/camel/component/alibaba/oss/alibaba-oss.json \ No newline at end of file diff --git a/docs/components/modules/ROOT/nav.adoc b/docs/components/modules/ROOT/nav.adoc index f92937294b7f8..ccb3d1bc1d5dd 100644 --- a/docs/components/modules/ROOT/nav.adoc +++ b/docs/components/modules/ROOT/nav.adoc @@ -31,6 +31,8 @@ *** xref:spring-ai-vector-store-component.adoc[Spring AI Vector Store] *** xref:tensorflow-serving-component.adoc[TensorFlow Serving] *** xref:weaviate-component.adoc[weaviate] +*** xref:alibaba-mns-component.adoc[Alibaba Message Service (MNS)] +*** xref:alibaba-oss-component.adoc[Alibaba Object Storage Service (OSS)] ** xref:amqp-component.adoc[AMQP] ** xref:arangodb-component.adoc[ArangoDb] ** xref:as2-component.adoc[AS2] diff --git a/docs/components/modules/ROOT/pages/alibaba-mns-component.adoc b/docs/components/modules/ROOT/pages/alibaba-mns-component.adoc new file mode 120000 index 0000000000000..560a74c915f1e --- /dev/null +++ b/docs/components/modules/ROOT/pages/alibaba-mns-component.adoc @@ -0,0 +1 @@ +../../../../../components/camel-alibaba/camel-alibaba-mns/src/main/docs/alibaba-mns-component.adoc \ No newline at end of file diff --git a/docs/components/modules/ROOT/pages/alibaba-oss-component.adoc b/docs/components/modules/ROOT/pages/alibaba-oss-component.adoc new file mode 120000 index 0000000000000..d6689e910f2cb --- /dev/null +++ b/docs/components/modules/ROOT/pages/alibaba-oss-component.adoc @@ -0,0 +1 @@ +../../../../../components/camel-alibaba/camel-alibaba-oss/src/main/docs/alibaba-oss-component.adoc \ No newline at end of file diff --git a/docs/components/modules/others/examples/json/alibaba-common.json b/docs/components/modules/others/examples/json/alibaba-common.json new file mode 120000 index 0000000000000..9df51baf4ca91 --- /dev/null +++ b/docs/components/modules/others/examples/json/alibaba-common.json @@ -0,0 +1 @@ +../../../../../../components/camel-alibaba/camel-alibaba-common/src/generated/resources/alibaba-common.json \ No newline at end of file diff --git a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java index edc584617f641..d622bfcb62864 100644 --- a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java +++ b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java @@ -100,6 +100,32 @@ static Activemq6ComponentBuilderFactory.Activemq6ComponentBuilder activemq6() { static AiToolComponentBuilderFactory.AiToolComponentBuilder aiTool() { return AiToolComponentBuilderFactory.aiTool(); } + /** + * Alibaba Message Service (MNS) (camel-alibaba-mns) + * Send and receive messages to/from Alibaba Cloud Message Service (MNS). + * + * Category: cloud,messaging + * Since: 4.23 + * Maven coordinates: org.apache.camel:camel-alibaba-mns + * + * @return the dsl builder + */ + static AlibabaMnsComponentBuilderFactory.AlibabaMnsComponentBuilder alibabaMns() { + return AlibabaMnsComponentBuilderFactory.alibabaMns(); + } + /** + * Alibaba Object Storage Service (OSS) (camel-alibaba-oss) + * Alibaba Cloud Object Storage Service (OSS) component + * + * Category: cloud + * Since: 4.23 + * Maven coordinates: org.apache.camel:camel-alibaba-oss + * + * @return the dsl builder + */ + static AlibabaOssComponentBuilderFactory.AlibabaOssComponentBuilder alibabaOss() { + return AlibabaOssComponentBuilderFactory.alibabaOss(); + } /** * AMQP (camel-amqp) * Messaging with AMQP protocol using Apache Qpid Client. diff --git a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/AlibabaMnsComponentBuilderFactory.java b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/AlibabaMnsComponentBuilderFactory.java new file mode 100644 index 0000000000000..2f50e83bae7e4 --- /dev/null +++ b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/AlibabaMnsComponentBuilderFactory.java @@ -0,0 +1,189 @@ +/* Generated by camel build tools - do NOT edit this file! */ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.builder.component.dsl; + +import javax.annotation.processing.Generated; +import org.apache.camel.Component; +import org.apache.camel.builder.component.AbstractComponentBuilder; +import org.apache.camel.builder.component.ComponentBuilder; +import org.apache.camel.component.alibaba.mns.MNSComponent; + +/** + * Send and receive messages to/from Alibaba Cloud Message Service (MNS). + * + * Generated by camel build tools - do NOT edit this file! + */ +@Generated("org.apache.camel.maven.packaging.ComponentDslMojo") +public interface AlibabaMnsComponentBuilderFactory { + + /** + * Alibaba Message Service (MNS) (camel-alibaba-mns) + * Send and receive messages to/from Alibaba Cloud Message Service (MNS). + * + * Category: cloud,messaging + * Since: 4.23 + * Maven coordinates: org.apache.camel:camel-alibaba-mns + * + * @return the dsl builder + */ + static AlibabaMnsComponentBuilder alibabaMns() { + return new AlibabaMnsComponentBuilderImpl(); + } + + /** + * Builder for the Alibaba Message Service (MNS) component. + */ + interface AlibabaMnsComponentBuilder extends ComponentBuilder { + + + /** + * Allows for bridging the consumer to the Camel routing Error Handler, + * which mean any exceptions (if possible) occurred while the Camel + * consumer is trying to pickup incoming messages, or the likes, will + * now be processed as a message and handled by the routing Error + * Handler. Important: This is only possible if the 3rd party component + * allows Camel to be alerted if an exception was thrown. Some + * components handle this internally only, and therefore + * bridgeErrorHandler is not possible. In other situations we may + * improve the Camel component to hook into the 3rd party component and + * make this possible for future releases. By default the consumer will + * use the org.apache.camel.spi.ExceptionHandler to deal with + * exceptions, that will be logged at WARN or ERROR level and ignored. + * + * The option is a: <code>boolean</code> type. + * + * Default: false + * Group: consumer + * + * @param bridgeErrorHandler the value to set + * @return the dsl builder + */ + default AlibabaMnsComponentBuilder bridgeErrorHandler(boolean bridgeErrorHandler) { + doSetProperty("bridgeErrorHandler", bridgeErrorHandler); + return this; + } + + + /** + * 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 during + * starting and cause the route to fail being started. By deferring this + * startup to be lazy then the startup failure can be handled during + * routing messages via Camel's routing error handlers. Beware that when + * the first message is processed then creating and starting the + * producer may take a little time and prolong the total processing time + * of the processing. + * + * The option is a: <code>boolean</code> type. + * + * Default: false + * Group: producer + * + * @param lazyStartProducer the value to set + * @return the dsl builder + */ + default AlibabaMnsComponentBuilder lazyStartProducer(boolean lazyStartProducer) { + doSetProperty("lazyStartProducer", lazyStartProducer); + return this; + } + + + /** + * Whether autowiring is enabled. This is used for automatic autowiring + * options (the option must be marked as autowired) by looking up in the + * registry to find if there is a single instance of matching type, + * which then gets configured on the component. This can be used for + * automatic configuring JDBC data sources, JMS connection factories, + * AWS Clients, etc. + * + * The option is a: <code>boolean</code> type. + * + * Default: true + * Group: advanced + * + * @param autowiredEnabled the value to set + * @return the dsl builder + */ + default AlibabaMnsComponentBuilder autowiredEnabled(boolean autowiredEnabled) { + doSetProperty("autowiredEnabled", autowiredEnabled); + return this; + } + + + /** + * Used for enabling or disabling all consumer based health checks from + * this component. + * + * The option is a: <code>boolean</code> type. + * + * Default: true + * Group: health + * + * @param healthCheckConsumerEnabled the value to set + * @return the dsl builder + */ + default AlibabaMnsComponentBuilder healthCheckConsumerEnabled(boolean healthCheckConsumerEnabled) { + doSetProperty("healthCheckConsumerEnabled", healthCheckConsumerEnabled); + return this; + } + + + /** + * 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 producer checks globally by + * setting camel.health.producersEnabled=true. + * + * The option is a: <code>boolean</code> type. + * + * Default: true + * Group: health + * + * @param healthCheckProducerEnabled the value to set + * @return the dsl builder + */ + default AlibabaMnsComponentBuilder healthCheckProducerEnabled(boolean healthCheckProducerEnabled) { + doSetProperty("healthCheckProducerEnabled", healthCheckProducerEnabled); + return this; + } + } + + class AlibabaMnsComponentBuilderImpl + extends AbstractComponentBuilder + implements AlibabaMnsComponentBuilder { + @Override + protected MNSComponent buildConcreteComponent() { + return new MNSComponent(); + } + @Override + protected boolean setPropertyOnComponent( + Component component, + String name, + Object value) { + switch (name) { + case "bridgeErrorHandler": ((MNSComponent) component).setBridgeErrorHandler((boolean) value); return true; + case "lazyStartProducer": ((MNSComponent) component).setLazyStartProducer((boolean) value); return true; + case "autowiredEnabled": ((MNSComponent) component).setAutowiredEnabled((boolean) value); return true; + case "healthCheckConsumerEnabled": ((MNSComponent) component).setHealthCheckConsumerEnabled((boolean) value); return true; + case "healthCheckProducerEnabled": ((MNSComponent) component).setHealthCheckProducerEnabled((boolean) value); return true; + default: return false; + } + } + } +} \ No newline at end of file diff --git a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/AlibabaOssComponentBuilderFactory.java b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/AlibabaOssComponentBuilderFactory.java new file mode 100644 index 0000000000000..dbfdcc11b01b6 --- /dev/null +++ b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/AlibabaOssComponentBuilderFactory.java @@ -0,0 +1,189 @@ +/* Generated by camel build tools - do NOT edit this file! */ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.builder.component.dsl; + +import javax.annotation.processing.Generated; +import org.apache.camel.Component; +import org.apache.camel.builder.component.AbstractComponentBuilder; +import org.apache.camel.builder.component.ComponentBuilder; +import org.apache.camel.component.alibaba.oss.OSSComponent; + +/** + * Alibaba Cloud Object Storage Service (OSS) component + * + * Generated by camel build tools - do NOT edit this file! + */ +@Generated("org.apache.camel.maven.packaging.ComponentDslMojo") +public interface AlibabaOssComponentBuilderFactory { + + /** + * Alibaba Object Storage Service (OSS) (camel-alibaba-oss) + * Alibaba Cloud Object Storage Service (OSS) component + * + * Category: cloud + * Since: 4.23 + * Maven coordinates: org.apache.camel:camel-alibaba-oss + * + * @return the dsl builder + */ + static AlibabaOssComponentBuilder alibabaOss() { + return new AlibabaOssComponentBuilderImpl(); + } + + /** + * Builder for the Alibaba Object Storage Service (OSS) component. + */ + interface AlibabaOssComponentBuilder extends ComponentBuilder { + + + /** + * Allows for bridging the consumer to the Camel routing Error Handler, + * which mean any exceptions (if possible) occurred while the Camel + * consumer is trying to pickup incoming messages, or the likes, will + * now be processed as a message and handled by the routing Error + * Handler. Important: This is only possible if the 3rd party component + * allows Camel to be alerted if an exception was thrown. Some + * components handle this internally only, and therefore + * bridgeErrorHandler is not possible. In other situations we may + * improve the Camel component to hook into the 3rd party component and + * make this possible for future releases. By default the consumer will + * use the org.apache.camel.spi.ExceptionHandler to deal with + * exceptions, that will be logged at WARN or ERROR level and ignored. + * + * The option is a: <code>boolean</code> type. + * + * Default: false + * Group: consumer + * + * @param bridgeErrorHandler the value to set + * @return the dsl builder + */ + default AlibabaOssComponentBuilder bridgeErrorHandler(boolean bridgeErrorHandler) { + doSetProperty("bridgeErrorHandler", bridgeErrorHandler); + return this; + } + + + /** + * 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 during + * starting and cause the route to fail being started. By deferring this + * startup to be lazy then the startup failure can be handled during + * routing messages via Camel's routing error handlers. Beware that when + * the first message is processed then creating and starting the + * producer may take a little time and prolong the total processing time + * of the processing. + * + * The option is a: <code>boolean</code> type. + * + * Default: false + * Group: producer + * + * @param lazyStartProducer the value to set + * @return the dsl builder + */ + default AlibabaOssComponentBuilder lazyStartProducer(boolean lazyStartProducer) { + doSetProperty("lazyStartProducer", lazyStartProducer); + return this; + } + + + /** + * Whether autowiring is enabled. This is used for automatic autowiring + * options (the option must be marked as autowired) by looking up in the + * registry to find if there is a single instance of matching type, + * which then gets configured on the component. This can be used for + * automatic configuring JDBC data sources, JMS connection factories, + * AWS Clients, etc. + * + * The option is a: <code>boolean</code> type. + * + * Default: true + * Group: advanced + * + * @param autowiredEnabled the value to set + * @return the dsl builder + */ + default AlibabaOssComponentBuilder autowiredEnabled(boolean autowiredEnabled) { + doSetProperty("autowiredEnabled", autowiredEnabled); + return this; + } + + + /** + * Used for enabling or disabling all consumer based health checks from + * this component. + * + * The option is a: <code>boolean</code> type. + * + * Default: true + * Group: health + * + * @param healthCheckConsumerEnabled the value to set + * @return the dsl builder + */ + default AlibabaOssComponentBuilder healthCheckConsumerEnabled(boolean healthCheckConsumerEnabled) { + doSetProperty("healthCheckConsumerEnabled", healthCheckConsumerEnabled); + return this; + } + + + /** + * 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 producer checks globally by + * setting camel.health.producersEnabled=true. + * + * The option is a: <code>boolean</code> type. + * + * Default: true + * Group: health + * + * @param healthCheckProducerEnabled the value to set + * @return the dsl builder + */ + default AlibabaOssComponentBuilder healthCheckProducerEnabled(boolean healthCheckProducerEnabled) { + doSetProperty("healthCheckProducerEnabled", healthCheckProducerEnabled); + return this; + } + } + + class AlibabaOssComponentBuilderImpl + extends AbstractComponentBuilder + implements AlibabaOssComponentBuilder { + @Override + protected OSSComponent buildConcreteComponent() { + return new OSSComponent(); + } + @Override + protected boolean setPropertyOnComponent( + Component component, + String name, + Object value) { + switch (name) { + case "bridgeErrorHandler": ((OSSComponent) component).setBridgeErrorHandler((boolean) value); return true; + case "lazyStartProducer": ((OSSComponent) component).setLazyStartProducer((boolean) value); return true; + case "autowiredEnabled": ((OSSComponent) component).setAutowiredEnabled((boolean) value); return true; + case "healthCheckConsumerEnabled": ((OSSComponent) component).setHealthCheckConsumerEnabled((boolean) value); return true; + case "healthCheckProducerEnabled": ((OSSComponent) component).setHealthCheckProducerEnabled((boolean) value); return true; + default: return false; + } + } + } +} \ No newline at end of file diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java index 83a4781d4449f..9805eb8da4b3e 100644 --- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java +++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java @@ -252,6 +252,7 @@ public interface EndpointBuilderFactory org.apache.camel.builder.endpoint.dsl.LogEndpointBuilderFactory.LogBuilders, org.apache.camel.builder.endpoint.dsl.LuceneEndpointBuilderFactory.LuceneBuilders, org.apache.camel.builder.endpoint.dsl.LumberjackEndpointBuilderFactory.LumberjackBuilders, + org.apache.camel.builder.endpoint.dsl.MNSEndpointBuilderFactory.MNSBuilders, org.apache.camel.builder.endpoint.dsl.MQ2EndpointBuilderFactory.MQ2Builders, org.apache.camel.builder.endpoint.dsl.MSK2EndpointBuilderFactory.MSK2Builders, org.apache.camel.builder.endpoint.dsl.MailEndpointBuilderFactory.MailBuilders, @@ -282,6 +283,7 @@ public interface EndpointBuilderFactory org.apache.camel.builder.endpoint.dsl.NovaEndpointBuilderFactory.NovaBuilders, org.apache.camel.builder.endpoint.dsl.OAIPMHEndpointBuilderFactory.OAIPMHBuilders, org.apache.camel.builder.endpoint.dsl.OBSEndpointBuilderFactory.OBSBuilders, + org.apache.camel.builder.endpoint.dsl.OSSEndpointBuilderFactory.OSSBuilders, org.apache.camel.builder.endpoint.dsl.Olingo2EndpointBuilderFactory.Olingo2Builders, org.apache.camel.builder.endpoint.dsl.Olingo4EndpointBuilderFactory.Olingo4Builders, org.apache.camel.builder.endpoint.dsl.OnceEndpointBuilderFactory.OnceBuilders, diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilders.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilders.java index 5674d6acd2e8e..b17b4fba6da20 100644 --- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilders.java +++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilders.java @@ -249,6 +249,7 @@ public interface EndpointBuilders org.apache.camel.builder.endpoint.dsl.LogEndpointBuilderFactory, org.apache.camel.builder.endpoint.dsl.LuceneEndpointBuilderFactory, org.apache.camel.builder.endpoint.dsl.LumberjackEndpointBuilderFactory, + org.apache.camel.builder.endpoint.dsl.MNSEndpointBuilderFactory, org.apache.camel.builder.endpoint.dsl.MQ2EndpointBuilderFactory, org.apache.camel.builder.endpoint.dsl.MSK2EndpointBuilderFactory, org.apache.camel.builder.endpoint.dsl.MailEndpointBuilderFactory, @@ -279,6 +280,7 @@ public interface EndpointBuilders org.apache.camel.builder.endpoint.dsl.NovaEndpointBuilderFactory, org.apache.camel.builder.endpoint.dsl.OAIPMHEndpointBuilderFactory, org.apache.camel.builder.endpoint.dsl.OBSEndpointBuilderFactory, + org.apache.camel.builder.endpoint.dsl.OSSEndpointBuilderFactory, org.apache.camel.builder.endpoint.dsl.Olingo2EndpointBuilderFactory, org.apache.camel.builder.endpoint.dsl.Olingo4EndpointBuilderFactory, org.apache.camel.builder.endpoint.dsl.OnceEndpointBuilderFactory, diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointHeaderBuilders.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointHeaderBuilders.java index ad3792db9a89f..2764a24f9d79f 100644 --- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointHeaderBuilders.java +++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointHeaderBuilders.java @@ -79,6 +79,32 @@ public static ActiveMQEndpointBuilderFactory.ActiveMQHeaderNameBuilder activemq( public static ActiveMQ6EndpointBuilderFactory.ActiveMQ6HeaderNameBuilder activemq6() { return ActiveMQ6EndpointBuilderFactory.ActiveMQ6HeaderNameBuilder.INSTANCE; } + /** + * Alibaba Message Service (MNS) (camel-alibaba-mns) + * Send and receive messages to/from Alibaba Cloud Message Service (MNS). + * + * Category: cloud,messaging + * Since: 4.23 + * Maven coordinates: org.apache.camel:camel-alibaba-mns + * + * @return the dsl builder for the headers' name. + */ + public static MNSEndpointBuilderFactory.MNSHeaderNameBuilder alibabaMns() { + return MNSEndpointBuilderFactory.MNSHeaderNameBuilder.INSTANCE; + } + /** + * Alibaba Object Storage Service (OSS) (camel-alibaba-oss) + * Alibaba Cloud Object Storage Service (OSS) component + * + * Category: cloud + * Since: 4.23 + * Maven coordinates: org.apache.camel:camel-alibaba-oss + * + * @return the dsl builder for the headers' name. + */ + public static OSSEndpointBuilderFactory.OSSHeaderNameBuilder alibabaOss() { + return OSSEndpointBuilderFactory.OSSHeaderNameBuilder.INSTANCE; + } /** * AMQP (camel-amqp) * Messaging with AMQP protocol using Apache Qpid Client. diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java index 2f6aa940af898..e4387feecbfe7 100644 --- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java +++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java @@ -218,6 +218,86 @@ public static AiToolEndpointBuilderFactory.AiToolEndpointBuilder aiTool(String p public static AiToolEndpointBuilderFactory.AiToolEndpointBuilder aiTool(String componentName, String path) { return AiToolEndpointBuilderFactory.endpointBuilder(componentName, path); } + /** + * Alibaba Message Service (MNS) (camel-alibaba-mns) + * Send and receive messages to/from Alibaba Cloud Message Service (MNS). + * + * Category: cloud,messaging + * Since: 4.23 + * Maven coordinates: org.apache.camel:camel-alibaba-mns + * + * Syntax: alibaba-mns:queueName + * + * Path parameter: queueName (required) + * Queue name, or topic name when using the topic URI syntax + * + * @param path queueName + * @return the dsl builder + */ + public static MNSEndpointBuilderFactory.MNSEndpointBuilder alibabaMns(String path) { + return alibabaMns("alibaba-mns", path); + } + /** + * Alibaba Message Service (MNS) (camel-alibaba-mns) + * Send and receive messages to/from Alibaba Cloud Message Service (MNS). + * + * Category: cloud,messaging + * Since: 4.23 + * Maven coordinates: org.apache.camel:camel-alibaba-mns + * + * Syntax: alibaba-mns:queueName + * + * Path parameter: queueName (required) + * Queue name, or topic name when using the topic URI syntax + * + * @param componentName to use a custom component name for the endpoint + * instead of the default name + * @param path queueName + * @return the dsl builder + */ + public static MNSEndpointBuilderFactory.MNSEndpointBuilder alibabaMns(String componentName, String path) { + return MNSEndpointBuilderFactory.endpointBuilder(componentName, path); + } + /** + * Alibaba Object Storage Service (OSS) (camel-alibaba-oss) + * Alibaba Cloud Object Storage Service (OSS) component + * + * Category: cloud + * Since: 4.23 + * Maven coordinates: org.apache.camel:camel-alibaba-oss + * + * Syntax: alibaba-oss:bucketName + * + * Path parameter: bucketName + * Name of bucket to perform operation on + * + * @param path bucketName + * @return the dsl builder + */ + public static OSSEndpointBuilderFactory.OSSEndpointBuilder alibabaOss(String path) { + return alibabaOss("alibaba-oss", path); + } + /** + * Alibaba Object Storage Service (OSS) (camel-alibaba-oss) + * Alibaba Cloud Object Storage Service (OSS) component + * + * Category: cloud + * Since: 4.23 + * Maven coordinates: org.apache.camel:camel-alibaba-oss + * + * Syntax: alibaba-oss:bucketName + * + * Path parameter: bucketName + * Name of bucket to perform operation on + * + * @param componentName to use a custom component name for the endpoint + * instead of the default name + * @param path bucketName + * @return the dsl builder + */ + public static OSSEndpointBuilderFactory.OSSEndpointBuilder alibabaOss(String componentName, String path) { + return OSSEndpointBuilderFactory.endpointBuilder(componentName, path); + } /** * AMQP (camel-amqp) * Messaging with AMQP protocol using Apache Qpid Client. diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/MNSEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/MNSEndpointBuilderFactory.java new file mode 100644 index 0000000000000..78b1ba34fdcef --- /dev/null +++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/MNSEndpointBuilderFactory.java @@ -0,0 +1,1581 @@ +/* Generated by camel build tools - do NOT edit this file! */ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.builder.endpoint.dsl; + +import java.util.*; +import java.util.concurrent.*; +import java.util.function.*; +import java.util.stream.*; +import javax.annotation.processing.Generated; +import org.apache.camel.builder.EndpointConsumerBuilder; +import org.apache.camel.builder.EndpointProducerBuilder; +import org.apache.camel.builder.endpoint.AbstractEndpointBuilder; + +/** + * Send and receive messages to/from Alibaba Cloud Message Service (MNS). + * + * Generated by camel build tools - do NOT edit this file! + */ +@Generated("org.apache.camel.maven.packaging.EndpointDslMojo") +public interface MNSEndpointBuilderFactory { + + /** + * Builder for endpoint consumers for the Alibaba Message Service (MNS) component. + */ + public interface MNSEndpointConsumerBuilder + extends + EndpointConsumerBuilder { + default AdvancedMNSEndpointConsumerBuilder advanced() { + return (AdvancedMNSEndpointConsumerBuilder) this; + } + /** + * MNS account endpoint, for example + * https://123456.mns.cn-hangzhou.aliyuncs.com. + * + * The option is a: java.lang.String type. + * + * Required: true + * Group: common + * + * @param accountEndpoint the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder accountEndpoint(String accountEndpoint) { + doSetProperty("accountEndpoint", accountEndpoint); + return this; + } + /** + * Operation to perform. + * + * The option is a: java.lang.String type. + * + * Group: common + * + * @param operation the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder operation(String operation) { + doSetProperty("operation", operation); + return this; + } + /** + * Alibaba Cloud region. + * + * The option is a: java.lang.String type. + * + * Required: true + * Group: common + * + * @param region the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder region(String region) { + doSetProperty("region", region); + return this; + } + /** + * Topic name for publishMessage operations. + * + * The option is a: java.lang.String type. + * + * Group: common + * + * @param topicName the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder topicName(String topicName) { + doSetProperty("topicName", topicName); + return this; + } + /** + * Long polling wait time in seconds when receiving messages. + * + * The option is a: int type. + * + * Default: 0 + * Group: common + * + * @param waitSeconds the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder waitSeconds(int waitSeconds) { + doSetProperty("waitSeconds", waitSeconds); + return this; + } + /** + * Long polling wait time in seconds when receiving messages. + * + * The option will be converted to a int type. + * + * Default: 0 + * Group: common + * + * @param waitSeconds the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder waitSeconds(String waitSeconds) { + doSetProperty("waitSeconds", waitSeconds); + return this; + } + /** + * Delete message from the queue after it has been processed. + * + * The option is a: boolean type. + * + * Default: true + * Group: consumer + * + * @param deleteAfterRead the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder deleteAfterRead(boolean deleteAfterRead) { + doSetProperty("deleteAfterRead", deleteAfterRead); + return this; + } + /** + * Delete message from the queue after it has been processed. + * + * The option will be converted to a boolean type. + * + * Default: true + * Group: consumer + * + * @param deleteAfterRead the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder deleteAfterRead(String deleteAfterRead) { + doSetProperty("deleteAfterRead", deleteAfterRead); + return this; + } + /** + * Maximum number of messages to receive per poll. + * + * The option is a: int type. + * + * Default: 1 + * Group: consumer + * + * @param maxMessagesPerPoll the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder maxMessagesPerPoll(int maxMessagesPerPoll) { + doSetProperty("maxMessagesPerPoll", maxMessagesPerPoll); + return this; + } + /** + * Maximum number of messages to receive per poll. + * + * The option will be converted to a int type. + * + * Default: 1 + * Group: consumer + * + * @param maxMessagesPerPoll the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder maxMessagesPerPoll(String maxMessagesPerPoll) { + doSetProperty("maxMessagesPerPoll", maxMessagesPerPoll); + return this; + } + /** + * If the polling consumer did not poll any files, you can enable this + * option to send an empty message (no body) instead. + * + * The option is a: boolean type. + * + * Default: false + * Group: consumer + * + * @param sendEmptyMessageWhenIdle the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder sendEmptyMessageWhenIdle(boolean sendEmptyMessageWhenIdle) { + doSetProperty("sendEmptyMessageWhenIdle", sendEmptyMessageWhenIdle); + return this; + } + /** + * If the polling consumer did not poll any files, you can enable this + * option to send an empty message (no body) instead. + * + * The option will be converted to a boolean type. + * + * Default: false + * Group: consumer + * + * @param sendEmptyMessageWhenIdle the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder sendEmptyMessageWhenIdle(String sendEmptyMessageWhenIdle) { + doSetProperty("sendEmptyMessageWhenIdle", sendEmptyMessageWhenIdle); + return this; + } + /** + * The number of subsequent error polls (failed due some error) that + * should happen before the backoffMultipler should kick-in. + * + * The option is a: int type. + * + * Group: scheduler + * + * @param backoffErrorThreshold the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder backoffErrorThreshold(int backoffErrorThreshold) { + doSetProperty("backoffErrorThreshold", backoffErrorThreshold); + return this; + } + /** + * The number of subsequent error polls (failed due some error) that + * should happen before the backoffMultipler should kick-in. + * + * The option will be converted to a int type. + * + * Group: scheduler + * + * @param backoffErrorThreshold the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder backoffErrorThreshold(String backoffErrorThreshold) { + doSetProperty("backoffErrorThreshold", backoffErrorThreshold); + return this; + } + /** + * The number of subsequent idle polls that should happen before the + * backoffMultipler should kick-in. + * + * The option is a: int type. + * + * Group: scheduler + * + * @param backoffIdleThreshold the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder backoffIdleThreshold(int backoffIdleThreshold) { + doSetProperty("backoffIdleThreshold", backoffIdleThreshold); + return this; + } + /** + * The number of subsequent idle polls that should happen before the + * backoffMultipler should kick-in. + * + * The option will be converted to a int type. + * + * Group: scheduler + * + * @param backoffIdleThreshold the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder backoffIdleThreshold(String backoffIdleThreshold) { + doSetProperty("backoffIdleThreshold", backoffIdleThreshold); + return this; + } + /** + * To let the scheduled polling consumer backoff if there has been a + * number of subsequent idles/errors in a row. The multiplier is then + * the number of polls that will be skipped before the next actual + * attempt is happening again. When this option is in use then + * backoffIdleThreshold and/or backoffErrorThreshold must also be + * configured. + * + * The option is a: int type. + * + * Group: scheduler + * + * @param backoffMultiplier the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder backoffMultiplier(int backoffMultiplier) { + doSetProperty("backoffMultiplier", backoffMultiplier); + return this; + } + /** + * To let the scheduled polling consumer backoff if there has been a + * number of subsequent idles/errors in a row. The multiplier is then + * the number of polls that will be skipped before the next actual + * attempt is happening again. When this option is in use then + * backoffIdleThreshold and/or backoffErrorThreshold must also be + * configured. + * + * The option will be converted to a int type. + * + * Group: scheduler + * + * @param backoffMultiplier the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder backoffMultiplier(String backoffMultiplier) { + doSetProperty("backoffMultiplier", backoffMultiplier); + return this; + } + /** + * Milliseconds before the next poll. + * + * The option is a: long type. + * + * Default: 500 + * Group: scheduler + * + * @param delay the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder delay(long delay) { + doSetProperty("delay", delay); + return this; + } + /** + * Milliseconds before the next poll. + * + * The option will be converted to a long type. + * + * Default: 500 + * Group: scheduler + * + * @param delay the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder delay(String delay) { + doSetProperty("delay", delay); + return this; + } + /** + * If greedy is enabled, then the ScheduledPollConsumer will run + * immediately again, if the previous run polled 1 or more messages. + * + * The option is a: boolean type. + * + * Default: false + * Group: scheduler + * + * @param greedy the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder greedy(boolean greedy) { + doSetProperty("greedy", greedy); + return this; + } + /** + * If greedy is enabled, then the ScheduledPollConsumer will run + * immediately again, if the previous run polled 1 or more messages. + * + * The option will be converted to a boolean type. + * + * Default: false + * Group: scheduler + * + * @param greedy the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder greedy(String greedy) { + doSetProperty("greedy", greedy); + return this; + } + /** + * Milliseconds before the first poll starts. + * + * The option is a: long type. + * + * Default: 1000 + * Group: scheduler + * + * @param initialDelay the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder initialDelay(long initialDelay) { + doSetProperty("initialDelay", initialDelay); + return this; + } + /** + * Milliseconds before the first poll starts. + * + * The option will be converted to a long type. + * + * Default: 1000 + * Group: scheduler + * + * @param initialDelay the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder initialDelay(String initialDelay) { + doSetProperty("initialDelay", initialDelay); + return this; + } + /** + * Specifies a maximum limit of number of fires. So if you set it to 1, + * the scheduler will only fire once. If you set it to 5, it will only + * fire five times. A value of zero or negative means fire forever. + * + * The option is a: long type. + * + * Default: 0 + * Group: scheduler + * + * @param repeatCount the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder repeatCount(long repeatCount) { + doSetProperty("repeatCount", repeatCount); + return this; + } + /** + * Specifies a maximum limit of number of fires. So if you set it to 1, + * the scheduler will only fire once. If you set it to 5, it will only + * fire five times. A value of zero or negative means fire forever. + * + * The option will be converted to a long type. + * + * Default: 0 + * Group: scheduler + * + * @param repeatCount the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder repeatCount(String repeatCount) { + doSetProperty("repeatCount", repeatCount); + return this; + } + /** + * The consumer logs a start/complete log line when it polls. This + * option allows you to configure the logging level for that. + * + * The option is a: org.apache.camel.LoggingLevel type. + * + * Default: TRACE + * Group: scheduler + * + * @param runLoggingLevel the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder runLoggingLevel(org.apache.camel.LoggingLevel runLoggingLevel) { + doSetProperty("runLoggingLevel", runLoggingLevel); + return this; + } + /** + * The consumer logs a start/complete log line when it polls. This + * option allows you to configure the logging level for that. + * + * The option will be converted to a + * org.apache.camel.LoggingLevel type. + * + * Default: TRACE + * Group: scheduler + * + * @param runLoggingLevel the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder runLoggingLevel(String runLoggingLevel) { + doSetProperty("runLoggingLevel", runLoggingLevel); + return this; + } + /** + * Allows for configuring a custom/shared thread pool to use for the + * consumer. By default each consumer has its own single threaded thread + * pool. + * + * The option is a: + * java.util.concurrent.ScheduledExecutorService type. + * + * Group: scheduler + * + * @param scheduledExecutorService the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder scheduledExecutorService(ScheduledExecutorService scheduledExecutorService) { + doSetProperty("scheduledExecutorService", scheduledExecutorService); + return this; + } + /** + * Allows for configuring a custom/shared thread pool to use for the + * consumer. By default each consumer has its own single threaded thread + * pool. + * + * The option will be converted to a + * java.util.concurrent.ScheduledExecutorService type. + * + * Group: scheduler + * + * @param scheduledExecutorService the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder scheduledExecutorService(String scheduledExecutorService) { + doSetProperty("scheduledExecutorService", scheduledExecutorService); + return this; + } + /** + * To use a cron scheduler from either camel-spring or camel-quartz + * component. Use value spring or quartz for built in scheduler. + * + * The option is a: java.lang.Object type. + * + * Default: none + * Group: scheduler + * + * @param scheduler the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder scheduler(Object scheduler) { + doSetProperty("scheduler", scheduler); + return this; + } + /** + * To use a cron scheduler from either camel-spring or camel-quartz + * component. Use value spring or quartz for built in scheduler. + * + * The option will be converted to a java.lang.Object type. + * + * Default: none + * Group: scheduler + * + * @param scheduler the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder scheduler(String scheduler) { + doSetProperty("scheduler", scheduler); + return this; + } + /** + * To configure additional properties when using a custom scheduler or + * any of the Quartz, Spring based scheduler. This is a multi-value + * option with prefix: scheduler. + * + * The option is a: java.util.Map<java.lang.String, + * java.lang.Object> type. + * The option is multivalued, and you can use the + * schedulerProperties(String, Object) method to add a value (call the + * method multiple times to set more values). + * + * Group: scheduler + * + * @param key the option key + * @param value the option value + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder schedulerProperties(String key, Object value) { + doSetMultiValueProperty("schedulerProperties", "scheduler." + key, value); + return this; + } + /** + * To configure additional properties when using a custom scheduler or + * any of the Quartz, Spring based scheduler. This is a multi-value + * option with prefix: scheduler. + * + * The option is a: java.util.Map<java.lang.String, + * java.lang.Object> type. + * The option is multivalued, and you can use the + * schedulerProperties(String, Object) method to add a value (call the + * method multiple times to set more values). + * + * Group: scheduler + * + * @param values the values + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder schedulerProperties(Map values) { + doSetMultiValueProperties("schedulerProperties", "scheduler.", values); + return this; + } + /** + * Whether the scheduler should be auto started. + * + * The option is a: boolean type. + * + * Default: true + * Group: scheduler + * + * @param startScheduler the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder startScheduler(boolean startScheduler) { + doSetProperty("startScheduler", startScheduler); + return this; + } + /** + * Whether the scheduler should be auto started. + * + * The option will be converted to a boolean type. + * + * Default: true + * Group: scheduler + * + * @param startScheduler the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder startScheduler(String startScheduler) { + doSetProperty("startScheduler", startScheduler); + return this; + } + /** + * Time unit for initialDelay and delay options. + * + * The option is a: java.util.concurrent.TimeUnit type. + * + * Default: MILLISECONDS + * Group: scheduler + * + * @param timeUnit the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder timeUnit(TimeUnit timeUnit) { + doSetProperty("timeUnit", timeUnit); + return this; + } + /** + * Time unit for initialDelay and delay options. + * + * The option will be converted to a + * java.util.concurrent.TimeUnit type. + * + * Default: MILLISECONDS + * Group: scheduler + * + * @param timeUnit the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder timeUnit(String timeUnit) { + doSetProperty("timeUnit", timeUnit); + return this; + } + /** + * Controls if fixed delay or fixed rate is used. See + * ScheduledExecutorService in JDK for details. + * + * The option is a: boolean type. + * + * Default: true + * Group: scheduler + * + * @param useFixedDelay the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder useFixedDelay(boolean useFixedDelay) { + doSetProperty("useFixedDelay", useFixedDelay); + return this; + } + /** + * Controls if fixed delay or fixed rate is used. See + * ScheduledExecutorService in JDK for details. + * + * The option will be converted to a boolean type. + * + * Default: true + * Group: scheduler + * + * @param useFixedDelay the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder useFixedDelay(String useFixedDelay) { + doSetProperty("useFixedDelay", useFixedDelay); + return this; + } + /** + * Access key for the cloud user. + * + * The option is a: java.lang.String type. + * + * Group: security + * + * @param accessKey the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder accessKey(String accessKey) { + doSetProperty("accessKey", accessKey); + return this; + } + /** + * Secret key for the cloud user. + * + * The option is a: java.lang.String type. + * + * Group: security + * + * @param secretKey the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder secretKey(String secretKey) { + doSetProperty("secretKey", secretKey); + return this; + } + /** + * Configuration object for cloud service authentication. + * + * The option is a: + * org.apache.camel.component.alibaba.common.models.ServiceKeys type. + * + * Group: security + * + * @param serviceKeys the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder serviceKeys(org.apache.camel.component.alibaba.common.models.ServiceKeys serviceKeys) { + doSetProperty("serviceKeys", serviceKeys); + return this; + } + /** + * Configuration object for cloud service authentication. + * + * The option will be converted to a + * org.apache.camel.component.alibaba.common.models.ServiceKeys type. + * + * Group: security + * + * @param serviceKeys the value to set + * @return the dsl builder + */ + default MNSEndpointConsumerBuilder serviceKeys(String serviceKeys) { + doSetProperty("serviceKeys", serviceKeys); + return this; + } + } + + /** + * Advanced builder for endpoint consumers for the Alibaba Message Service (MNS) component. + */ + public interface AdvancedMNSEndpointConsumerBuilder + extends + EndpointConsumerBuilder { + default MNSEndpointConsumerBuilder basic() { + return (MNSEndpointConsumerBuilder) this; + } + /** + * Allows for bridging the consumer to the Camel routing Error Handler, + * which mean any exceptions (if possible) occurred while the Camel + * consumer is trying to pickup incoming messages, or the likes, will + * now be processed as a message and handled by the routing Error + * Handler. Important: This is only possible if the 3rd party component + * allows Camel to be alerted if an exception was thrown. Some + * components handle this internally only, and therefore + * bridgeErrorHandler is not possible. In other situations we may + * improve the Camel component to hook into the 3rd party component and + * make this possible for future releases. By default the consumer will + * use the org.apache.camel.spi.ExceptionHandler to deal with + * exceptions, that will be logged at WARN or ERROR level and ignored. + * + * The option is a: boolean type. + * + * Default: false + * Group: consumer (advanced) + * + * @param bridgeErrorHandler the value to set + * @return the dsl builder + */ + default AdvancedMNSEndpointConsumerBuilder bridgeErrorHandler(boolean bridgeErrorHandler) { + doSetProperty("bridgeErrorHandler", bridgeErrorHandler); + return this; + } + /** + * Allows for bridging the consumer to the Camel routing Error Handler, + * which mean any exceptions (if possible) occurred while the Camel + * consumer is trying to pickup incoming messages, or the likes, will + * now be processed as a message and handled by the routing Error + * Handler. Important: This is only possible if the 3rd party component + * allows Camel to be alerted if an exception was thrown. Some + * components handle this internally only, and therefore + * bridgeErrorHandler is not possible. In other situations we may + * improve the Camel component to hook into the 3rd party component and + * make this possible for future releases. By default the consumer will + * use the org.apache.camel.spi.ExceptionHandler to deal with + * exceptions, that will be logged at WARN or ERROR level and ignored. + * + * The option will be converted to a boolean type. + * + * Default: false + * Group: consumer (advanced) + * + * @param bridgeErrorHandler the value to set + * @return the dsl builder + */ + default AdvancedMNSEndpointConsumerBuilder bridgeErrorHandler(String bridgeErrorHandler) { + doSetProperty("bridgeErrorHandler", bridgeErrorHandler); + return this; + } + /** + * To let the consumer use a custom ExceptionHandler. Notice if the + * option bridgeErrorHandler is enabled then this option is not in use. + * By default the consumer will deal with exceptions, that will be + * logged at WARN or ERROR level and ignored. + * + * The option is a: org.apache.camel.spi.ExceptionHandler + * type. + * + * Group: consumer (advanced) + * + * @param exceptionHandler the value to set + * @return the dsl builder + */ + default AdvancedMNSEndpointConsumerBuilder exceptionHandler(org.apache.camel.spi.ExceptionHandler exceptionHandler) { + doSetProperty("exceptionHandler", exceptionHandler); + return this; + } + /** + * To let the consumer use a custom ExceptionHandler. Notice if the + * option bridgeErrorHandler is enabled then this option is not in use. + * By default the consumer will deal with exceptions, that will be + * logged at WARN or ERROR level and ignored. + * + * The option will be converted to a + * org.apache.camel.spi.ExceptionHandler type. + * + * Group: consumer (advanced) + * + * @param exceptionHandler the value to set + * @return the dsl builder + */ + default AdvancedMNSEndpointConsumerBuilder exceptionHandler(String exceptionHandler) { + doSetProperty("exceptionHandler", exceptionHandler); + return this; + } + /** + * Sets the exchange pattern when the consumer creates an exchange. + * + * The option is a: org.apache.camel.ExchangePattern type. + * + * Group: consumer (advanced) + * + * @param exchangePattern the value to set + * @return the dsl builder + */ + default AdvancedMNSEndpointConsumerBuilder exchangePattern(org.apache.camel.ExchangePattern exchangePattern) { + doSetProperty("exchangePattern", exchangePattern); + return this; + } + /** + * Sets the exchange pattern when the consumer creates an exchange. + * + * The option will be converted to a + * org.apache.camel.ExchangePattern type. + * + * Group: consumer (advanced) + * + * @param exchangePattern the value to set + * @return the dsl builder + */ + default AdvancedMNSEndpointConsumerBuilder exchangePattern(String exchangePattern) { + doSetProperty("exchangePattern", exchangePattern); + return this; + } + /** + * A pluggable org.apache.camel.PollingConsumerPollingStrategy allowing + * you to provide your custom implementation to control error handling + * usually occurred during the poll operation before an Exchange have + * been created and being routed in Camel. + * + * The option is a: + * org.apache.camel.spi.PollingConsumerPollStrategy type. + * + * Group: consumer (advanced) + * + * @param pollStrategy the value to set + * @return the dsl builder + */ + default AdvancedMNSEndpointConsumerBuilder pollStrategy(org.apache.camel.spi.PollingConsumerPollStrategy pollStrategy) { + doSetProperty("pollStrategy", pollStrategy); + return this; + } + /** + * A pluggable org.apache.camel.PollingConsumerPollingStrategy allowing + * you to provide your custom implementation to control error handling + * usually occurred during the poll operation before an Exchange have + * been created and being routed in Camel. + * + * The option will be converted to a + * org.apache.camel.spi.PollingConsumerPollStrategy type. + * + * Group: consumer (advanced) + * + * @param pollStrategy the value to set + * @return the dsl builder + */ + default AdvancedMNSEndpointConsumerBuilder pollStrategy(String pollStrategy) { + doSetProperty("pollStrategy", pollStrategy); + return this; + } + /** + * Autowire an existing MNSClient instance. + * + * The option is a: com.aliyun.mns.client.MNSClient type. + * + * Group: advanced + * + * @param mnsClient the value to set + * @return the dsl builder + */ + default AdvancedMNSEndpointConsumerBuilder mnsClient(com.aliyun.mns.client.MNSClient mnsClient) { + doSetProperty("mnsClient", mnsClient); + return this; + } + /** + * Autowire an existing MNSClient instance. + * + * The option will be converted to a + * com.aliyun.mns.client.MNSClient type. + * + * Group: advanced + * + * @param mnsClient the value to set + * @return the dsl builder + */ + default AdvancedMNSEndpointConsumerBuilder mnsClient(String mnsClient) { + doSetProperty("mnsClient", mnsClient); + return this; + } + } + + /** + * Builder for endpoint producers for the Alibaba Message Service (MNS) component. + */ + public interface MNSEndpointProducerBuilder + extends + EndpointProducerBuilder { + default AdvancedMNSEndpointProducerBuilder advanced() { + return (AdvancedMNSEndpointProducerBuilder) this; + } + + /** + * MNS account endpoint, for example + * https://123456.mns.cn-hangzhou.aliyuncs.com. + * + * The option is a: java.lang.String type. + * + * Required: true + * Group: common + * + * @param accountEndpoint the value to set + * @return the dsl builder + */ + default MNSEndpointProducerBuilder accountEndpoint(String accountEndpoint) { + doSetProperty("accountEndpoint", accountEndpoint); + return this; + } + /** + * Operation to perform. + * + * The option is a: java.lang.String type. + * + * Group: common + * + * @param operation the value to set + * @return the dsl builder + */ + default MNSEndpointProducerBuilder operation(String operation) { + doSetProperty("operation", operation); + return this; + } + /** + * Alibaba Cloud region. + * + * The option is a: java.lang.String type. + * + * Required: true + * Group: common + * + * @param region the value to set + * @return the dsl builder + */ + default MNSEndpointProducerBuilder region(String region) { + doSetProperty("region", region); + return this; + } + /** + * Topic name for publishMessage operations. + * + * The option is a: java.lang.String type. + * + * Group: common + * + * @param topicName the value to set + * @return the dsl builder + */ + default MNSEndpointProducerBuilder topicName(String topicName) { + doSetProperty("topicName", topicName); + return this; + } + /** + * Long polling wait time in seconds when receiving messages. + * + * The option is a: int type. + * + * Default: 0 + * Group: common + * + * @param waitSeconds the value to set + * @return the dsl builder + */ + default MNSEndpointProducerBuilder waitSeconds(int waitSeconds) { + doSetProperty("waitSeconds", waitSeconds); + return this; + } + /** + * Long polling wait time in seconds when receiving messages. + * + * The option will be converted to a int type. + * + * Default: 0 + * Group: common + * + * @param waitSeconds the value to set + * @return the dsl builder + */ + default MNSEndpointProducerBuilder waitSeconds(String waitSeconds) { + doSetProperty("waitSeconds", waitSeconds); + return this; + } + /** + * Access key for the cloud user. + * + * The option is a: java.lang.String type. + * + * Group: security + * + * @param accessKey the value to set + * @return the dsl builder + */ + default MNSEndpointProducerBuilder accessKey(String accessKey) { + doSetProperty("accessKey", accessKey); + return this; + } + /** + * Secret key for the cloud user. + * + * The option is a: java.lang.String type. + * + * Group: security + * + * @param secretKey the value to set + * @return the dsl builder + */ + default MNSEndpointProducerBuilder secretKey(String secretKey) { + doSetProperty("secretKey", secretKey); + return this; + } + /** + * Configuration object for cloud service authentication. + * + * The option is a: + * org.apache.camel.component.alibaba.common.models.ServiceKeys type. + * + * Group: security + * + * @param serviceKeys the value to set + * @return the dsl builder + */ + default MNSEndpointProducerBuilder serviceKeys(org.apache.camel.component.alibaba.common.models.ServiceKeys serviceKeys) { + doSetProperty("serviceKeys", serviceKeys); + return this; + } + /** + * Configuration object for cloud service authentication. + * + * The option will be converted to a + * org.apache.camel.component.alibaba.common.models.ServiceKeys type. + * + * Group: security + * + * @param serviceKeys the value to set + * @return the dsl builder + */ + default MNSEndpointProducerBuilder serviceKeys(String serviceKeys) { + doSetProperty("serviceKeys", serviceKeys); + return this; + } + } + + /** + * Advanced builder for endpoint producers for the Alibaba Message Service (MNS) component. + */ + public interface AdvancedMNSEndpointProducerBuilder extends EndpointProducerBuilder { + default MNSEndpointProducerBuilder basic() { + return (MNSEndpointProducerBuilder) this; + } + + /** + * 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 during + * starting and cause the route to fail being started. By deferring this + * startup to be lazy then the startup failure can be handled during + * routing messages via Camel's routing error handlers. Beware that when + * the first message is processed then creating and starting the + * producer may take a little time and prolong the total processing time + * of the processing. + * + * The option is a: boolean type. + * + * Default: false + * Group: producer (advanced) + * + * @param lazyStartProducer the value to set + * @return the dsl builder + */ + default AdvancedMNSEndpointProducerBuilder lazyStartProducer(boolean lazyStartProducer) { + doSetProperty("lazyStartProducer", lazyStartProducer); + return this; + } + /** + * 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 during + * starting and cause the route to fail being started. By deferring this + * startup to be lazy then the startup failure can be handled during + * routing messages via Camel's routing error handlers. Beware that when + * the first message is processed then creating and starting the + * producer may take a little time and prolong the total processing time + * of the processing. + * + * The option will be converted to a boolean type. + * + * Default: false + * Group: producer (advanced) + * + * @param lazyStartProducer the value to set + * @return the dsl builder + */ + default AdvancedMNSEndpointProducerBuilder lazyStartProducer(String lazyStartProducer) { + doSetProperty("lazyStartProducer", lazyStartProducer); + return this; + } + /** + * Autowire an existing MNSClient instance. + * + * The option is a: com.aliyun.mns.client.MNSClient type. + * + * Group: advanced + * + * @param mnsClient the value to set + * @return the dsl builder + */ + default AdvancedMNSEndpointProducerBuilder mnsClient(com.aliyun.mns.client.MNSClient mnsClient) { + doSetProperty("mnsClient", mnsClient); + return this; + } + /** + * Autowire an existing MNSClient instance. + * + * The option will be converted to a + * com.aliyun.mns.client.MNSClient type. + * + * Group: advanced + * + * @param mnsClient the value to set + * @return the dsl builder + */ + default AdvancedMNSEndpointProducerBuilder mnsClient(String mnsClient) { + doSetProperty("mnsClient", mnsClient); + return this; + } + } + + /** + * Builder for endpoint for the Alibaba Message Service (MNS) component. + */ + public interface MNSEndpointBuilder + extends + MNSEndpointConsumerBuilder, + MNSEndpointProducerBuilder { + default AdvancedMNSEndpointBuilder advanced() { + return (AdvancedMNSEndpointBuilder) this; + } + + /** + * MNS account endpoint, for example + * https://123456.mns.cn-hangzhou.aliyuncs.com. + * + * The option is a: java.lang.String type. + * + * Required: true + * Group: common + * + * @param accountEndpoint the value to set + * @return the dsl builder + */ + default MNSEndpointBuilder accountEndpoint(String accountEndpoint) { + doSetProperty("accountEndpoint", accountEndpoint); + return this; + } + /** + * Operation to perform. + * + * The option is a: java.lang.String type. + * + * Group: common + * + * @param operation the value to set + * @return the dsl builder + */ + default MNSEndpointBuilder operation(String operation) { + doSetProperty("operation", operation); + return this; + } + /** + * Alibaba Cloud region. + * + * The option is a: java.lang.String type. + * + * Required: true + * Group: common + * + * @param region the value to set + * @return the dsl builder + */ + default MNSEndpointBuilder region(String region) { + doSetProperty("region", region); + return this; + } + /** + * Topic name for publishMessage operations. + * + * The option is a: java.lang.String type. + * + * Group: common + * + * @param topicName the value to set + * @return the dsl builder + */ + default MNSEndpointBuilder topicName(String topicName) { + doSetProperty("topicName", topicName); + return this; + } + /** + * Long polling wait time in seconds when receiving messages. + * + * The option is a: int type. + * + * Default: 0 + * Group: common + * + * @param waitSeconds the value to set + * @return the dsl builder + */ + default MNSEndpointBuilder waitSeconds(int waitSeconds) { + doSetProperty("waitSeconds", waitSeconds); + return this; + } + /** + * Long polling wait time in seconds when receiving messages. + * + * The option will be converted to a int type. + * + * Default: 0 + * Group: common + * + * @param waitSeconds the value to set + * @return the dsl builder + */ + default MNSEndpointBuilder waitSeconds(String waitSeconds) { + doSetProperty("waitSeconds", waitSeconds); + return this; + } + /** + * Access key for the cloud user. + * + * The option is a: java.lang.String type. + * + * Group: security + * + * @param accessKey the value to set + * @return the dsl builder + */ + default MNSEndpointBuilder accessKey(String accessKey) { + doSetProperty("accessKey", accessKey); + return this; + } + /** + * Secret key for the cloud user. + * + * The option is a: java.lang.String type. + * + * Group: security + * + * @param secretKey the value to set + * @return the dsl builder + */ + default MNSEndpointBuilder secretKey(String secretKey) { + doSetProperty("secretKey", secretKey); + return this; + } + /** + * Configuration object for cloud service authentication. + * + * The option is a: + * org.apache.camel.component.alibaba.common.models.ServiceKeys type. + * + * Group: security + * + * @param serviceKeys the value to set + * @return the dsl builder + */ + default MNSEndpointBuilder serviceKeys(org.apache.camel.component.alibaba.common.models.ServiceKeys serviceKeys) { + doSetProperty("serviceKeys", serviceKeys); + return this; + } + /** + * Configuration object for cloud service authentication. + * + * The option will be converted to a + * org.apache.camel.component.alibaba.common.models.ServiceKeys type. + * + * Group: security + * + * @param serviceKeys the value to set + * @return the dsl builder + */ + default MNSEndpointBuilder serviceKeys(String serviceKeys) { + doSetProperty("serviceKeys", serviceKeys); + return this; + } + } + + /** + * Advanced builder for endpoint for the Alibaba Message Service (MNS) component. + */ + public interface AdvancedMNSEndpointBuilder + extends + AdvancedMNSEndpointConsumerBuilder, + AdvancedMNSEndpointProducerBuilder { + default MNSEndpointBuilder basic() { + return (MNSEndpointBuilder) this; + } + + /** + * Autowire an existing MNSClient instance. + * + * The option is a: com.aliyun.mns.client.MNSClient type. + * + * Group: advanced + * + * @param mnsClient the value to set + * @return the dsl builder + */ + default AdvancedMNSEndpointBuilder mnsClient(com.aliyun.mns.client.MNSClient mnsClient) { + doSetProperty("mnsClient", mnsClient); + return this; + } + /** + * Autowire an existing MNSClient instance. + * + * The option will be converted to a + * com.aliyun.mns.client.MNSClient type. + * + * Group: advanced + * + * @param mnsClient the value to set + * @return the dsl builder + */ + default AdvancedMNSEndpointBuilder mnsClient(String mnsClient) { + doSetProperty("mnsClient", mnsClient); + return this; + } + } + + public interface MNSBuilders { + /** + * Alibaba Message Service (MNS) (camel-alibaba-mns) + * Send and receive messages to/from Alibaba Cloud Message Service + * (MNS). + * + * Category: cloud,messaging + * Since: 4.23 + * Maven coordinates: org.apache.camel:camel-alibaba-mns + * + * @return the dsl builder for the headers' name. + */ + default MNSHeaderNameBuilder alibabaMns() { + return MNSHeaderNameBuilder.INSTANCE; + } + /** + * Alibaba Message Service (MNS) (camel-alibaba-mns) + * Send and receive messages to/from Alibaba Cloud Message Service + * (MNS). + * + * Category: cloud,messaging + * Since: 4.23 + * Maven coordinates: org.apache.camel:camel-alibaba-mns + * + * Syntax: alibaba-mns:queueName + * + * Path parameter: queueName (required) + * Queue name, or topic name when using the topic URI syntax + * + * @param path queueName + * @return the dsl builder + */ + default MNSEndpointBuilder alibabaMns(String path) { + return MNSEndpointBuilderFactory.endpointBuilder("alibaba-mns", path); + } + /** + * Alibaba Message Service (MNS) (camel-alibaba-mns) + * Send and receive messages to/from Alibaba Cloud Message Service + * (MNS). + * + * Category: cloud,messaging + * Since: 4.23 + * Maven coordinates: org.apache.camel:camel-alibaba-mns + * + * Syntax: alibaba-mns:queueName + * + * Path parameter: queueName (required) + * Queue name, or topic name when using the topic URI syntax + * + * @param componentName to use a custom component name for the endpoint + * instead of the default name + * @param path queueName + * @return the dsl builder + */ + default MNSEndpointBuilder alibabaMns(String componentName, String path) { + return MNSEndpointBuilderFactory.endpointBuilder(componentName, path); + } + + } + /** + * The builder of headers' name for the Alibaba Message Service (MNS) component. + */ + public static class MNSHeaderNameBuilder { + /** + * The internal instance of the builder used to access to all the + * methods representing the name of headers. + */ + public static final MNSHeaderNameBuilder INSTANCE = new MNSHeaderNameBuilder(); + + /** + * The MNS message id. + * + * The option is a: {@code String} type. + * + * Group: common + * + * @return the name of the header {@code AlibabaMnsMessageId}. + */ + public String alibabaMnsMessageId() { + return "CamelAlibabaMnsMessageId"; + } + /** + * The MNS receipt handle. + * + * The option is a: {@code String} type. + * + * Group: common + * + * @return the name of the header {@code AlibabaMnsReceiptHandle}. + */ + public String alibabaMnsReceiptHandle() { + return "CamelAlibabaMnsReceiptHandle"; + } + /** + * The MD5 digest of the message body. + * + * The option is a: {@code String} type. + * + * Group: common + * + * @return the name of the header {@code AlibabaMnsMessageBodyMd5}. + */ + public String alibabaMnsMessageBodyMd5() { + return "CamelAlibabaMnsMessageBodyMd5"; + } + /** + * Delay in seconds before the message becomes visible. + * + * The option is a: {@code Integer} type. + * + * Group: producer + * + * @return the name of the header {@code AlibabaMnsDelaySeconds}. + */ + public String alibabaMnsDelaySeconds() { + return "CamelAlibabaMnsDelaySeconds"; + } + /** + * Message priority. + * + * The option is a: {@code Integer} type. + * + * Group: producer + * + * @return the name of the header {@code AlibabaMnsPriority}. + */ + public String alibabaMnsPriority() { + return "CamelAlibabaMnsPriority"; + } + /** + * Message tag for topic publish operations. + * + * The option is a: {@code String} type. + * + * Group: producer + * + * @return the name of the header {@code AlibabaMnsMessageTag}. + */ + public String alibabaMnsMessageTag() { + return "CamelAlibabaMnsMessageTag"; + } + /** + * Number of times the message has been dequeued. + * + * The option is a: {@code Integer} type. + * + * Group: consumer + * + * @return the name of the header {@code AlibabaMnsDequeueCount}. + */ + public String alibabaMnsDequeueCount() { + return "CamelAlibabaMnsDequeueCount"; + } + /** + * Time when the message was enqueued. + * + * The option is a: {@code java.util.Date} type. + * + * Group: consumer + * + * @return the name of the header {@code AlibabaMnsEnqueueTime}. + */ + public String alibabaMnsEnqueueTime() { + return "CamelAlibabaMnsEnqueueTime"; + } + /** + * Next time the message becomes visible. + * + * The option is a: {@code java.util.Date} type. + * + * Group: consumer + * + * @return the name of the header {@code AlibabaMnsNextVisibleTime}. + */ + public String alibabaMnsNextVisibleTime() { + return "CamelAlibabaMnsNextVisibleTime"; + } + /** + * Time when the message was first dequeued. + * + * The option is a: {@code java.util.Date} type. + * + * Group: consumer + * + * @return the name of the header {@code AlibabaMnsFirstDequeueTime}. + */ + public String alibabaMnsFirstDequeueTime() { + return "CamelAlibabaMnsFirstDequeueTime"; + } + } + static MNSEndpointBuilder endpointBuilder(String componentName, String path) { + class MNSEndpointBuilderImpl extends AbstractEndpointBuilder implements MNSEndpointBuilder, AdvancedMNSEndpointBuilder { + public MNSEndpointBuilderImpl(String path) { + super(componentName, path); + } + } + return new MNSEndpointBuilderImpl(path); + } +} \ No newline at end of file diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/OSSEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/OSSEndpointBuilderFactory.java new file mode 100644 index 0000000000000..281627f2e5d9c --- /dev/null +++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/OSSEndpointBuilderFactory.java @@ -0,0 +1,1470 @@ +/* Generated by camel build tools - do NOT edit this file! */ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.builder.endpoint.dsl; + +import java.util.*; +import java.util.concurrent.*; +import java.util.function.*; +import java.util.stream.*; +import javax.annotation.processing.Generated; +import org.apache.camel.builder.EndpointConsumerBuilder; +import org.apache.camel.builder.EndpointProducerBuilder; +import org.apache.camel.builder.endpoint.AbstractEndpointBuilder; + +/** + * Alibaba Cloud Object Storage Service (OSS) component + * + * Generated by camel build tools - do NOT edit this file! + */ +@Generated("org.apache.camel.maven.packaging.EndpointDslMojo") +public interface OSSEndpointBuilderFactory { + + /** + * Builder for endpoint consumers for the Alibaba Object Storage Service (OSS) component. + */ + public interface OSSEndpointConsumerBuilder + extends + EndpointConsumerBuilder { + default AdvancedOSSEndpointConsumerBuilder advanced() { + return (AdvancedOSSEndpointConsumerBuilder) this; + } + /** + * OSS endpoint URL. Carries higher precedence than region based client + * initialization. + * + * The option is a: java.lang.String type. + * + * Group: common + * + * @param endpoint the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder endpoint(String endpoint) { + doSetProperty("endpoint", endpoint); + return this; + } + /** + * Name of object to perform operation with. + * + * The option is a: java.lang.String type. + * + * Group: common + * + * @param objectName the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder objectName(String objectName) { + doSetProperty("objectName", objectName); + return this; + } + /** + * OSS service region. + * + * The option is a: java.lang.String type. + * + * Required: true + * Group: common + * + * @param region the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder region(String region) { + doSetProperty("region", region); + return this; + } + /** + * Determines if objects should be deleted after they have been + * retrieved. + * + * The option is a: boolean type. + * + * Default: false + * Group: consumer + * + * @param deleteAfterRead the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder deleteAfterRead(boolean deleteAfterRead) { + doSetProperty("deleteAfterRead", deleteAfterRead); + return this; + } + /** + * Determines if objects should be deleted after they have been + * retrieved. + * + * The option will be converted to a boolean type. + * + * Default: false + * Group: consumer + * + * @param deleteAfterRead the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder deleteAfterRead(String deleteAfterRead) { + doSetProperty("deleteAfterRead", deleteAfterRead); + return this; + } + /** + * The maximum number of messages to poll at each polling. + * + * The option is a: int type. + * + * Default: 10 + * Group: consumer + * + * @param maxMessagesPerPoll the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder maxMessagesPerPoll(int maxMessagesPerPoll) { + doSetProperty("maxMessagesPerPoll", maxMessagesPerPoll); + return this; + } + /** + * The maximum number of messages to poll at each polling. + * + * The option will be converted to a int type. + * + * Default: 10 + * Group: consumer + * + * @param maxMessagesPerPoll the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder maxMessagesPerPoll(String maxMessagesPerPoll) { + doSetProperty("maxMessagesPerPoll", maxMessagesPerPoll); + return this; + } + /** + * The object name prefix used for filtering objects to be listed. + * + * The option is a: java.lang.String type. + * + * Group: consumer + * + * @param prefix the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder prefix(String prefix) { + doSetProperty("prefix", prefix); + return this; + } + /** + * If the polling consumer did not poll any files, you can enable this + * option to send an empty message (no body) instead. + * + * The option is a: boolean type. + * + * Default: false + * Group: consumer + * + * @param sendEmptyMessageWhenIdle the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder sendEmptyMessageWhenIdle(boolean sendEmptyMessageWhenIdle) { + doSetProperty("sendEmptyMessageWhenIdle", sendEmptyMessageWhenIdle); + return this; + } + /** + * If the polling consumer did not poll any files, you can enable this + * option to send an empty message (no body) instead. + * + * The option will be converted to a boolean type. + * + * Default: false + * Group: consumer + * + * @param sendEmptyMessageWhenIdle the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder sendEmptyMessageWhenIdle(String sendEmptyMessageWhenIdle) { + doSetProperty("sendEmptyMessageWhenIdle", sendEmptyMessageWhenIdle); + return this; + } + /** + * The number of subsequent error polls (failed due some error) that + * should happen before the backoffMultipler should kick-in. + * + * The option is a: int type. + * + * Group: scheduler + * + * @param backoffErrorThreshold the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder backoffErrorThreshold(int backoffErrorThreshold) { + doSetProperty("backoffErrorThreshold", backoffErrorThreshold); + return this; + } + /** + * The number of subsequent error polls (failed due some error) that + * should happen before the backoffMultipler should kick-in. + * + * The option will be converted to a int type. + * + * Group: scheduler + * + * @param backoffErrorThreshold the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder backoffErrorThreshold(String backoffErrorThreshold) { + doSetProperty("backoffErrorThreshold", backoffErrorThreshold); + return this; + } + /** + * The number of subsequent idle polls that should happen before the + * backoffMultipler should kick-in. + * + * The option is a: int type. + * + * Group: scheduler + * + * @param backoffIdleThreshold the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder backoffIdleThreshold(int backoffIdleThreshold) { + doSetProperty("backoffIdleThreshold", backoffIdleThreshold); + return this; + } + /** + * The number of subsequent idle polls that should happen before the + * backoffMultipler should kick-in. + * + * The option will be converted to a int type. + * + * Group: scheduler + * + * @param backoffIdleThreshold the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder backoffIdleThreshold(String backoffIdleThreshold) { + doSetProperty("backoffIdleThreshold", backoffIdleThreshold); + return this; + } + /** + * To let the scheduled polling consumer backoff if there has been a + * number of subsequent idles/errors in a row. The multiplier is then + * the number of polls that will be skipped before the next actual + * attempt is happening again. When this option is in use then + * backoffIdleThreshold and/or backoffErrorThreshold must also be + * configured. + * + * The option is a: int type. + * + * Group: scheduler + * + * @param backoffMultiplier the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder backoffMultiplier(int backoffMultiplier) { + doSetProperty("backoffMultiplier", backoffMultiplier); + return this; + } + /** + * To let the scheduled polling consumer backoff if there has been a + * number of subsequent idles/errors in a row. The multiplier is then + * the number of polls that will be skipped before the next actual + * attempt is happening again. When this option is in use then + * backoffIdleThreshold and/or backoffErrorThreshold must also be + * configured. + * + * The option will be converted to a int type. + * + * Group: scheduler + * + * @param backoffMultiplier the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder backoffMultiplier(String backoffMultiplier) { + doSetProperty("backoffMultiplier", backoffMultiplier); + return this; + } + /** + * Milliseconds before the next poll. + * + * The option is a: long type. + * + * Default: 500 + * Group: scheduler + * + * @param delay the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder delay(long delay) { + doSetProperty("delay", delay); + return this; + } + /** + * Milliseconds before the next poll. + * + * The option will be converted to a long type. + * + * Default: 500 + * Group: scheduler + * + * @param delay the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder delay(String delay) { + doSetProperty("delay", delay); + return this; + } + /** + * If greedy is enabled, then the ScheduledPollConsumer will run + * immediately again, if the previous run polled 1 or more messages. + * + * The option is a: boolean type. + * + * Default: false + * Group: scheduler + * + * @param greedy the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder greedy(boolean greedy) { + doSetProperty("greedy", greedy); + return this; + } + /** + * If greedy is enabled, then the ScheduledPollConsumer will run + * immediately again, if the previous run polled 1 or more messages. + * + * The option will be converted to a boolean type. + * + * Default: false + * Group: scheduler + * + * @param greedy the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder greedy(String greedy) { + doSetProperty("greedy", greedy); + return this; + } + /** + * Milliseconds before the first poll starts. + * + * The option is a: long type. + * + * Default: 1000 + * Group: scheduler + * + * @param initialDelay the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder initialDelay(long initialDelay) { + doSetProperty("initialDelay", initialDelay); + return this; + } + /** + * Milliseconds before the first poll starts. + * + * The option will be converted to a long type. + * + * Default: 1000 + * Group: scheduler + * + * @param initialDelay the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder initialDelay(String initialDelay) { + doSetProperty("initialDelay", initialDelay); + return this; + } + /** + * Specifies a maximum limit of number of fires. So if you set it to 1, + * the scheduler will only fire once. If you set it to 5, it will only + * fire five times. A value of zero or negative means fire forever. + * + * The option is a: long type. + * + * Default: 0 + * Group: scheduler + * + * @param repeatCount the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder repeatCount(long repeatCount) { + doSetProperty("repeatCount", repeatCount); + return this; + } + /** + * Specifies a maximum limit of number of fires. So if you set it to 1, + * the scheduler will only fire once. If you set it to 5, it will only + * fire five times. A value of zero or negative means fire forever. + * + * The option will be converted to a long type. + * + * Default: 0 + * Group: scheduler + * + * @param repeatCount the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder repeatCount(String repeatCount) { + doSetProperty("repeatCount", repeatCount); + return this; + } + /** + * The consumer logs a start/complete log line when it polls. This + * option allows you to configure the logging level for that. + * + * The option is a: org.apache.camel.LoggingLevel type. + * + * Default: TRACE + * Group: scheduler + * + * @param runLoggingLevel the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder runLoggingLevel(org.apache.camel.LoggingLevel runLoggingLevel) { + doSetProperty("runLoggingLevel", runLoggingLevel); + return this; + } + /** + * The consumer logs a start/complete log line when it polls. This + * option allows you to configure the logging level for that. + * + * The option will be converted to a + * org.apache.camel.LoggingLevel type. + * + * Default: TRACE + * Group: scheduler + * + * @param runLoggingLevel the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder runLoggingLevel(String runLoggingLevel) { + doSetProperty("runLoggingLevel", runLoggingLevel); + return this; + } + /** + * Allows for configuring a custom/shared thread pool to use for the + * consumer. By default each consumer has its own single threaded thread + * pool. + * + * The option is a: + * java.util.concurrent.ScheduledExecutorService type. + * + * Group: scheduler + * + * @param scheduledExecutorService the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder scheduledExecutorService(ScheduledExecutorService scheduledExecutorService) { + doSetProperty("scheduledExecutorService", scheduledExecutorService); + return this; + } + /** + * Allows for configuring a custom/shared thread pool to use for the + * consumer. By default each consumer has its own single threaded thread + * pool. + * + * The option will be converted to a + * java.util.concurrent.ScheduledExecutorService type. + * + * Group: scheduler + * + * @param scheduledExecutorService the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder scheduledExecutorService(String scheduledExecutorService) { + doSetProperty("scheduledExecutorService", scheduledExecutorService); + return this; + } + /** + * To use a cron scheduler from either camel-spring or camel-quartz + * component. Use value spring or quartz for built in scheduler. + * + * The option is a: java.lang.Object type. + * + * Default: none + * Group: scheduler + * + * @param scheduler the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder scheduler(Object scheduler) { + doSetProperty("scheduler", scheduler); + return this; + } + /** + * To use a cron scheduler from either camel-spring or camel-quartz + * component. Use value spring or quartz for built in scheduler. + * + * The option will be converted to a java.lang.Object type. + * + * Default: none + * Group: scheduler + * + * @param scheduler the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder scheduler(String scheduler) { + doSetProperty("scheduler", scheduler); + return this; + } + /** + * To configure additional properties when using a custom scheduler or + * any of the Quartz, Spring based scheduler. This is a multi-value + * option with prefix: scheduler. + * + * The option is a: java.util.Map<java.lang.String, + * java.lang.Object> type. + * The option is multivalued, and you can use the + * schedulerProperties(String, Object) method to add a value (call the + * method multiple times to set more values). + * + * Group: scheduler + * + * @param key the option key + * @param value the option value + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder schedulerProperties(String key, Object value) { + doSetMultiValueProperty("schedulerProperties", "scheduler." + key, value); + return this; + } + /** + * To configure additional properties when using a custom scheduler or + * any of the Quartz, Spring based scheduler. This is a multi-value + * option with prefix: scheduler. + * + * The option is a: java.util.Map<java.lang.String, + * java.lang.Object> type. + * The option is multivalued, and you can use the + * schedulerProperties(String, Object) method to add a value (call the + * method multiple times to set more values). + * + * Group: scheduler + * + * @param values the values + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder schedulerProperties(Map values) { + doSetMultiValueProperties("schedulerProperties", "scheduler.", values); + return this; + } + /** + * Whether the scheduler should be auto started. + * + * The option is a: boolean type. + * + * Default: true + * Group: scheduler + * + * @param startScheduler the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder startScheduler(boolean startScheduler) { + doSetProperty("startScheduler", startScheduler); + return this; + } + /** + * Whether the scheduler should be auto started. + * + * The option will be converted to a boolean type. + * + * Default: true + * Group: scheduler + * + * @param startScheduler the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder startScheduler(String startScheduler) { + doSetProperty("startScheduler", startScheduler); + return this; + } + /** + * Time unit for initialDelay and delay options. + * + * The option is a: java.util.concurrent.TimeUnit type. + * + * Default: MILLISECONDS + * Group: scheduler + * + * @param timeUnit the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder timeUnit(TimeUnit timeUnit) { + doSetProperty("timeUnit", timeUnit); + return this; + } + /** + * Time unit for initialDelay and delay options. + * + * The option will be converted to a + * java.util.concurrent.TimeUnit type. + * + * Default: MILLISECONDS + * Group: scheduler + * + * @param timeUnit the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder timeUnit(String timeUnit) { + doSetProperty("timeUnit", timeUnit); + return this; + } + /** + * Controls if fixed delay or fixed rate is used. See + * ScheduledExecutorService in JDK for details. + * + * The option is a: boolean type. + * + * Default: true + * Group: scheduler + * + * @param useFixedDelay the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder useFixedDelay(boolean useFixedDelay) { + doSetProperty("useFixedDelay", useFixedDelay); + return this; + } + /** + * Controls if fixed delay or fixed rate is used. See + * ScheduledExecutorService in JDK for details. + * + * The option will be converted to a boolean type. + * + * Default: true + * Group: scheduler + * + * @param useFixedDelay the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder useFixedDelay(String useFixedDelay) { + doSetProperty("useFixedDelay", useFixedDelay); + return this; + } + /** + * Access key for the cloud user. + * + * The option is a: java.lang.String type. + * + * Required: true + * Group: security + * + * @param accessKey the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder accessKey(String accessKey) { + doSetProperty("accessKey", accessKey); + return this; + } + /** + * Secret key for the cloud user. + * + * The option is a: java.lang.String type. + * + * Required: true + * Group: security + * + * @param secretKey the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder secretKey(String secretKey) { + doSetProperty("secretKey", secretKey); + return this; + } + /** + * Configuration object for cloud service authentication. + * + * The option is a: + * org.apache.camel.component.alibaba.common.models.ServiceKeys type. + * + * Group: security + * + * @param serviceKeys the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder serviceKeys(org.apache.camel.component.alibaba.common.models.ServiceKeys serviceKeys) { + doSetProperty("serviceKeys", serviceKeys); + return this; + } + /** + * Configuration object for cloud service authentication. + * + * The option will be converted to a + * org.apache.camel.component.alibaba.common.models.ServiceKeys type. + * + * Group: security + * + * @param serviceKeys the value to set + * @return the dsl builder + */ + default OSSEndpointConsumerBuilder serviceKeys(String serviceKeys) { + doSetProperty("serviceKeys", serviceKeys); + return this; + } + } + + /** + * Advanced builder for endpoint consumers for the Alibaba Object Storage Service (OSS) component. + */ + public interface AdvancedOSSEndpointConsumerBuilder + extends + EndpointConsumerBuilder { + default OSSEndpointConsumerBuilder basic() { + return (OSSEndpointConsumerBuilder) this; + } + /** + * Allows for bridging the consumer to the Camel routing Error Handler, + * which mean any exceptions (if possible) occurred while the Camel + * consumer is trying to pickup incoming messages, or the likes, will + * now be processed as a message and handled by the routing Error + * Handler. Important: This is only possible if the 3rd party component + * allows Camel to be alerted if an exception was thrown. Some + * components handle this internally only, and therefore + * bridgeErrorHandler is not possible. In other situations we may + * improve the Camel component to hook into the 3rd party component and + * make this possible for future releases. By default the consumer will + * use the org.apache.camel.spi.ExceptionHandler to deal with + * exceptions, that will be logged at WARN or ERROR level and ignored. + * + * The option is a: boolean type. + * + * Default: false + * Group: consumer (advanced) + * + * @param bridgeErrorHandler the value to set + * @return the dsl builder + */ + default AdvancedOSSEndpointConsumerBuilder bridgeErrorHandler(boolean bridgeErrorHandler) { + doSetProperty("bridgeErrorHandler", bridgeErrorHandler); + return this; + } + /** + * Allows for bridging the consumer to the Camel routing Error Handler, + * which mean any exceptions (if possible) occurred while the Camel + * consumer is trying to pickup incoming messages, or the likes, will + * now be processed as a message and handled by the routing Error + * Handler. Important: This is only possible if the 3rd party component + * allows Camel to be alerted if an exception was thrown. Some + * components handle this internally only, and therefore + * bridgeErrorHandler is not possible. In other situations we may + * improve the Camel component to hook into the 3rd party component and + * make this possible for future releases. By default the consumer will + * use the org.apache.camel.spi.ExceptionHandler to deal with + * exceptions, that will be logged at WARN or ERROR level and ignored. + * + * The option will be converted to a boolean type. + * + * Default: false + * Group: consumer (advanced) + * + * @param bridgeErrorHandler the value to set + * @return the dsl builder + */ + default AdvancedOSSEndpointConsumerBuilder bridgeErrorHandler(String bridgeErrorHandler) { + doSetProperty("bridgeErrorHandler", bridgeErrorHandler); + return this; + } + /** + * To let the consumer use a custom ExceptionHandler. Notice if the + * option bridgeErrorHandler is enabled then this option is not in use. + * By default the consumer will deal with exceptions, that will be + * logged at WARN or ERROR level and ignored. + * + * The option is a: org.apache.camel.spi.ExceptionHandler + * type. + * + * Group: consumer (advanced) + * + * @param exceptionHandler the value to set + * @return the dsl builder + */ + default AdvancedOSSEndpointConsumerBuilder exceptionHandler(org.apache.camel.spi.ExceptionHandler exceptionHandler) { + doSetProperty("exceptionHandler", exceptionHandler); + return this; + } + /** + * To let the consumer use a custom ExceptionHandler. Notice if the + * option bridgeErrorHandler is enabled then this option is not in use. + * By default the consumer will deal with exceptions, that will be + * logged at WARN or ERROR level and ignored. + * + * The option will be converted to a + * org.apache.camel.spi.ExceptionHandler type. + * + * Group: consumer (advanced) + * + * @param exceptionHandler the value to set + * @return the dsl builder + */ + default AdvancedOSSEndpointConsumerBuilder exceptionHandler(String exceptionHandler) { + doSetProperty("exceptionHandler", exceptionHandler); + return this; + } + /** + * Sets the exchange pattern when the consumer creates an exchange. + * + * The option is a: org.apache.camel.ExchangePattern type. + * + * Group: consumer (advanced) + * + * @param exchangePattern the value to set + * @return the dsl builder + */ + default AdvancedOSSEndpointConsumerBuilder exchangePattern(org.apache.camel.ExchangePattern exchangePattern) { + doSetProperty("exchangePattern", exchangePattern); + return this; + } + /** + * Sets the exchange pattern when the consumer creates an exchange. + * + * The option will be converted to a + * org.apache.camel.ExchangePattern type. + * + * Group: consumer (advanced) + * + * @param exchangePattern the value to set + * @return the dsl builder + */ + default AdvancedOSSEndpointConsumerBuilder exchangePattern(String exchangePattern) { + doSetProperty("exchangePattern", exchangePattern); + return this; + } + /** + * A pluggable org.apache.camel.PollingConsumerPollingStrategy allowing + * you to provide your custom implementation to control error handling + * usually occurred during the poll operation before an Exchange have + * been created and being routed in Camel. + * + * The option is a: + * org.apache.camel.spi.PollingConsumerPollStrategy type. + * + * Group: consumer (advanced) + * + * @param pollStrategy the value to set + * @return the dsl builder + */ + default AdvancedOSSEndpointConsumerBuilder pollStrategy(org.apache.camel.spi.PollingConsumerPollStrategy pollStrategy) { + doSetProperty("pollStrategy", pollStrategy); + return this; + } + /** + * A pluggable org.apache.camel.PollingConsumerPollingStrategy allowing + * you to provide your custom implementation to control error handling + * usually occurred during the poll operation before an Exchange have + * been created and being routed in Camel. + * + * The option will be converted to a + * org.apache.camel.spi.PollingConsumerPollStrategy type. + * + * Group: consumer (advanced) + * + * @param pollStrategy the value to set + * @return the dsl builder + */ + default AdvancedOSSEndpointConsumerBuilder pollStrategy(String pollStrategy) { + doSetProperty("pollStrategy", pollStrategy); + return this; + } + /** + * An autowired OSS client. + * + * The option is a: com.aliyun.sdk.service.oss2.OSSClient + * type. + * + * Group: advanced + * + * @param ossClient the value to set + * @return the dsl builder + */ + default AdvancedOSSEndpointConsumerBuilder ossClient(com.aliyun.sdk.service.oss2.OSSClient ossClient) { + doSetProperty("ossClient", ossClient); + return this; + } + /** + * An autowired OSS client. + * + * The option will be converted to a + * com.aliyun.sdk.service.oss2.OSSClient type. + * + * Group: advanced + * + * @param ossClient the value to set + * @return the dsl builder + */ + default AdvancedOSSEndpointConsumerBuilder ossClient(String ossClient) { + doSetProperty("ossClient", ossClient); + return this; + } + } + + /** + * Builder for endpoint producers for the Alibaba Object Storage Service (OSS) component. + */ + public interface OSSEndpointProducerBuilder + extends + EndpointProducerBuilder { + default AdvancedOSSEndpointProducerBuilder advanced() { + return (AdvancedOSSEndpointProducerBuilder) this; + } + + /** + * OSS endpoint URL. Carries higher precedence than region based client + * initialization. + * + * The option is a: java.lang.String type. + * + * Group: common + * + * @param endpoint the value to set + * @return the dsl builder + */ + default OSSEndpointProducerBuilder endpoint(String endpoint) { + doSetProperty("endpoint", endpoint); + return this; + } + /** + * Name of object to perform operation with. + * + * The option is a: java.lang.String type. + * + * Group: common + * + * @param objectName the value to set + * @return the dsl builder + */ + default OSSEndpointProducerBuilder objectName(String objectName) { + doSetProperty("objectName", objectName); + return this; + } + /** + * OSS service region. + * + * The option is a: java.lang.String type. + * + * Required: true + * Group: common + * + * @param region the value to set + * @return the dsl builder + */ + default OSSEndpointProducerBuilder region(String region) { + doSetProperty("region", region); + return this; + } + /** + * Operation to be performed. + * + * The option is a: java.lang.String type. + * + * Group: producer + * + * @param operation the value to set + * @return the dsl builder + */ + default OSSEndpointProducerBuilder operation(String operation) { + doSetProperty("operation", operation); + return this; + } + /** + * Access key for the cloud user. + * + * The option is a: java.lang.String type. + * + * Required: true + * Group: security + * + * @param accessKey the value to set + * @return the dsl builder + */ + default OSSEndpointProducerBuilder accessKey(String accessKey) { + doSetProperty("accessKey", accessKey); + return this; + } + /** + * Secret key for the cloud user. + * + * The option is a: java.lang.String type. + * + * Required: true + * Group: security + * + * @param secretKey the value to set + * @return the dsl builder + */ + default OSSEndpointProducerBuilder secretKey(String secretKey) { + doSetProperty("secretKey", secretKey); + return this; + } + /** + * Configuration object for cloud service authentication. + * + * The option is a: + * org.apache.camel.component.alibaba.common.models.ServiceKeys type. + * + * Group: security + * + * @param serviceKeys the value to set + * @return the dsl builder + */ + default OSSEndpointProducerBuilder serviceKeys(org.apache.camel.component.alibaba.common.models.ServiceKeys serviceKeys) { + doSetProperty("serviceKeys", serviceKeys); + return this; + } + /** + * Configuration object for cloud service authentication. + * + * The option will be converted to a + * org.apache.camel.component.alibaba.common.models.ServiceKeys type. + * + * Group: security + * + * @param serviceKeys the value to set + * @return the dsl builder + */ + default OSSEndpointProducerBuilder serviceKeys(String serviceKeys) { + doSetProperty("serviceKeys", serviceKeys); + return this; + } + } + + /** + * Advanced builder for endpoint producers for the Alibaba Object Storage Service (OSS) component. + */ + public interface AdvancedOSSEndpointProducerBuilder extends EndpointProducerBuilder { + default OSSEndpointProducerBuilder basic() { + return (OSSEndpointProducerBuilder) this; + } + + /** + * 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 during + * starting and cause the route to fail being started. By deferring this + * startup to be lazy then the startup failure can be handled during + * routing messages via Camel's routing error handlers. Beware that when + * the first message is processed then creating and starting the + * producer may take a little time and prolong the total processing time + * of the processing. + * + * The option is a: boolean type. + * + * Default: false + * Group: producer (advanced) + * + * @param lazyStartProducer the value to set + * @return the dsl builder + */ + default AdvancedOSSEndpointProducerBuilder lazyStartProducer(boolean lazyStartProducer) { + doSetProperty("lazyStartProducer", lazyStartProducer); + return this; + } + /** + * 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 during + * starting and cause the route to fail being started. By deferring this + * startup to be lazy then the startup failure can be handled during + * routing messages via Camel's routing error handlers. Beware that when + * the first message is processed then creating and starting the + * producer may take a little time and prolong the total processing time + * of the processing. + * + * The option will be converted to a boolean type. + * + * Default: false + * Group: producer (advanced) + * + * @param lazyStartProducer the value to set + * @return the dsl builder + */ + default AdvancedOSSEndpointProducerBuilder lazyStartProducer(String lazyStartProducer) { + doSetProperty("lazyStartProducer", lazyStartProducer); + return this; + } + /** + * An autowired OSS client. + * + * The option is a: com.aliyun.sdk.service.oss2.OSSClient + * type. + * + * Group: advanced + * + * @param ossClient the value to set + * @return the dsl builder + */ + default AdvancedOSSEndpointProducerBuilder ossClient(com.aliyun.sdk.service.oss2.OSSClient ossClient) { + doSetProperty("ossClient", ossClient); + return this; + } + /** + * An autowired OSS client. + * + * The option will be converted to a + * com.aliyun.sdk.service.oss2.OSSClient type. + * + * Group: advanced + * + * @param ossClient the value to set + * @return the dsl builder + */ + default AdvancedOSSEndpointProducerBuilder ossClient(String ossClient) { + doSetProperty("ossClient", ossClient); + return this; + } + } + + /** + * Builder for endpoint for the Alibaba Object Storage Service (OSS) component. + */ + public interface OSSEndpointBuilder + extends + OSSEndpointConsumerBuilder, + OSSEndpointProducerBuilder { + default AdvancedOSSEndpointBuilder advanced() { + return (AdvancedOSSEndpointBuilder) this; + } + + /** + * OSS endpoint URL. Carries higher precedence than region based client + * initialization. + * + * The option is a: java.lang.String type. + * + * Group: common + * + * @param endpoint the value to set + * @return the dsl builder + */ + default OSSEndpointBuilder endpoint(String endpoint) { + doSetProperty("endpoint", endpoint); + return this; + } + /** + * Name of object to perform operation with. + * + * The option is a: java.lang.String type. + * + * Group: common + * + * @param objectName the value to set + * @return the dsl builder + */ + default OSSEndpointBuilder objectName(String objectName) { + doSetProperty("objectName", objectName); + return this; + } + /** + * OSS service region. + * + * The option is a: java.lang.String type. + * + * Required: true + * Group: common + * + * @param region the value to set + * @return the dsl builder + */ + default OSSEndpointBuilder region(String region) { + doSetProperty("region", region); + return this; + } + /** + * Access key for the cloud user. + * + * The option is a: java.lang.String type. + * + * Required: true + * Group: security + * + * @param accessKey the value to set + * @return the dsl builder + */ + default OSSEndpointBuilder accessKey(String accessKey) { + doSetProperty("accessKey", accessKey); + return this; + } + /** + * Secret key for the cloud user. + * + * The option is a: java.lang.String type. + * + * Required: true + * Group: security + * + * @param secretKey the value to set + * @return the dsl builder + */ + default OSSEndpointBuilder secretKey(String secretKey) { + doSetProperty("secretKey", secretKey); + return this; + } + /** + * Configuration object for cloud service authentication. + * + * The option is a: + * org.apache.camel.component.alibaba.common.models.ServiceKeys type. + * + * Group: security + * + * @param serviceKeys the value to set + * @return the dsl builder + */ + default OSSEndpointBuilder serviceKeys(org.apache.camel.component.alibaba.common.models.ServiceKeys serviceKeys) { + doSetProperty("serviceKeys", serviceKeys); + return this; + } + /** + * Configuration object for cloud service authentication. + * + * The option will be converted to a + * org.apache.camel.component.alibaba.common.models.ServiceKeys type. + * + * Group: security + * + * @param serviceKeys the value to set + * @return the dsl builder + */ + default OSSEndpointBuilder serviceKeys(String serviceKeys) { + doSetProperty("serviceKeys", serviceKeys); + return this; + } + } + + /** + * Advanced builder for endpoint for the Alibaba Object Storage Service (OSS) component. + */ + public interface AdvancedOSSEndpointBuilder + extends + AdvancedOSSEndpointConsumerBuilder, + AdvancedOSSEndpointProducerBuilder { + default OSSEndpointBuilder basic() { + return (OSSEndpointBuilder) this; + } + + /** + * An autowired OSS client. + * + * The option is a: com.aliyun.sdk.service.oss2.OSSClient + * type. + * + * Group: advanced + * + * @param ossClient the value to set + * @return the dsl builder + */ + default AdvancedOSSEndpointBuilder ossClient(com.aliyun.sdk.service.oss2.OSSClient ossClient) { + doSetProperty("ossClient", ossClient); + return this; + } + /** + * An autowired OSS client. + * + * The option will be converted to a + * com.aliyun.sdk.service.oss2.OSSClient type. + * + * Group: advanced + * + * @param ossClient the value to set + * @return the dsl builder + */ + default AdvancedOSSEndpointBuilder ossClient(String ossClient) { + doSetProperty("ossClient", ossClient); + return this; + } + } + + public interface OSSBuilders { + /** + * Alibaba Object Storage Service (OSS) (camel-alibaba-oss) + * Alibaba Cloud Object Storage Service (OSS) component + * + * Category: cloud + * Since: 4.23 + * Maven coordinates: org.apache.camel:camel-alibaba-oss + * + * @return the dsl builder for the headers' name. + */ + default OSSHeaderNameBuilder alibabaOss() { + return OSSHeaderNameBuilder.INSTANCE; + } + /** + * Alibaba Object Storage Service (OSS) (camel-alibaba-oss) + * Alibaba Cloud Object Storage Service (OSS) component + * + * Category: cloud + * Since: 4.23 + * Maven coordinates: org.apache.camel:camel-alibaba-oss + * + * Syntax: alibaba-oss:bucketName + * + * Path parameter: bucketName + * Name of bucket to perform operation on + * + * @param path bucketName + * @return the dsl builder + */ + default OSSEndpointBuilder alibabaOss(String path) { + return OSSEndpointBuilderFactory.endpointBuilder("alibaba-oss", path); + } + /** + * Alibaba Object Storage Service (OSS) (camel-alibaba-oss) + * Alibaba Cloud Object Storage Service (OSS) component + * + * Category: cloud + * Since: 4.23 + * Maven coordinates: org.apache.camel:camel-alibaba-oss + * + * Syntax: alibaba-oss:bucketName + * + * Path parameter: bucketName + * Name of bucket to perform operation on + * + * @param componentName to use a custom component name for the endpoint + * instead of the default name + * @param path bucketName + * @return the dsl builder + */ + default OSSEndpointBuilder alibabaOss(String componentName, String path) { + return OSSEndpointBuilderFactory.endpointBuilder(componentName, path); + } + + } + /** + * The builder of headers' name for the Alibaba Object Storage Service (OSS) component. + */ + public static class OSSHeaderNameBuilder { + /** + * The internal instance of the builder used to access to all the + * methods representing the name of headers. + */ + public static final OSSHeaderNameBuilder INSTANCE = new OSSHeaderNameBuilder(); + + /** + * Name of the bucket where object is contained. + * + * The option is a: {@code String} type. + * + * Group: consumer + * + * @return the name of the header {@code AlibabaOssBucketName}. + */ + public String alibabaOssBucketName() { + return "CamelAlibabaOssBucketName"; + } + /** + * The key that the object is stored under. + * + * The option is a: {@code String} type. + * + * Group: consumer + * + * @return the name of the header {@code AlibabaOssObjectKey}. + */ + public String alibabaOssObjectKey() { + return "CamelAlibabaOssObjectKey"; + } + /** + * The date and time that the object was last modified. + * + * The option is a: {@code String} type. + * + * Group: consumer + * + * @return the name of the header {@code AlibabaOssLastModified}. + */ + public String alibabaOssLastModified() { + return "CamelAlibabaOssLastModified"; + } + /** + * The 128-bit MD5 digest of the object content. + * + * The option is a: {@code String} type. + * + * Group: consumer + * + * @return the name of the header {@code AlibabaOssETag}. + */ + public String alibabaOssETag() { + return "CamelAlibabaOssETag"; + } + /** + * The 128-bit Base64-encoded digest of the object. + * + * The option is a: {@code String} type. + * + * Group: consumer + * + * @return the name of the header {@code AlibabaOssContentMD5}. + */ + public String alibabaOssContentMD5() { + return "CamelAlibabaOssContentMD5"; + } + /** + * Shows whether the object is a file or a folder. + * + * The option is a: {@code String} type. + * + * Group: consumer + * + * @return the name of the header {@code AlibabaOssObjectType}. + */ + public String alibabaOssObjectType() { + return "CamelAlibabaOssObjectType"; + } + /** + * The size of the object body in bytes. + * + * The option is a: {@code Long} type. + * + * Group: consumer + * + * @return the name of the header {@code AlibabaOssContentLength}. + */ + public String alibabaOssContentLength() { + return "CamelAlibabaOssContentLength"; + } + /** + * The type of content stored in the object. + * + * The option is a: {@code String} type. + * + * Group: consumer + * + * @return the name of the header {@code AlibabaOssContentType}. + */ + public String alibabaOssContentType() { + return "CamelAlibabaOssContentType"; + } + /** + * Name of the object with which the operation is to be performed. + * + * The option is a: {@code String} type. + * + * Group: consumer + * + * @return the name of the header {@code FileName}. + */ + public String fileName() { + return "CamelFileName"; + } + } + static OSSEndpointBuilder endpointBuilder(String componentName, String path) { + class OSSEndpointBuilderImpl extends AbstractEndpointBuilder implements OSSEndpointBuilder, AdvancedOSSEndpointBuilder { + public OSSEndpointBuilderImpl(String path) { + super(componentName, path); + } + } + return new OSSEndpointBuilderImpl(path); + } +} \ No newline at end of file diff --git a/dsl/camel-kamelet-main/src/generated/resources/camel-component-known-dependencies.properties b/dsl/camel-kamelet-main/src/generated/resources/camel-component-known-dependencies.properties index 9e616b03ac047..48b275c712df8 100644 --- a/dsl/camel-kamelet-main/src/generated/resources/camel-component-known-dependencies.properties +++ b/dsl/camel-kamelet-main/src/generated/resources/camel-component-known-dependencies.properties @@ -21,6 +21,8 @@ org.apache.camel.component.a2a.A2AComponent=camel:a2a org.apache.camel.component.activemq.ActiveMQComponent=camel:activemq org.apache.camel.component.activemq6.ActiveMQComponent=camel:activemq6 org.apache.camel.component.ai.tool.AiToolComponent=camel:ai-tool +org.apache.camel.component.alibaba.mns.MNSComponent=camel:alibaba-mns +org.apache.camel.component.alibaba.oss.OSSComponent=camel:alibaba-oss org.apache.camel.component.amqp.AMQPComponent=camel:amqp org.apache.camel.component.arangodb.ArangoDbComponent=camel:arangodb org.apache.camel.component.as2.AS2Component=camel:as2