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

rouazana pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit fa24a096a5853459c3769a34ccc68feb91626bfa
Author: Antoine Duprat <[email protected]>
AuthorDate: Mon Mar 4 14:35:11 2019 +0100

    JAMES-2671 Introduce AWS S3 blob store implementation
---
 server/blob/blob-objectstorage/pom.xml             |  5 ++
 .../james/blob/objectstorage/AESPayloadCodec.java  | 72 +++++++++++-------
 .../blob/objectstorage/ObjectStorageBlobsDAO.java  |  6 ++
 .../blob/objectstorage/aws/AwsS3ObjectStorage.java | 67 +++++++++++++++++
 .../blob/objectstorage/AESPayloadCodecTest.java    | 10 +--
 .../aws/AwsS3ObjectStorageBlobsDAOBuilderTest.java | 85 ++++++++++++++++++++++
 .../objectstorage/aws/DockerAwsS3Container.java    | 71 ++++++++++++++++++
 .../objectstorage/aws/DockerAwsS3Extension.java    | 53 ++++++++++++++
 .../src/test/resources/logback-test.xml            |  1 +
 .../ObjectStorageDependenciesModule.java           |  9 ++-
 10 files changed, 344 insertions(+), 35 deletions(-)

diff --git a/server/blob/blob-objectstorage/pom.xml 
b/server/blob/blob-objectstorage/pom.xml
index 09db947..2cddbd9 100644
--- a/server/blob/blob-objectstorage/pom.xml
+++ b/server/blob/blob-objectstorage/pom.xml
@@ -81,6 +81,11 @@
             <version>${jclouds.version}</version>
         </dependency>
         <dependency>
+            <groupId>org.apache.jclouds.api</groupId>
+            <artifactId>s3</artifactId>
+            <version>${jclouds.version}</version>
+        </dependency>
+        <dependency>
             <groupId>org.apache.jclouds.driver</groupId>
             <artifactId>jclouds-slf4j</artifactId>
             <version>${jclouds.version}</version>
diff --git 
a/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/AESPayloadCodec.java
 
b/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/AESPayloadCodec.java
index b92f73a..ca0e54d 100644
--- 
a/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/AESPayloadCodec.java
+++ 
b/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/AESPayloadCodec.java
@@ -19,51 +19,67 @@
 
 package org.apache.james.blob.objectstorage;
 
+import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PipedInputStream;
-import java.io.PipedOutputStream;
+import java.math.BigInteger;
 import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
 import java.util.Optional;
-import java.util.concurrent.atomic.AtomicLong;
 
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+
+import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
 import org.apache.james.blob.objectstorage.crypto.CryptoConfig;
-import org.apache.james.blob.objectstorage.crypto.PBKDF2StreamingAeadFactory;
 import org.jclouds.io.Payloads;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.crypto.tink.subtle.AesGcmHkdfStreaming;
