You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2022/05/23 02:47:31 UTC

[james-project] 02/10: JAMES-3769 Guice loading for search overrides on top of Guice

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

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

commit 06b731c99c9f4eda7e4af24493165df43a15dd87
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Mon May 9 12:05:04 2022 +0700

    JAMES-3769 Guice loading for search overrides on top of Guice
---
 .../backends/es/v7/ElasticSearchConfiguration.java | 25 +++++++--
 server/container/guice/elasticsearch/pom.xml       |  6 +++
 .../mailbox/ElasticSearchMailboxModule.java        | 17 ++++++
 .../mailbox/ElasticSearchMailboxModuleTest.java    | 60 ++++++++++++++++++++++
 .../james/modules/mailbox/SearchOverrideA.java     | 40 +++++++++++++++
 .../james/modules/mailbox/SearchOverrideB.java     | 40 +++++++++++++++
 .../src/test/resources/recursive/.keep             |  0
 7 files changed, 185 insertions(+), 3 deletions(-)

diff --git a/backends-common/elasticsearch-v7/src/main/java/org/apache/james/backends/es/v7/ElasticSearchConfiguration.java b/backends-common/elasticsearch-v7/src/main/java/org/apache/james/backends/es/v7/ElasticSearchConfiguration.java
index b7dedbac23..0292403554 100644
--- a/backends-common/elasticsearch-v7/src/main/java/org/apache/james/backends/es/v7/ElasticSearchConfiguration.java
+++ b/backends-common/elasticsearch-v7/src/main/java/org/apache/james/backends/es/v7/ElasticSearchConfiguration.java
@@ -309,6 +309,7 @@ public class ElasticSearchConfiguration {
         private Optional<SSLConfiguration> sslTrustConfiguration;
         private Optional<Integer> maxConnectionsPerHost;
         private Optional<Integer> maxConnections;
+        private ImmutableList.Builder<String> searchOverrides;
 
         public Builder() {
             hosts = ImmutableList.builder();
@@ -323,6 +324,7 @@ public class ElasticSearchConfiguration {
             sslTrustConfiguration = Optional.empty();
             maxConnectionsPerHost = Optional.empty();
             maxConnections = Optional.empty();
+            searchOverrides = ImmutableList.builder();
         }
 
         public Builder addHost(Host host) {
@@ -398,6 +400,11 @@ public class ElasticSearchConfiguration {
             return this;
         }
 
+        public Builder withSearchOverrides(List<String> searchOverrides) {
+            this.searchOverrides.addAll(searchOverrides);
+            return this;
+        }
+
         public ElasticSearchConfiguration build() {
             ImmutableList<Host> hosts = this.hosts.build();
             Preconditions.checkState(!hosts.isEmpty(), "You need to specify ElasticSearch host");
@@ -411,7 +418,10 @@ public class ElasticSearchConfiguration {
                 requestTimeout.orElse(DEFAULT_REQUEST_TIMEOUT),
                 hostScheme.orElse(DEFAULT_SCHEME),
                 credential,
-                sslTrustConfiguration.orElse(DEFAULT_SSL_TRUST_CONFIGURATION), maxConnections, maxConnectionsPerHost);
+                sslTrustConfiguration.orElse(DEFAULT_SSL_TRUST_CONFIGURATION),
+                maxConnections,
+                maxConnectionsPerHost,
+                searchOverrides.build());
         }
     }
 
@@ -436,6 +446,7 @@ public class ElasticSearchConfiguration {
     public static final String ELASTICSEARCH_RETRY_CONNECTION_MAX_RETRIES = "elasticsearch.retryConnection.maxRetries";
     public static final String ELASTICSEARCH_MAX_CONNECTIONS = "elasticsearch.max.connections";
     public static final String ELASTICSEARCH_MAX_CONNECTIONS_PER_HOSTS = "elasticsearch.max.connections.per.hosts";
+    public static final String ELASTICSEARCH_SEARCH_OVERRIDES = "elasticsearch.search.overrides";
 
     public static final int DEFAULT_CONNECTION_MAX_RETRIES = 7;
     public static final int DEFAULT_CONNECTION_MIN_DELAY = 3000;
@@ -466,6 +477,7 @@ public class ElasticSearchConfiguration {
             .maxRetries(Optional.ofNullable(configuration.getInteger(ELASTICSEARCH_RETRY_CONNECTION_MAX_RETRIES, null)))
             .maxConnections(Optional.ofNullable(configuration.getInteger(ELASTICSEARCH_MAX_CONNECTIONS, null)))
             .maxConnectionsPerHost(Optional.ofNullable(configuration.getInteger(ELASTICSEARCH_MAX_CONNECTIONS_PER_HOSTS, null)))
+            .withSearchOverrides(Optional.ofNullable(configuration.getStringArray(ELASTICSEARCH_SEARCH_OVERRIDES)).map(ImmutableList::copyOf).orElse(ImmutableList.of()))
             .build();
     }
 
@@ -560,9 +572,10 @@ public class ElasticSearchConfiguration {
     private final SSLConfiguration sslConfiguration;
     private final Optional<Integer> maxConnections;
     private final Optional<Integer> maxConnectionsPerHost;
+    private final List<String> searchOverrides;
 
     private ElasticSearchConfiguration(ImmutableList<Host> hosts, int nbShards, int nbReplica, int waitForActiveShards, int minDelay, int maxRetries, Duration requestTimeout,
-                                       HostScheme hostScheme, Optional<Credential> credential, SSLConfiguration sslConfiguration, Optional<Integer> maxConnections, Optional<Integer> maxConnectionsPerHost) {
+                                       HostScheme hostScheme, Optional<Credential> credential, SSLConfiguration sslConfiguration, Optional<Integer> maxConnections, Optional<Integer> maxConnectionsPerHost, List<String> searchOverrides) {
         this.hosts = hosts;
         this.nbShards = nbShards;
         this.nbReplica = nbReplica;
@@ -575,6 +588,11 @@ public class ElasticSearchConfiguration {
         this.sslConfiguration = sslConfiguration;
         this.maxConnections = maxConnections;
         this.maxConnectionsPerHost = maxConnectionsPerHost;
+        this.searchOverrides = searchOverrides;
+    }
+
+    public List<String> getSearchOverrides() {
+        return searchOverrides;
     }
 
     public ImmutableList<Host> getHosts() {
@@ -641,6 +659,7 @@ public class ElasticSearchConfiguration {
                 && Objects.equals(this.credential, that.credential)
                 && Objects.equals(this.sslConfiguration, that.sslConfiguration)
                 && Objects.equals(this.maxConnections, that.maxConnections)
+                && Objects.equals(this.searchOverrides, that.searchOverrides)
                 && Objects.equals(this.maxConnectionsPerHost, that.maxConnectionsPerHost);
         }
         return false;
@@ -649,6 +668,6 @@ public class ElasticSearchConfiguration {
     @Override
     public final int hashCode() {
         return Objects.hash(hosts, nbShards, nbReplica, waitForActiveShards, minDelay, maxRetries, requestTimeout,
-            hostScheme, credential, sslConfiguration, maxConnections, maxConnectionsPerHost);
+            hostScheme, credential, sslConfiguration, maxConnections, maxConnectionsPerHost, searchOverrides);
     }
 }
diff --git a/server/container/guice/elasticsearch/pom.xml b/server/container/guice/elasticsearch/pom.xml
index c0a51a5af8..839ef508b7 100644
--- a/server/container/guice/elasticsearch/pom.xml
+++ b/server/container/guice/elasticsearch/pom.xml
@@ -55,6 +55,12 @@
             <groupId>${james.groupId}</groupId>
             <artifactId>apache-james-mailbox-tika</artifactId>
         </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>james-server-filesystem-api</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
             <artifactId>james-server-guice-common</artifactId>
diff --git a/server/container/guice/elasticsearch/src/main/java/org/apache/james/modules/mailbox/ElasticSearchMailboxModule.java b/server/container/guice/elasticsearch/src/main/java/org/apache/james/modules/mailbox/ElasticSearchMailboxModule.java
index 86c6edbd44..577e7da266 100644
--- a/server/container/guice/elasticsearch/src/main/java/org/apache/james/modules/mailbox/ElasticSearchMailboxModule.java
+++ b/server/container/guice/elasticsearch/src/main/java/org/apache/james/modules/mailbox/ElasticSearchMailboxModule.java
@@ -23,6 +23,7 @@ import static org.apache.james.mailbox.elasticsearch.v7.search.ElasticSearchSear
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.util.Set;
 
 import javax.inject.Inject;
 import javax.inject.Named;
@@ -48,13 +49,19 @@ import org.apache.james.mailbox.elasticsearch.v7.search.ElasticSearchSearcher;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MessageId;
 import org.apache.james.mailbox.store.search.ListeningMessageSearchIndex;
+import org.apache.james.mailbox.store.search.ListeningMessageSearchIndex.SearchOverride;
 import org.apache.james.mailbox.store.search.MessageSearchIndex;
+import org.apache.james.utils.ClassName;
+import org.apache.james.utils.GuiceGenericLoader;
 import org.apache.james.utils.InitializationOperation;
 import org.apache.james.utils.InitilizationOperationBuilder;
+import org.apache.james.utils.NamingScheme;
 import org.apache.james.utils.PropertiesProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.github.fge.lambdas.Throwing;
+import com.google.common.collect.ImmutableSet;
 import com.google.inject.AbstractModule;
 import com.google.inject.Provides;
 import com.google.inject.Scopes;
@@ -111,6 +118,16 @@ public class ElasticSearchMailboxModule extends AbstractModule {
             .to(ElasticSearchStartUpCheck.class);
     }
 
+    @Provides
+    Set<SearchOverride> provideSearchOverrides(GuiceGenericLoader loader, ElasticSearchConfiguration configuration) {
+        return configuration.getSearchOverrides()
+            .stream()
+            .map(ClassName::new)
+            .map(Throwing.function(loader.<SearchOverride>withNamingSheme(NamingScheme.IDENTITY)::instantiate))
+            .peek(routes -> LOGGER.info("Loading Search override {}", routes.getClass().getCanonicalName()))
+            .collect(ImmutableSet.toImmutableSet());
+    }
+
     @Provides
     @Singleton
     @Named(MailboxElasticSearchConstants.InjectionNames.MAILBOX)
diff --git a/server/container/guice/elasticsearch/src/test/java/org/apache/james/modules/mailbox/ElasticSearchMailboxModuleTest.java b/server/container/guice/elasticsearch/src/test/java/org/apache/james/modules/mailbox/ElasticSearchMailboxModuleTest.java
new file mode 100644
index 0000000000..dde2c517db
--- /dev/null
+++ b/server/container/guice/elasticsearch/src/test/java/org/apache/james/modules/mailbox/ElasticSearchMailboxModuleTest.java
@@ -0,0 +1,60 @@
+/****************************************************************
+ * 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.mailbox;
+
+import static org.apache.james.filesystem.api.FileSystemFixture.RECURSIVE_CLASSPATH_FILE_SYSTEM;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Set;
+
+import org.apache.james.backends.es.v7.ElasticSearchConfiguration;
+import org.apache.james.mailbox.store.search.ListeningMessageSearchIndex;
+import org.apache.james.util.Host;
+import org.apache.james.utils.ExtendedClassLoader;
+import org.apache.james.utils.ExtensionConfiguration;
+import org.apache.james.utils.GuiceGenericLoader;
+import org.junit.jupiter.api.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.inject.Guice;
+
+class ElasticSearchMailboxModuleTest {
+    @Test
+    void test() {
+        GuiceGenericLoader genericLoader = new GuiceGenericLoader(
+            Guice.createInjector(),
+            new ExtendedClassLoader(RECURSIVE_CLASSPATH_FILE_SYSTEM),
+            new ExtensionConfiguration(ImmutableList.of()));
+
+        Set<ListeningMessageSearchIndex.SearchOverride> searchOverrides = new ElasticSearchMailboxModule()
+            .provideSearchOverrides(genericLoader,
+            ElasticSearchConfiguration.builder()
+                .addHost(Host.parseConfString("127.0.0.1", 9200))
+                .withSearchOverrides(ImmutableList.of(
+                    "org.apache.james.modules.mailbox.SearchOverrideA",
+                    "org.apache.james.modules.mailbox.SearchOverrideB"))
+                .build());
+
+        assertThat(searchOverrides)
+            .hasSize(2)
+            .<Class>extracting(ListeningMessageSearchIndex.SearchOverride::getClass)
+            .containsOnly(SearchOverrideA.class, SearchOverrideB.class);
+    }
+}
\ No newline at end of file
diff --git a/server/container/guice/elasticsearch/src/test/java/org/apache/james/modules/mailbox/SearchOverrideA.java b/server/container/guice/elasticsearch/src/test/java/org/apache/james/modules/mailbox/SearchOverrideA.java
new file mode 100644
index 0000000000..51338b24b9
--- /dev/null
+++ b/server/container/guice/elasticsearch/src/test/java/org/apache/james/modules/mailbox/SearchOverrideA.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.james.modules.mailbox;
+
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MessageUid;
+import org.apache.james.mailbox.model.Mailbox;
+import org.apache.james.mailbox.model.SearchQuery;
+import org.apache.james.mailbox.store.search.ListeningMessageSearchIndex;
+
+import reactor.core.publisher.Flux;
+
+public class SearchOverrideA implements ListeningMessageSearchIndex.SearchOverride {
+    @Override
+    public boolean applicable(SearchQuery searchQuery, MailboxSession session) {
+        return false;
+    }
+
+    @Override
+    public Flux<MessageUid> search(MailboxSession session, Mailbox mailbox, SearchQuery searchQuery) {
+        return Flux.empty();
+    }
+}
diff --git a/server/container/guice/elasticsearch/src/test/java/org/apache/james/modules/mailbox/SearchOverrideB.java b/server/container/guice/elasticsearch/src/test/java/org/apache/james/modules/mailbox/SearchOverrideB.java
new file mode 100644
index 0000000000..e6eb6ce0c4
--- /dev/null
+++ b/server/container/guice/elasticsearch/src/test/java/org/apache/james/modules/mailbox/SearchOverrideB.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.james.modules.mailbox;
+
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MessageUid;
+import org.apache.james.mailbox.model.Mailbox;
+import org.apache.james.mailbox.model.SearchQuery;
+import org.apache.james.mailbox.store.search.ListeningMessageSearchIndex;
+
+import reactor.core.publisher.Flux;
+
+public class SearchOverrideB implements ListeningMessageSearchIndex.SearchOverride {
+    @Override
+    public boolean applicable(SearchQuery searchQuery, MailboxSession session) {
+        return false;
+    }
+
+    @Override
+    public Flux<MessageUid> search(MailboxSession session, Mailbox mailbox, SearchQuery searchQuery) {
+        return Flux.empty();
+    }
+}
diff --git a/server/container/guice/elasticsearch/src/test/resources/recursive/.keep b/server/container/guice/elasticsearch/src/test/resources/recursive/.keep
new file mode 100644
index 0000000000..e69de29bb2


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org