This is an automated email from the ASF dual-hosted git repository. acosentino pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/master by this push: new 8757e5a CAMEL-12135 - Camel-AWS S3: Add the ability to specify credentials and region at component level 8757e5a is described below commit 8757e5aac64107732f43a58e4ea23940b1c11429 Author: Andrea Cosentino <anco...@gmail.com> AuthorDate: Fri Jan 12 09:13:01 2018 +0100 CAMEL-12135 - Camel-AWS S3: Add the ability to specify credentials and region at component level --- .../camel-aws/src/main/docs/aws-s3-component.adoc | 14 +- .../apache/camel/component/aws/s3/S3Component.java | 68 +++- .../camel/component/aws/s3/S3Configuration.java | 13 + .../aws/s3/S3ComponentConfigurationTest.java | 28 ++ .../s3/springboot/S3ComponentConfiguration.java | 366 +++++++++++++++++++++ 5 files changed, 487 insertions(+), 2 deletions(-) diff --git a/components/camel-aws/src/main/docs/aws-s3-component.adoc b/components/camel-aws/src/main/docs/aws-s3-component.adoc index 8d3b027..b6a5c39 100644 --- a/components/camel-aws/src/main/docs/aws-s3-component.adoc +++ b/components/camel-aws/src/main/docs/aws-s3-component.adoc @@ -35,7 +35,19 @@ from("aws-s3:helloBucket?accessKey=yourAccessKey&secretKey=yourSecretKey&prefix= // component options: START -The AWS S3 Storage Service component has no options. +The AWS S3 Storage Service component supports 5 options which are listed below. + + + +[width="100%",cols="2,5,^1,2",options="header"] +|=== +| Name | Description | Default | Type +| *configuration* (advanced) | The AWS S3 default configuration | | S3Configuration +| *accessKey* (common) | Amazon AWS Access Key | | String +| *secretKey* (common) | Amazon AWS Secret Key | | String +| *region* (common) | The region where the bucket is located. This option is used in the com.amazonaws.services.s3.model.CreateBucketRequest. | | String +| *resolveProperty Placeholders* (advanced) | Whether the component should resolve property placeholders on itself when starting. Only properties which are of String type can use property placeholders. | true | boolean +|=== // component options: END diff --git a/components/camel-aws/src/main/java/org/apache/camel/component/aws/s3/S3Component.java b/components/camel-aws/src/main/java/org/apache/camel/component/aws/s3/S3Component.java index 0e56f44..f17dc31 100644 --- a/components/camel-aws/src/main/java/org/apache/camel/component/aws/s3/S3Component.java +++ b/components/camel-aws/src/main/java/org/apache/camel/component/aws/s3/S3Component.java @@ -21,9 +21,20 @@ import java.util.Map; import org.apache.camel.CamelContext; import org.apache.camel.Endpoint; import org.apache.camel.impl.DefaultComponent; +import org.apache.camel.spi.Metadata; +import org.apache.camel.util.ObjectHelper; public class S3Component extends DefaultComponent { + @Metadata + private String accessKey; + @Metadata + private String secretKey; + @Metadata + private String region; + @Metadata(label = "advanced") + private S3Configuration configuration; + public S3Component() { this(null); } @@ -31,11 +42,12 @@ public class S3Component extends DefaultComponent { public S3Component(CamelContext context) { super(context); + this.configuration = new S3Configuration(); registerExtension(new S3ComponentVerifierExtension()); } protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception { - S3Configuration configuration = new S3Configuration(); + final S3Configuration configuration = this.configuration.copy(); setProperties(configuration, parameters); if (remaining == null || remaining.trim().length() == 0) { @@ -46,6 +58,15 @@ public class S3Component extends DefaultComponent { } configuration.setBucketName(remaining); + if (ObjectHelper.isEmpty(configuration.getAccessKey())) { + setAccessKey(accessKey); + } + if (ObjectHelper.isEmpty(configuration.getSecretKey())) { + setSecretKey(secretKey); + } + if (ObjectHelper.isEmpty(configuration.getRegion())) { + setRegion(region); + } if (configuration.getAmazonS3Client() == null && (configuration.getAccessKey() == null || configuration.getSecretKey() == null)) { throw new IllegalArgumentException("AmazonS3Client or accessKey and secretKey must be specified"); } @@ -54,4 +75,49 @@ public class S3Component extends DefaultComponent { setProperties(endpoint, parameters); return endpoint; } + + public S3Configuration getConfiguration() { + return configuration; + } + + /** + * The AWS S3 default configuration + */ + public void setConfiguration(S3Configuration configuration) { + this.configuration = configuration; + } + + public String getAccessKey() { + return configuration.getAccessKey(); + } + + /** + * Amazon AWS Access Key + */ + public void setAccessKey(String accessKey) { + configuration.setAccessKey(accessKey); + } + + public String getSecretKey() { + return configuration.getSecretKey(); + } + + /** + * Amazon AWS Secret Key + */ + public void setSecretKey(String secretKey) { + configuration.setSecretKey(secretKey); + } + + public String getRegion() { + return configuration.getRegion(); + } + + /** + * The region where the bucket is located. This option is used in the + * `com.amazonaws.services.s3.model.CreateBucketRequest`. + */ + public void setRegion(String region) { + configuration.setRegion(region); + } } diff --git a/components/camel-aws/src/main/java/org/apache/camel/component/aws/s3/S3Configuration.java b/components/camel-aws/src/main/java/org/apache/camel/component/aws/s3/S3Configuration.java index fcca089..2e0ba6a 100644 --- a/components/camel-aws/src/main/java/org/apache/camel/component/aws/s3/S3Configuration.java +++ b/components/camel-aws/src/main/java/org/apache/camel/component/aws/s3/S3Configuration.java @@ -19,6 +19,7 @@ package org.apache.camel.component.aws.s3; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.model.EncryptionMaterials; +import org.apache.camel.RuntimeCamelException; import org.apache.camel.spi.UriParam; import org.apache.camel.spi.UriParams; import org.apache.camel.util.ObjectHelper; @@ -358,4 +359,16 @@ public class S3Configuration implements Cloneable { boolean hasProxyConfiguration() { return ObjectHelper.isNotEmpty(getProxyHost()) && ObjectHelper.isNotEmpty(getProxyPort()); } + + // ************************************************* + // + // ************************************************* + + public S3Configuration copy() { + try { + return (S3Configuration)super.clone(); + } catch (CloneNotSupportedException e) { + throw new RuntimeCamelException(e); + } + } } diff --git a/components/camel-aws/src/test/java/org/apache/camel/component/aws/s3/S3ComponentConfigurationTest.java b/components/camel-aws/src/test/java/org/apache/camel/component/aws/s3/S3ComponentConfigurationTest.java index 39ec751..1437cd3 100644 --- a/components/camel-aws/src/test/java/org/apache/camel/component/aws/s3/S3ComponentConfigurationTest.java +++ b/components/camel-aws/src/test/java/org/apache/camel/component/aws/s3/S3ComponentConfigurationTest.java @@ -16,6 +16,8 @@ */ package org.apache.camel.component.aws.s3; +import com.amazonaws.regions.Regions; + import org.apache.camel.impl.JndiRegistry; import org.apache.camel.impl.PropertyPlaceholderDelegateRegistry; import org.apache.camel.test.junit4.CamelTestSupport; @@ -144,6 +146,32 @@ public class S3ComponentConfigurationTest extends CamelTestSupport { } @Test + public void createEndpointWithComponentElements() throws Exception { + S3Component component = new S3Component(context); + component.setAccessKey("XXX"); + component.setSecretKey("YYY"); + S3Endpoint endpoint = (S3Endpoint)component.createEndpoint("aws-s3://MyBucket"); + + assertEquals("MyBucket", endpoint.getConfiguration().getBucketName()); + assertEquals("XXX", endpoint.getConfiguration().getAccessKey()); + assertEquals("YYY", endpoint.getConfiguration().getSecretKey()); + } + + @Test + public void createEndpointWithComponentAndEndpointElements() throws Exception { + S3Component component = new S3Component(context); + component.setAccessKey("XXX"); + component.setSecretKey("YYY"); + component.setRegion(Regions.US_WEST_1.toString()); + S3Endpoint endpoint = (S3Endpoint)component.createEndpoint("aws-s3://MyBucket?accessKey=xxxxxx&secretKey=yyyyy®ion=US_EAST_1"); + + assertEquals("MyBucket", endpoint.getConfiguration().getBucketName()); + assertEquals("xxxxxx", endpoint.getConfiguration().getAccessKey()); + assertEquals("yyyyy", endpoint.getConfiguration().getSecretKey()); + assertEquals("US_EAST_1", endpoint.getConfiguration().getRegion()); + } + + @Test public void createEndpointWithoutSecretKeyAndAccessKeyConfiguration() throws Exception { AmazonS3ClientMock mock = new AmazonS3ClientMock(); diff --git a/platforms/spring-boot/components-starter/camel-aws-starter/src/main/java/org/apache/camel/component/aws/s3/springboot/S3ComponentConfiguration.java b/platforms/spring-boot/components-starter/camel-aws-starter/src/main/java/org/apache/camel/component/aws/s3/springboot/S3ComponentConfiguration.java index 9696eea..9ca5603 100644 --- a/platforms/spring-boot/components-starter/camel-aws-starter/src/main/java/org/apache/camel/component/aws/s3/springboot/S3ComponentConfiguration.java +++ b/platforms/spring-boot/components-starter/camel-aws-starter/src/main/java/org/apache/camel/component/aws/s3/springboot/S3ComponentConfiguration.java @@ -17,8 +17,12 @@ package org.apache.camel.component.aws.s3.springboot; import javax.annotation.Generated; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.model.EncryptionMaterials; +import org.apache.camel.component.aws.s3.S3Operations; import org.apache.camel.spring.boot.ComponentConfigurationPropertiesCommon; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.NestedConfigurationProperty; /** * The aws-s3 component is used for storing and retrieving objecct from Amazon @@ -33,12 +37,62 @@ public class S3ComponentConfiguration ComponentConfigurationPropertiesCommon { /** + * The AWS S3 default configuration + */ + private S3ConfigurationNestedConfiguration configuration; + /** + * Amazon AWS Access Key + */ + private String accessKey; + /** + * Amazon AWS Secret Key + */ + private String secretKey; + /** + * The region where the bucket is located. This option is used in the + * com.amazonaws.services.s3.model.CreateBucketRequest. + */ + private String region; + /** * Whether the component should resolve property placeholders on itself when * starting. Only properties which are of String type can use property * placeholders. */ private Boolean resolvePropertyPlaceholders = true; + public S3ConfigurationNestedConfiguration getConfiguration() { + return configuration; + } + + public void setConfiguration( + S3ConfigurationNestedConfiguration configuration) { + this.configuration = configuration; + } + + 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 Boolean getResolvePropertyPlaceholders() { return resolvePropertyPlaceholders; } @@ -47,4 +101,316 @@ public class S3ComponentConfiguration Boolean resolvePropertyPlaceholders) { this.resolvePropertyPlaceholders = resolvePropertyPlaceholders; } + + public static class S3ConfigurationNestedConfiguration { + public static final Class CAMEL_NESTED_CLASS = org.apache.camel.component.aws.s3.S3Configuration.class; + /** + * Setup the partSize which is used in multi part upload, the default + * size is 25M. + */ + private Long partSize = 26214400L; + /** + * If it is true, camel will upload the file with multi part format, the + * part size is decided by the option of `partSize` + */ + private Boolean multiPartUpload = false; + /** + * The region with which the AWS-S3 client wants to work with. + */ + private String amazonS3Endpoint; + /** + * Amazon AWS Access Key + */ + private String accessKey; + /** + * Amazon AWS Secret Key + */ + private String secretKey; + /** + * Reference to a `com.amazonaws.services.sqs.AmazonS3` in the + * link:registry.html[Registry]. + */ + private AmazonS3 amazonS3Client; + /** + * The prefix which is used in the + * com.amazonaws.services.s3.model.ListObjectsRequest to only consume + * objects we are interested in. + */ + private String prefix; + /** + * Name of the bucket. The bucket will be created if it doesn't already + * exists. + */ + private String bucketName; + /** + * To get the object from the bucket with the given file name + */ + private String fileName; + /** + * The region where the bucket is located. This option is used in the + * `com.amazonaws.services.s3.model.CreateBucketRequest`. + */ + private String region; + /** + * If it is true, the exchange body will be set to a stream to the + * contents of the file. If false, the headers will be set with the S3 + * object metadata, but the body will be null. This option is strongly + * related to autocloseBody option. In case of setting includeBody to + * true and autocloseBody to false, it will be up to the caller to close + * the S3Object stream. Setting autocloseBody to true, will close the + * S3Object stream automatically. + */ + private Boolean includeBody = true; + /** + * Delete objects from S3 after they have been retrieved. The delete is + * only performed if the Exchange is committed. If a rollback occurs, + * the object is not deleted. + * <p/> + * If this option is false, then the same objects will be retrieve over + * and over again on the polls. Therefore you need to use the Idempotent + * Consumer EIP in the route to filter out duplicates. You can filter + * using the {@link S3Constants#BUCKET_NAME} and {@link S3Constants#KEY} + * headers, or only the {@link S3Constants#KEY} header. + */ + private Boolean deleteAfterRead = true; + /** + * Delete file object after the S3 file has been uploaded + */ + private Boolean deleteAfterWrite = false; + /** + * The policy for this queue to set in the + * `com.amazonaws.services.s3.AmazonS3#setBucketPolicy()` method. + */ + private String policy; + /** + * The storage class to set in the + * `com.amazonaws.services.s3.model.PutObjectRequest` request. + */ + private String storageClass; + /** + * Sets the server-side encryption algorithm when encrypting the object + * using AWS-managed keys. For example use <tt>AES256</tt>. + */ + private String serverSideEncryption; + /** + * To define a proxy host when instantiating the SQS client + */ + private String proxyHost; + /** + * Specify a proxy port to be used inside the client definition. + */ + private Integer proxyPort; + /** + * Whether or not the S3 client should use path style access + */ + private Boolean pathStyleAccess = false; + /** + * The operation to do in case the user don't want to do only an upload + */ + private S3Operations operation; + /** + * If this option is true and includeBody is true, then the + * S3Object.close() method will be called on exchange completion. This + * option is strongly related to includeBody option. In case of setting + * includeBody to true and autocloseBody to false, it will be up to the + * caller to close the S3Object stream. Setting autocloseBody to true, + * will close the S3Object stream automatically. + */ + private Boolean autocloseBody = true; + /** + * The encryption materials to use in case of Symmetric/Asymmetric + * client usage + */ + @NestedConfigurationProperty + private EncryptionMaterials encryptionMaterials; + /** + * Define if encryption must be used or not + */ + private Boolean useEncryption = false; + + public Long getPartSize() { + return partSize; + } + + public void setPartSize(Long partSize) { + this.partSize = partSize; + } + + public Boolean getMultiPartUpload() { + return multiPartUpload; + } + + public void setMultiPartUpload(Boolean multiPartUpload) { + this.multiPartUpload = multiPartUpload; + } + + public String getAmazonS3Endpoint() { + return amazonS3Endpoint; + } + + public void setAmazonS3Endpoint(String amazonS3Endpoint) { + this.amazonS3Endpoint = amazonS3Endpoint; + } + + 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 AmazonS3 getAmazonS3Client() { + return amazonS3Client; + } + + public void setAmazonS3Client(AmazonS3 amazonS3Client) { + this.amazonS3Client = amazonS3Client; + } + + public String getPrefix() { + return prefix; + } + + public void setPrefix(String prefix) { + this.prefix = prefix; + } + + public String getBucketName() { + return bucketName; + } + + public void setBucketName(String bucketName) { + this.bucketName = bucketName; + } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public String getRegion() { + return region; + } + + public void setRegion(String region) { + this.region = region; + } + + public Boolean getIncludeBody() { + return includeBody; + } + + public void setIncludeBody(Boolean includeBody) { + this.includeBody = includeBody; + } + + public Boolean getDeleteAfterRead() { + return deleteAfterRead; + } + + public void setDeleteAfterRead(Boolean deleteAfterRead) { + this.deleteAfterRead = deleteAfterRead; + } + + public Boolean getDeleteAfterWrite() { + return deleteAfterWrite; + } + + public void setDeleteAfterWrite(Boolean deleteAfterWrite) { + this.deleteAfterWrite = deleteAfterWrite; + } + + public String getPolicy() { + return policy; + } + + public void setPolicy(String policy) { + this.policy = policy; + } + + public String getStorageClass() { + return storageClass; + } + + public void setStorageClass(String storageClass) { + this.storageClass = storageClass; + } + + public String getServerSideEncryption() { + return serverSideEncryption; + } + + public void setServerSideEncryption(String serverSideEncryption) { + this.serverSideEncryption = serverSideEncryption; + } + + public String getProxyHost() { + return proxyHost; + } + + public void setProxyHost(String proxyHost) { + this.proxyHost = proxyHost; + } + + public Integer getProxyPort() { + return proxyPort; + } + + public void setProxyPort(Integer proxyPort) { + this.proxyPort = proxyPort; + } + + public Boolean getPathStyleAccess() { + return pathStyleAccess; + } + + public void setPathStyleAccess(Boolean pathStyleAccess) { + this.pathStyleAccess = pathStyleAccess; + } + + public S3Operations getOperation() { + return operation; + } + + public void setOperation(S3Operations operation) { + this.operation = operation; + } + + public Boolean getAutocloseBody() { + return autocloseBody; + } + + public void setAutocloseBody(Boolean autocloseBody) { + this.autocloseBody = autocloseBody; + } + + public EncryptionMaterials getEncryptionMaterials() { + return encryptionMaterials; + } + + public void setEncryptionMaterials( + EncryptionMaterials encryptionMaterials) { + this.encryptionMaterials = encryptionMaterials; + } + + public Boolean getUseEncryption() { + return useEncryption; + } + + public void setUseEncryption(Boolean useEncryption) { + this.useEncryption = useEncryption; + } + } } \ No newline at end of file -- To stop receiving notification emails like this one, please contact ['"commits@camel.apache.org" <commits@camel.apache.org>'].