+import com.google.common.io.ByteSource;
+import com.google.common.io.FileBackedOutputStream;
+import com.google.crypto.tink.Aead;
+import com.google.crypto.tink.aead.AeadConfig;
+import com.google.crypto.tink.subtle.AesGcmJce;
 
 public class AESPayloadCodec implements PayloadCodec {
+
     private static final Logger LOGGER = 
LoggerFactory.getLogger(AESPayloadCodec.class);
-    private final AesGcmHkdfStreaming streamingAead;
+    private static final byte[] EMPTY_ASSOCIATED_DATA = new byte[0];
+    private static final int PBKDF2_ITERATIONS = 65536;
+    private static final int KEY_SIZE = 256;
+    private static final String SECRET_KEY_FACTORY_ALGORITHM = 
"PBKDF2WithHmacSHA256";
+    private static final BigInteger MAX_BYTES = FileUtils.ONE_MB_BI;
+
+    private final Aead aead;
 
     public AESPayloadCodec(CryptoConfig cryptoConfig) {
-        streamingAead = 
PBKDF2StreamingAeadFactory.newAesGcmHkdfStreaming(cryptoConfig);
+        try {
+            AeadConfig.register();
+
+            SecretKey secretKey = deriveKey(cryptoConfig);
+            aead = new AesGcmJce(secretKey.getEncoded());
+        } catch (GeneralSecurityException e) {
+            throw new RuntimeException("Error while starting AESPayloadCodec", 
e);
+        }
+    }
+
+    private static SecretKey deriveKey(CryptoConfig cryptoConfig) throws 
NoSuchAlgorithmException, InvalidKeySpecException {
+        byte[] saltBytes = cryptoConfig.salt();
+        SecretKeyFactory skf = 
SecretKeyFactory.getInstance(SECRET_KEY_FACTORY_ALGORITHM);
+        PBEKeySpec spec = new PBEKeySpec(cryptoConfig.password(), saltBytes, 
PBKDF2_ITERATIONS, KEY_SIZE);
+        return skf.generateSecret(spec);
     }
 
     @Override
-    public Payload write(InputStream is) {
-        PipedInputStream snk = new PipedInputStream();
-        try {
-            AtomicLong length = new AtomicLong();
-            PipedOutputStream src = new PipedOutputStream(snk);
-            OutputStream outputStream = streamingAead.newEncryptingStream(src, 
PBKDF2StreamingAeadFactory.EMPTY_ASSOCIATED_DATA);
-            Thread copyThread = new Thread(() -> {
-                try (OutputStream stream = outputStream) {
-                    length.addAndGet(IOUtils.copy(is, stream));
-                } catch (IOException e) {
-                    throw new RuntimeException("Stream copy failure ", e);
-                }
-            });
-            copyThread.setUncaughtExceptionHandler((Thread t, Throwable e) ->
-                LOGGER.error("Unable to encrypt payload's input stream",e)
-            );
-            copyThread.start();
-            return new Payload(Payloads.newInputStreamPayload(snk), 
Optional.of(length.get()));
+    public Payload write(InputStream inputStream) {
+        try (FileBackedOutputStream outputStream = new 
FileBackedOutputStream(MAX_BYTES.intValue())) {
+            outputStream.write(aead.encrypt(IOUtils.toByteArray(inputStream), 
EMPTY_ASSOCIATED_DATA));
+            ByteSource data = outputStream.asByteSource();
+            return new Payload(Payloads.newByteSourcePayload(data), 
Optional.of(Long.valueOf(data.size())));
         } catch (IOException | GeneralSecurityException e) {
             throw new RuntimeException("Unable to build payload for object 
storage, failed to " +
                 "encrypt", e);
@@ -73,7 +89,9 @@ public class AESPayloadCodec implements PayloadCodec {
     @Override
     public InputStream read(Payload payload) throws IOException {
         try {
-            return 
streamingAead.newDecryptingStream(payload.getPayload().openStream(), 
PBKDF2StreamingAeadFactory.EMPTY_ASSOCIATED_DATA);
+            byte[] ciphertext = 
IOUtils.toByteArray(payload.getPayload().openStream());
+            byte[] decrypt = aead.decrypt(ciphertext, EMPTY_ASSOCIATED_DATA);
+            return new ByteArrayInputStream(decrypt);
         } catch (GeneralSecurityException e) {
             throw new IOException("Incorrect crypto setup", e);
         }
diff --git 
a/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/ObjectStorageBlobsDAO.java
 
b/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/ObjectStorageBlobsDAO.java
index d870912..857553d 100644
--- 
a/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/ObjectStorageBlobsDAO.java
+++ 
b/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/ObjectStorageBlobsDAO.java
@@ -28,6 +28,8 @@ import org.apache.commons.io.IOUtils;
 import org.apache.james.blob.api.BlobId;
 import org.apache.james.blob.api.BlobStore;
 import org.apache.james.blob.api.ObjectStoreException;
+import org.apache.james.blob.objectstorage.aws.AwsS3AuthConfiguration;
+import org.apache.james.blob.objectstorage.aws.AwsS3ObjectStorage;
 import org.apache.james.blob.objectstorage.swift.SwiftKeystone2ObjectStorage;
 import org.apache.james.blob.objectstorage.swift.SwiftKeystone3ObjectStorage;
 import org.apache.james.blob.objectstorage.swift.SwiftTempAuthObjectStorage;
@@ -73,6 +75,10 @@ public class ObjectStorageBlobsDAO implements BlobStore {
         return SwiftKeystone3ObjectStorage.daoBuilder(testConfig);
     }
 
+    public static ObjectStorageBlobsDAOBuilder.RequireContainerName 
builder(AwsS3AuthConfiguration testConfig) {
+        return AwsS3ObjectStorage.daoBuilder(testConfig);
+    }
+
     public Mono<ContainerName> createContainer(ContainerName name) {
         return Mono.fromCallable(() -> 
blobStore.createContainerInLocation(DEFAULT_LOCATION, name.value()))
             .filter(created -> created == false)
diff --git 
a/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/aws/AwsS3ObjectStorage.java
 
b/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/aws/AwsS3ObjectStorage.java
new file mode 100644
index 0000000..be5eac5
--- /dev/null
+++ 
b/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/aws/AwsS3ObjectStorage.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.james.blob.objectstorage.aws;
+
+import java.util.Properties;
+import java.util.function.Supplier;
+
+import org.apache.james.blob.objectstorage.ObjectStorageBlobsDAOBuilder;
+import org.jclouds.ContextBuilder;
+import org.jclouds.blobstore.BlobStore;
+import org.jclouds.blobstore.BlobStoreContext;
+import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Module;
+
+public class AwsS3ObjectStorage {
+
+    private static final Iterable<Module> JCLOUDS_MODULES =
+        ImmutableSet.of(new SLF4JLoggingModule());
+
+    public static ObjectStorageBlobsDAOBuilder.RequireContainerName 
daoBuilder(AwsS3AuthConfiguration configuration) {
+        return ObjectStorageBlobsDAOBuilder.forBlobStore(new 
BlobStoreBuilder(configuration));
+    }
+
+    private static class BlobStoreBuilder implements Supplier<BlobStore> {
+        private final AwsS3AuthConfiguration configuration;
+
+        private BlobStoreBuilder(AwsS3AuthConfiguration configuration) {
+            this.configuration = configuration;
+        }
+
+        public BlobStore get() {
+            Properties overrides = new Properties();
+            overrides.setProperty("PROPERTY_S3_VIRTUAL_HOST_BUCKETS", "false");
+
+            return contextBuilder()
+                .endpoint(configuration.getEndpoint())
+                .credentials(configuration.getAccessKeyId(), 
configuration.getSecretKey())
+                .overrides(overrides)
+                .modules(JCLOUDS_MODULES)
+                .buildView(BlobStoreContext.class)
+                .getBlobStore();
+        }
+
+        private ContextBuilder contextBuilder() {
+            return ContextBuilder.newBuilder("s3");
+        }
+    }
+}
diff --git 
a/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/AESPayloadCodecTest.java
 
b/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/AESPayloadCodecTest.java
index 3127916..9fbd588 100644
--- 
a/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/AESPayloadCodecTest.java
+++ 
b/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/AESPayloadCodecTest.java
@@ -26,6 +26,8 @@ import java.io.ByteArrayInputStream;
 import java.io.FilterInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
 import java.util.Optional;
 
 import org.apache.commons.io.IOUtils;
@@ -37,7 +39,7 @@ import org.junit.jupiter.api.Test;
 import com.google.crypto.tink.subtle.Hex;
 
 class AESPayloadCodecTest implements PayloadCodecContract {
-    private static final byte[] ENCRYPTED_BYTES = 
Hex.decode("28cdfb53c283185598ec7c49c415c6b56e85d3d74af89740270c2d2cd8006e1265a301436d919ed7acfc14586b5bd193e34c744ef1641230457dae3475");
+    private static final byte[] ENCRYPTED_BYTES = 
Hex.decode("0d5321372dae79366a2cc4ca7f52a9acd9bb6408e50a6bcb7b0008d0b10c90db46");
 
     @Override
     public PayloadCodec codec() {
@@ -83,10 +85,6 @@ class AESPayloadCodecTest implements PayloadCodecContract {
                 }
             }),
             Optional.empty());
-        int i = ENCRYPTED_BYTES.length / 2;
-        byte[] bytes = new byte[i];
-        InputStream is = codec().read(payload);
-        assertThatThrownBy(() -> is.read(bytes, 0, 
i)).isInstanceOf(IOException.class);
-
+        assertThatThrownBy(() -> 
codec().read(payload)).isInstanceOf(IOException.class);
     }
 }
diff --git 
a/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/aws/AwsS3ObjectStorageBlobsDAOBuilderTest.java
 
b/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/aws/AwsS3ObjectStorageBlobsDAOBuilderTest.java
new file mode 100644
index 0000000..afa6447
--- /dev/null
+++ 
b/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/aws/AwsS3ObjectStorageBlobsDAOBuilderTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.james.blob.objectstorage.aws;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.util.UUID;
+
+import org.apache.james.blob.api.HashBlobId;
+import org.apache.james.blob.objectstorage.ContainerName;
+import org.apache.james.blob.objectstorage.ObjectStorageBlobsDAO;
+import org.apache.james.blob.objectstorage.ObjectStorageBlobsDAOBuilder;
+import org.apache.james.blob.objectstorage.ObjectStorageBlobsDAOContract;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(DockerAwsS3Extension.class)
+class AwsS3ObjectStorageBlobsDAOBuilderTest implements 
ObjectStorageBlobsDAOContract {
+
+    private ContainerName containerName;
+    private AwsS3AuthConfiguration configuration;
+
+    @BeforeEach
+    void setUp(DockerAwsS3Container dockerAwsS3Container) {
+        containerName = ContainerName.of(UUID.randomUUID().toString());
+        configuration = AwsS3AuthConfiguration.builder()
+            .endpoint(dockerAwsS3Container.getEndpoint())
+            .accessKeyId(DockerAwsS3Container.SCALITY_ACCESS_KEY_ID)
+            .secretKey(DockerAwsS3Container.SCALITY_SECRET_ACCESS_KEY)
+            .build();
+    }
+
+    @Override
+    public ContainerName containerName() {
+        return containerName;
+    }
+
+    @Test
+    void containerNameIsMandatoryToBuildBlobsDAO() {
+        ObjectStorageBlobsDAOBuilder.ReadyToBuild builder = 
ObjectStorageBlobsDAO
+            .builder(configuration)
+            .container(null)
+            .blobIdFactory(new HashBlobId.Factory());
+
+        
assertThatThrownBy(builder::build).isInstanceOf(IllegalStateException.class);
+    }
+
+    @Test
+    void blobIdFactoryIsMandatoryToBuildBlobsDAO() {
+        ObjectStorageBlobsDAOBuilder.ReadyToBuild builder = 
ObjectStorageBlobsDAO
+            .builder(configuration)
+            .container(containerName)
+            .blobIdFactory(null);
+
+        
assertThatThrownBy(builder::build).isInstanceOf(IllegalStateException.class);
+    }
+
+    @Test
+    void builtBlobsDAOCanStoreAndRetrieve() {
+        ObjectStorageBlobsDAOBuilder.ReadyToBuild builder = 
ObjectStorageBlobsDAO
+            .builder(configuration)
+            .container(containerName)
+            .blobIdFactory(new HashBlobId.Factory());
+
+        assertBlobsDAOCanStoreAndRetrieve(builder);
+    }
+}
\ No newline at end of file
diff --git 
a/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/aws/DockerAwsS3Container.java
 
b/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/aws/DockerAwsS3Container.java
new file mode 100644
index 0000000..bef1009
--- /dev/null
+++ 
b/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/aws/DockerAwsS3Container.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.james.blob.objectstorage.aws;
+
+import org.apache.james.util.Host;
+import org.testcontainers.containers.GenericContainer;
+import org.testcontainers.containers.wait.strategy.Wait;
+
+public class DockerAwsS3Container {
+
+    private static final String AWS_S3_DOCKER_IMAGE = 
"scality/s3server:mem-6018536a";
+    private static final int AWS_S3_PORT = 8000;
+    private static final int ONE_TIME = 1;
+
+    public static final String SCALITY_ACCESS_KEY_ID = "newAccessKey";
+    public static final String SCALITY_SECRET_ACCESS_KEY = "newSecretKey";
+
+    private final GenericContainer<?> awsS3Container;
+
+    public DockerAwsS3Container() {
+        this.awsS3Container = new GenericContainer<>(AWS_S3_DOCKER_IMAGE);
+        this.awsS3Container
+            .withExposedPorts(AWS_S3_PORT)
+            .withEnv("S3BACKEND", "mem")
+            .withEnv("SCALITY_ACCESS_KEY_ID", SCALITY_ACCESS_KEY_ID)
+            .withEnv("SCALITY_SECRET_ACCESS_KEY", SCALITY_SECRET_ACCESS_KEY)
+            .withEnv("LOG_LEVEL", "trace")
+            .waitingFor(Wait.forLogMessage(".*\"message\":\"server 
started\".*\\n", ONE_TIME));
+    }
+
+    public void start() {
+        awsS3Container.start();
+    }
+
+    public void stop() {
+        awsS3Container.stop();
+    }
+
+    public Host getHost() {
+        return Host.from(getIp(), getPort());
+    }
+
+    public String getIp() {
+        return awsS3Container.getContainerIpAddress();
+    }
+
+    public int getPort() {
+        return awsS3Container.getMappedPort(AWS_S3_PORT);
+    }
+
+    public String getEndpoint() {
+        return "http://"; + getIp() + ":" + getPort() + "/";
+    }
+}
diff --git 
a/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/aws/DockerAwsS3Extension.java
 
b/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/aws/DockerAwsS3Extension.java
new file mode 100644
index 0000000..571fbb5
--- /dev/null
+++ 
b/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/aws/DockerAwsS3Extension.java
@@ -0,0 +1,53 @@
+/*
+ * 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.james.blob.objectstorage.aws;
+
+import org.junit.jupiter.api.extension.AfterAllCallback;
+import org.junit.jupiter.api.extension.BeforeAllCallback;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.api.extension.ParameterContext;
+import org.junit.jupiter.api.extension.ParameterResolutionException;
+import org.junit.jupiter.api.extension.ParameterResolver;
+
+public class DockerAwsS3Extension implements ParameterResolver, 
BeforeAllCallback, AfterAllCallback {
+
+    private DockerAwsS3Container awsS3Container;
+
+    @Override
+    public void beforeAll(ExtensionContext context) {
+        awsS3Container = new DockerAwsS3Container();
+        awsS3Container.start();
+    }
+
+    @Override
+    public void afterAll(ExtensionContext context) {
+        awsS3Container.stop();
+    }
+
+    @Override
+    public boolean supportsParameter(ParameterContext parameterContext, 
ExtensionContext extensionContext) throws ParameterResolutionException {
+        return (parameterContext.getParameter().getType() == 
DockerAwsS3Container.class);
+    }
+
+    @Override
+    public Object resolveParameter(ParameterContext parameterContext, 
ExtensionContext extensionContext) throws ParameterResolutionException {
+        return awsS3Container;
+    }
+}
diff --git a/server/blob/blob-objectstorage/src/test/resources/logback-test.xml 
b/server/blob/blob-objectstorage/src/test/resources/logback-test.xml
index b48b76f..8bcda7f 100644
--- a/server/blob/blob-objectstorage/src/test/resources/logback-test.xml
+++ b/server/blob/blob-objectstorage/src/test/resources/logback-test.xml
@@ -35,5 +35,6 @@
     </root>
 
 
+    <logger name="jclouds.headers" level="DEBUG"/>
     <logger name="org.apache.james" level="ERROR"/>
 </configuration>
\ No newline at end of file
diff --git 
a/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/ObjectStorageDependenciesModule.java
 
b/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/ObjectStorageDependenciesModule.java
index a4acb21..56ec3cd 100644
--- 
a/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/ObjectStorageDependenciesModule.java
+++ 
b/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/ObjectStorageDependenciesModule.java
@@ -32,6 +32,8 @@ import org.apache.james.blob.api.BlobId;
 import org.apache.james.blob.api.HashBlobId;
 import org.apache.james.blob.objectstorage.ObjectStorageBlobsDAO;
 import org.apache.james.blob.objectstorage.ObjectStorageBlobsDAOBuilder;
+import org.apache.james.blob.objectstorage.aws.AwsS3AuthConfiguration;
+import org.apache.james.blob.objectstorage.aws.AwsS3ObjectStorage;
 import org.apache.james.modules.mailbox.ConfigurationComponent;
 import org.apache.james.modules.objectstorage.swift.SwiftObjectStorage;
 import org.apache.james.utils.PropertiesProvider;
@@ -71,8 +73,11 @@ public class ObjectStorageDependenciesModule extends 
AbstractModule {
     }
 
     private ObjectStorageBlobsDAOBuilder.RequireContainerName 
selectDaoBuilder(ObjectStorageBlobConfiguration configuration) {
-        if (configuration.getProvider() == ObjectStorageProvider.SWIFT) {
-            return SwiftObjectStorage.builder(configuration);
+        switch (configuration.getProvider()) {
+            case SWIFT:
+                return SwiftObjectStorage.builder(configuration);
+            case AWSS3:
+                return AwsS3ObjectStorage.daoBuilder((AwsS3AuthConfiguration) 
configuration.getSpecificAuthConfiguration());
         }
         throw new IllegalArgumentException("unknown provider " + 
configuration.getProvider());
     }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to