Repository: james-project
Updated Branches:
  refs/heads/master e00ebe12c -> 956ee5a32


JAMES-2582 declare module to bind blobstore impl by properties file 
configuration


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/956ee5a3
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/956ee5a3
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/956ee5a3

Branch: refs/heads/master
Commit: 956ee5a32c9054a5e2b5c097ffec06b52b37a39a
Parents: e6691f5
Author: duc <dt...@linagora.com>
Authored: Sun Nov 4 21:16:19 2018 +0700
Committer: Antoine Duprat <adup...@linagora.com>
Committed: Mon Nov 5 17:35:58 2018 +0100

----------------------------------------------------------------------
 .../objectstorage/FakePropertiesProvider.java   |   2 +-
 .../guice/cassandra-rabbitmq-guice/pom.xml      |  10 ++
 .../BlobStoreChoosingConfiguration.java         |   2 +-
 .../objectstore/BlobStoreChoosingModule.java    | 133 +++++++++++++++++++
 .../BlobStoreChoosingConfigurationTest.java     |  10 +-
 .../BlobStoreChoosingModuleTest.java            | 114 ++++++++++++++++
 6 files changed, 264 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/956ee5a3/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/FakePropertiesProvider.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/FakePropertiesProvider.java
 
b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/FakePropertiesProvider.java
index cff47ee..b4ca08b 100644
--- 
a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/FakePropertiesProvider.java
+++ 
b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/FakePropertiesProvider.java
@@ -55,7 +55,7 @@ public class FakePropertiesProvider extends 
PropertiesProvider {
         return new FakePropertiesProviderBuilder();
     }
 
-    static class FakePropertiesProviderBuilder {
+    public static class FakePropertiesProviderBuilder {
         private final ImmutableMap.Builder<String, Configuration> 
configurations;
 
         public FakePropertiesProviderBuilder() {

http://git-wip-us.apache.org/repos/asf/james-project/blob/956ee5a3/server/container/guice/cassandra-rabbitmq-guice/pom.xml
----------------------------------------------------------------------
diff --git a/server/container/guice/cassandra-rabbitmq-guice/pom.xml 
b/server/container/guice/cassandra-rabbitmq-guice/pom.xml
index 47d1112..79ded79 100644
--- a/server/container/guice/cassandra-rabbitmq-guice/pom.xml
+++ b/server/container/guice/cassandra-rabbitmq-guice/pom.xml
@@ -83,6 +83,16 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>blob-objectstorage-guice</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>blob-objectstorage-guice</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>james-server-cassandra-guice</artifactId>
         </dependency>
         <dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/956ee5a3/server/container/guice/cassandra-rabbitmq-guice/src/main/java/org/apache/james/modules/objectstore/BlobStoreChoosingConfiguration.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/cassandra-rabbitmq-guice/src/main/java/org/apache/james/modules/objectstore/BlobStoreChoosingConfiguration.java
 
b/server/container/guice/cassandra-rabbitmq-guice/src/main/java/org/apache/james/modules/objectstore/BlobStoreChoosingConfiguration.java
index 2d9fc5c..f980530 100644
--- 
a/server/container/guice/cassandra-rabbitmq-guice/src/main/java/org/apache/james/modules/objectstore/BlobStoreChoosingConfiguration.java
+++ 
b/server/container/guice/cassandra-rabbitmq-guice/src/main/java/org/apache/james/modules/objectstore/BlobStoreChoosingConfiguration.java
@@ -37,7 +37,7 @@ public class BlobStoreChoosingConfiguration {
         static String supportedImplNames() {
             return Stream.of(BlobStoreImplName.values())
                 .map(BlobStoreImplName::getName)
-                .collect(Collectors.joining(","));
+                .collect(Collectors.joining(", "));
         }
 
         static BlobStoreImplName from(String name) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/956ee5a3/server/container/guice/cassandra-rabbitmq-guice/src/main/java/org/apache/james/modules/objectstore/BlobStoreChoosingModule.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/cassandra-rabbitmq-guice/src/main/java/org/apache/james/modules/objectstore/BlobStoreChoosingModule.java
 
b/server/container/guice/cassandra-rabbitmq-guice/src/main/java/org/apache/james/modules/objectstore/BlobStoreChoosingModule.java
new file mode 100644
index 0000000..a6467e0
--- /dev/null
+++ 
b/server/container/guice/cassandra-rabbitmq-guice/src/main/java/org/apache/james/modules/objectstore/BlobStoreChoosingModule.java
@@ -0,0 +1,133 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.modules.objectstore;
+
+import java.io.FileNotFoundException;
+import java.util.function.Supplier;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.james.backends.cassandra.components.CassandraModule;
+import 
org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration;
+import org.apache.james.blob.api.BlobStore;
+import org.apache.james.blob.api.HashBlobId;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
+import org.apache.james.blob.cassandra.CassandraBlobsDAO;
+import org.apache.james.blob.objectstorage.PayloadCodec;
+import org.apache.james.modules.objectstorage.ObjectStorageBlobsDAOProvider;
+import org.apache.james.modules.objectstorage.PayloadCodecProvider;
+import org.apache.james.utils.PropertiesProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.datastax.driver.core.Session;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
+import com.google.inject.Scopes;
+import com.google.inject.multibindings.Multibinder;
+
+public class BlobStoreChoosingModule extends AbstractModule {
+
+    interface BlobStoreFactory extends Supplier<BlobStore> {}
+
+    static class CassandraBlobStoreFactory implements BlobStoreFactory {
+        private final Session session;
+        private final CassandraConfiguration configuration;
+        private final HashBlobId.Factory blobIdFactory;
+
+        @Inject
+        CassandraBlobStoreFactory(Session session, CassandraConfiguration 
configuration, HashBlobId.Factory blobIdFactory) {
+            this.session = session;
+            this.configuration = configuration;
+            this.blobIdFactory = blobIdFactory;
+        }
+
+        @Override
+        public BlobStore get() {
+            return new CassandraBlobsDAO(
+                session,
+                configuration,
+                blobIdFactory);
+        }
+    }
+
+    static class SwiftBlobStoreFactory implements BlobStoreFactory {
+        private final ObjectStorageBlobsDAOProvider blobsDAOProvider;
+
+        @Inject
+        SwiftBlobStoreFactory(ObjectStorageBlobsDAOProvider blobsDAOProvider) {
+            this.blobsDAOProvider = blobsDAOProvider;
+        }
+
+        @Override
+        public BlobStore get() {
+            return blobsDAOProvider.get();
+        }
+    }
+
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(BlobStoreChoosingModule.class);
+
+    static final String BLOBSTORE_CONFIGURATION_NAME = "objectstore";
+
+    @Override
+    protected void configure() {
+        bind(SwiftBlobStoreFactory.class).in(Scopes.SINGLETON);
+        
bind(PayloadCodec.class).toProvider(PayloadCodecProvider.class).in(Scopes.SINGLETON);
+
+        bind(CassandraBlobStoreFactory.class).in(Scopes.SINGLETON);
+        Multibinder<CassandraModule> cassandraDataDefinitions = 
Multibinder.newSetBinder(binder(), CassandraModule.class);
+        
cassandraDataDefinitions.addBinding().toInstance(CassandraBlobModule.MODULE);
+    }
+
+    @VisibleForTesting
+    @Provides
+    @Singleton
+    BlobStoreFactory provideBlobStoreFactory(PropertiesProvider 
propertiesProvider,
+                                             CassandraBlobStoreFactory 
cassandraBlobStoreFactory,
+                                             SwiftBlobStoreFactory 
swiftBlobStoreFactory) throws ConfigurationException {
+        try {
+            Configuration configuration = 
propertiesProvider.getConfiguration(BLOBSTORE_CONFIGURATION_NAME);
+            BlobStoreChoosingConfiguration choosingConfiguration = 
BlobStoreChoosingConfiguration.from(configuration);
+            switch (choosingConfiguration.getImplementation()) {
+                case SWIFT:
+                    return swiftBlobStoreFactory;
+                case CASSANDRA:
+                    return cassandraBlobStoreFactory;
+                default:
+                    throw new RuntimeException(String.format("can not get the 
right blobstore provider with configuration %s",
+                        choosingConfiguration.toString()));
+            }
+        } catch (FileNotFoundException e) {
+            LOGGER.warn("Could not find " + BLOBSTORE_CONFIGURATION_NAME + " 
configuration file, using cassandra blobstore as the default");
+            return cassandraBlobStoreFactory;
+        }
+    }
+
+    @Provides
+    @Singleton
+    private BlobStore provideBlobStore(BlobStoreFactory blobStoreFactory) {
+        return blobStoreFactory.get();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/956ee5a3/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/modules/objectstore/BlobStoreChoosingConfigurationTest.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/modules/objectstore/BlobStoreChoosingConfigurationTest.java
 
b/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/modules/objectstore/BlobStoreChoosingConfigurationTest.java
index 34b4b7a..a32fba8 100644
--- 
a/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/modules/objectstore/BlobStoreChoosingConfigurationTest.java
+++ 
b/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/modules/objectstore/BlobStoreChoosingConfigurationTest.java
@@ -36,17 +36,17 @@ class BlobStoreChoosingConfigurationTest {
 
         assertThatThrownBy(() -> 
BlobStoreChoosingConfiguration.from(configuration))
             .isInstanceOf(IllegalStateException.class)
-            .hasMessage("objectstore.implementation property is missing please 
use one of supported values in: cassandra,swift");
+            .hasMessage("objectstore.implementation property is missing please 
use one of supported values in: cassandra, swift");
     }
 
     @Test
-    void fromShouldReturnSwiftWhenBlobStoreImplIsNull() {
+    void fromShouldThrowWhenBlobStoreImplIsNull() {
         PropertiesConfiguration configuration = new PropertiesConfiguration();
         configuration.addProperty("objectstore.implementation", null);
 
         assertThatThrownBy(() -> 
BlobStoreChoosingConfiguration.from(configuration))
             .isInstanceOf(IllegalStateException.class)
-            .hasMessage("objectstore.implementation property is missing please 
use one of supported values in: cassandra,swift");
+            .hasMessage("objectstore.implementation property is missing please 
use one of supported values in: cassandra, swift");
     }
 
     @Test
@@ -56,7 +56,7 @@ class BlobStoreChoosingConfigurationTest {
 
         assertThatThrownBy(() -> 
BlobStoreChoosingConfiguration.from(configuration))
             .isInstanceOf(IllegalStateException.class)
-            .hasMessage("objectstore.implementation property is missing please 
use one of supported values in: cassandra,swift");
+            .hasMessage("objectstore.implementation property is missing please 
use one of supported values in: cassandra, swift");
     }
 
     @Test
@@ -66,7 +66,7 @@ class BlobStoreChoosingConfigurationTest {
 
         assertThatThrownBy(() -> 
BlobStoreChoosingConfiguration.from(configuration))
             .isInstanceOf(IllegalArgumentException.class)
-            .hasMessage("un_supported is not a valid name of BlobStores, 
please use one of supported values in: cassandra,swift");
+            .hasMessage("un_supported is not a valid name of BlobStores, 
please use one of supported values in: cassandra, swift");
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/james-project/blob/956ee5a3/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/modules/objectstore/BlobStoreChoosingModuleTest.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/modules/objectstore/BlobStoreChoosingModuleTest.java
 
b/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/modules/objectstore/BlobStoreChoosingModuleTest.java
new file mode 100644
index 0000000..d6a575d
--- /dev/null
+++ 
b/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/modules/objectstore/BlobStoreChoosingModuleTest.java
@@ -0,0 +1,114 @@
+/****************************************************************
+ * 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.modules.objectstore;
+
+import static 
org.apache.james.modules.objectstore.BlobStoreChoosingModule.BLOBSTORE_CONFIGURATION_NAME;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.Mockito.mock;
+
+import org.apache.commons.configuration.PropertiesConfiguration;
+import org.apache.james.modules.objectstorage.FakePropertiesProvider;
+import 
org.apache.james.modules.objectstore.BlobStoreChoosingConfiguration.BlobStoreImplName;
+import 
org.apache.james.modules.objectstore.BlobStoreChoosingModule.CassandraBlobStoreFactory;
+import 
org.apache.james.modules.objectstore.BlobStoreChoosingModule.SwiftBlobStoreFactory;
+import org.junit.jupiter.api.Test;
+
+class BlobStoreChoosingModuleTest {
+
+    private static CassandraBlobStoreFactory CASSANDRA_BLOBSTORE_FACTORY = 
mock(CassandraBlobStoreFactory.class);
+    private static SwiftBlobStoreFactory SWIFT_BLOBSTORE_FACTORY = 
mock(SwiftBlobStoreFactory.class);
+
+    @Test
+    void provideBlobStoreFactoryShouldThrowWhenMissingPropertyField() throws 
Exception {
+        BlobStoreChoosingModule module = new BlobStoreChoosingModule();
+        PropertiesConfiguration configuration = new PropertiesConfiguration();
+        configuration.addProperty("objectstore.implementation", "");
+        FakePropertiesProvider propertyProvider = 
FakePropertiesProvider.builder()
+            .register(BLOBSTORE_CONFIGURATION_NAME, configuration)
+            .build();
+
+        assertThatThrownBy(() -> 
module.provideBlobStoreFactory(propertyProvider, CASSANDRA_BLOBSTORE_FACTORY, 
SWIFT_BLOBSTORE_FACTORY))
+            .isInstanceOf(IllegalStateException.class);
+    }
+
+    @Test
+    void provideBlobStoreFactoryShouldThrowWhenEmptyPropertyField() throws 
Exception {
+        BlobStoreChoosingModule module = new BlobStoreChoosingModule();
+        PropertiesConfiguration configuration = new PropertiesConfiguration();
+        configuration.addProperty("objectstore.implementation", "");
+        FakePropertiesProvider propertyProvider = 
FakePropertiesProvider.builder()
+            .register(BLOBSTORE_CONFIGURATION_NAME, configuration)
+            .build();
+
+        assertThatThrownBy(() -> 
module.provideBlobStoreFactory(propertyProvider, CASSANDRA_BLOBSTORE_FACTORY, 
SWIFT_BLOBSTORE_FACTORY))
+            .isInstanceOf(IllegalStateException.class);
+    }
+
+    @Test
+    void 
provideBlobStoreFactoryShouldThrowWhenPropertyFieldIsNotInSupportedList() 
throws Exception {
+        BlobStoreChoosingModule module = new BlobStoreChoosingModule();
+        PropertiesConfiguration configuration = new PropertiesConfiguration();
+        configuration.addProperty("objectstore.implementation", "gabouzomeuh");
+        FakePropertiesProvider propertyProvider = 
FakePropertiesProvider.builder()
+            .register(BLOBSTORE_CONFIGURATION_NAME, configuration)
+            .build();
+
+        assertThatThrownBy(() -> 
module.provideBlobStoreFactory(propertyProvider, CASSANDRA_BLOBSTORE_FACTORY, 
SWIFT_BLOBSTORE_FACTORY))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    void provideBlobStoreFactoryShouldReturnCassandraWhenNoFile() throws 
Exception {
+        BlobStoreChoosingModule module = new BlobStoreChoosingModule();
+        FakePropertiesProvider propertyProvider = 
FakePropertiesProvider.builder()
+            .register("other_configuration_file", new 
PropertiesConfiguration())
+            .build();
+
+        assertThat(module.provideBlobStoreFactory(propertyProvider, 
CASSANDRA_BLOBSTORE_FACTORY, SWIFT_BLOBSTORE_FACTORY))
+            .isEqualTo(CASSANDRA_BLOBSTORE_FACTORY);
+    }
+
+    @Test
+    void 
provideBlobStoreFactoryShouldReturnSwiftFactoryWhenConfigurationImplIsSwift() 
throws Exception {
+        BlobStoreChoosingModule module = new BlobStoreChoosingModule();
+        PropertiesConfiguration configuration = new PropertiesConfiguration();
+        configuration.addProperty("objectstore.implementation", 
BlobStoreImplName.SWIFT.getName());
+        FakePropertiesProvider propertyProvider = 
FakePropertiesProvider.builder()
+            .register(BLOBSTORE_CONFIGURATION_NAME, configuration)
+            .build();
+
+        assertThat(module.provideBlobStoreFactory(propertyProvider, 
CASSANDRA_BLOBSTORE_FACTORY, SWIFT_BLOBSTORE_FACTORY))
+            .isEqualTo(SWIFT_BLOBSTORE_FACTORY);
+    }
+
+    @Test
+    void 
provideBlobStoreFactoryShouldReturnCassandraFactoryWhenConfigurationImplIsCassandra()
 throws Exception {
+        BlobStoreChoosingModule module = new BlobStoreChoosingModule();
+        PropertiesConfiguration configuration = new PropertiesConfiguration();
+        configuration.addProperty("objectstore.implementation", 
BlobStoreImplName.CASSANDRA.getName());
+        FakePropertiesProvider propertyProvider = 
FakePropertiesProvider.builder()
+            .register(BLOBSTORE_CONFIGURATION_NAME, configuration)
+            .build();
+
+        assertThat(module.provideBlobStoreFactory(propertyProvider, 
CASSANDRA_BLOBSTORE_FACTORY, SWIFT_BLOBSTORE_FACTORY))
+            .isEqualTo(CASSANDRA_BLOBSTORE_FACTORY);
+    }
+}
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org
For additional commands, e-mail: server-dev-h...@james.apache.org

Reply via email to