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 2023/02/17 03:11:14 UTC

[james-project] branch master updated: JAMES-3884 One ImapProcessor set per IMAP server (#1442)

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


The following commit(s) were added to refs/heads/master by this push:
     new 94a8567e69 JAMES-3884 One ImapProcessor set per IMAP server (#1442)
94a8567e69 is described below

commit 94a8567e69daca7448e9cd6a4450454aac31834c
Author: Benoit TELLIER <bt...@linagora.com>
AuthorDate: Fri Feb 17 10:11:09 2023 +0700

    JAMES-3884 One ImapProcessor set per IMAP server (#1442)
---
 .../custom-imap/src/main/resources/imapserver.xml  | 16 ++++++
 .../java/org/apache/james/GuiceJamesServer.java    |  2 +-
 .../james/modules/protocols/IMAPServerModule.java  | 65 +++++++++++++---------
 .../james/modules/protocols/ImapGuiceProbe.java    |  6 ++
 .../james/imapserver/netty/IMAPServerFactory.java  | 21 +++++--
 5 files changed, 79 insertions(+), 31 deletions(-)

diff --git a/examples/custom-imap/src/main/resources/imapserver.xml b/examples/custom-imap/src/main/resources/imapserver.xml
index a6c9d42c66..f52a9d1b12 100644
--- a/examples/custom-imap/src/main/resources/imapserver.xml
+++ b/examples/custom-imap/src/main/resources/imapserver.xml
@@ -36,6 +36,22 @@ under the License.
         <customProperties>pong.response=customImapParameter</customProperties>
         <customProperties>prop.b=anotherValue</customProperties>
     </imapserver>
+    <imapserver enabled="true">
+        <jmxName>imapservers</jmxName>
+        <bind>0.0.0.0:0</bind>
+        <connectionBacklog>200</connectionBacklog>
+        <tls socketTLS="true" startTLS="false">
+            <keystore>classpath://keystore</keystore>
+            <secret>james72laBalle</secret>
+            <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
+        </tls>
+        <connectionLimit>0</connectionLimit>
+        <connectionLimitPerIP>0</connectionLimitPerIP>
+        <plainAuthDisallowed>false</plainAuthDisallowed>
+        <gracefulShutdown>false</gracefulShutdown>
+        <customProperties>pong.response=bad</customProperties>
+        <customProperties>prop.b=baad</customProperties>
+    </imapserver>
     <imapPackages>org.apache.james.modules.protocols.DefaultImapPackage</imapPackages>
     <imapPackages>org.apache.james.examples.imap.PingImapPackages</imapPackages>
 </imapservers>
\ No newline at end of file
diff --git a/server/container/guice/common/src/main/java/org/apache/james/GuiceJamesServer.java b/server/container/guice/common/src/main/java/org/apache/james/GuiceJamesServer.java
index 79be7e1a7f..90c7fea64b 100644
--- a/server/container/guice/common/src/main/java/org/apache/james/GuiceJamesServer.java
+++ b/server/container/guice/common/src/main/java/org/apache/james/GuiceJamesServer.java
@@ -85,12 +85,12 @@ public class GuiceJamesServer {
     public void start() throws Exception {
         try {
             Injector injector = Guice.createInjector(module);
+            guiceProbeProvider = injector.getInstance(GuiceProbeProvider.class);
             preDestroy = injector.getInstance(Key.get(new TypeLiteral<Stager<PreDestroy>>() {
             }));
             injector.getInstance(StartUpChecksPerformer.class)
                 .performCheck();
             injector.getInstance(InitializationOperations.class).initModules();
-            guiceProbeProvider = injector.getInstance(GuiceProbeProvider.class);
             isStartedProbe.notifyStarted();
             LOGGER.info("JAMES server started");
         } catch (Throwable e) {
diff --git a/server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/IMAPServerModule.java b/server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/IMAPServerModule.java
index bafd667fc8..16de94303f 100644
--- a/server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/IMAPServerModule.java
+++ b/server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/IMAPServerModule.java
@@ -23,8 +23,11 @@ import java.util.Optional;
 import java.util.function.Function;
 import java.util.stream.Stream;
 
+import javax.inject.Provider;
+
 import org.apache.commons.configuration2.ex.ConfigurationException;
 import org.apache.commons.lang3.tuple.Pair;
+import org.apache.james.filesystem.api.FileSystem;
 import org.apache.james.imap.api.display.Localizer;
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
 import org.apache.james.imap.api.process.DefaultMailboxTyper;
@@ -52,6 +55,8 @@ import org.apache.james.imap.processor.SelectProcessor;
 import org.apache.james.imap.processor.base.AbstractProcessor;
 import org.apache.james.imap.processor.base.UnknownRequestProcessor;
 import org.apache.james.imapserver.netty.IMAPServerFactory;
+import org.apache.james.metrics.api.GaugeRegistry;
+import org.apache.james.metrics.api.MetricFactory;
 import org.apache.james.server.core.configuration.ConfigurationProvider;
 import org.apache.james.utils.ClassName;
 import org.apache.james.utils.GuiceGenericLoader;
@@ -78,10 +83,10 @@ public class IMAPServerModule extends AbstractModule {
 
     @Override
     protected void configure() {
-        bind(IMAPServerFactory.class).in(Scopes.SINGLETON);
         bind(Localizer.class).to(DefaultLocalizer.class);
         bind(UnpooledStatusResponseFactory.class).in(Scopes.SINGLETON);
         bind(StatusResponseFactory.class).to(UnpooledStatusResponseFactory.class);
+        bind(ImapProcessor.class).to(DefaultProcessor.class);
 
         bind(CapabilityProcessor.class).in(Scopes.SINGLETON);
         bind(AuthenticateProcessor.class).in(Scopes.SINGLETON);
@@ -93,13 +98,15 @@ public class IMAPServerModule extends AbstractModule {
     }
 
     @Provides
-    ImapProcessor provideImapProcessor(ImmutableMap<Class, ImapProcessor> processorMap, StatusResponseFactory statusResponseFactory) {
-        return new DefaultProcessor(processorMap, new UnknownRequestProcessor(statusResponseFactory));
+    @Singleton
+    IMAPServerFactory provideServerFactory(FileSystem fileSystem, Provider<ImapDecoder> decoder, Provider<ImapEncoder> encoder, Provider<ImapProcessor> processor,
+                                        MetricFactory metricFactory, GaugeRegistry gaugeRegistry) {
+        return new IMAPServerFactory(fileSystem, decoder, encoder, processor, metricFactory, gaugeRegistry);
     }
 
     @Provides
-    ImmutableMap<Class, ImapProcessor> provideClassImapProcessors(ImapPackage imapPackage, GuiceGenericLoader loader) {
-        return imapPackage.processors()
+    DefaultProcessor provideClassImapProcessors(ImapPackage imapPackage, GuiceGenericLoader loader, StatusResponseFactory statusResponseFactory) {
+        ImmutableMap<Class, ImapProcessor> processors = imapPackage.processors()
             .stream()
             .map(Throwing.function(loader::instantiate))
             .map(AbstractProcessor.class::cast)
@@ -107,6 +114,23 @@ public class IMAPServerModule extends AbstractModule {
             .collect(ImmutableMap.toImmutableMap(
                 Pair::getLeft,
                 Pair::getRight));
+
+        Optional<EnableProcessor> enableProcessor = processors.values()
+            .stream()
+            .filter(EnableProcessor.class::isInstance)
+            .map(EnableProcessor.class::cast)
+            .findFirst();
+
+        Optional<CapabilityProcessor> capabilityProcessor = processors.values()
+            .stream()
+            .filter(CapabilityProcessor.class::isInstance)
+            .map(CapabilityProcessor.class::cast)
+            .findFirst();
+
+        enableProcessor.ifPresent(processor -> configureEnable(processor, processors));
+        capabilityProcessor.ifPresent(processor -> configureCapability(processor, processors));
+
+        return new DefaultProcessor(processors, new UnknownRequestProcessor(statusResponseFactory));
     }
 
     @Provides
@@ -134,13 +158,11 @@ public class IMAPServerModule extends AbstractModule {
     }
 
     @Provides
-    @Singleton
     ImapDecoder provideImapDecoder(ImapCommandParserFactory imapCommandParserFactory, StatusResponseFactory statusResponseFactory) {
         return new DefaultImapDecoder(statusResponseFactory, imapCommandParserFactory);
     }
 
     @Provides
-    @Singleton
     ImapEncoder provideImapEncoder(ImapPackage imapPackage, GuiceGenericLoader loader) {
         Stream<ImapResponseEncoder> encoders = imapPackage.encoders()
             .stream()
@@ -160,26 +182,19 @@ public class IMAPServerModule extends AbstractModule {
             });
     }
 
-    @ProvidesIntoSet
-    InitializationOperation configureEnable(EnableProcessor enableProcessor, ImmutableMap<Class, ImapProcessor> processorMap) {
-        return InitilizationOperationBuilder
-            .forClass(IMAPServerFactory.class)
-            .init(() ->
-                processorMap.values().stream()
-                    .filter(PermitEnableCapabilityProcessor.class::isInstance)
-                    .map(PermitEnableCapabilityProcessor.class::cast)
-                    .forEach(enableProcessor::addProcessor));
+
+    private void configureEnable(EnableProcessor enableProcessor, ImmutableMap<Class, ImapProcessor> processorMap) {
+        processorMap.values().stream()
+            .filter(PermitEnableCapabilityProcessor.class::isInstance)
+            .map(PermitEnableCapabilityProcessor.class::cast)
+            .forEach(enableProcessor::addProcessor);
     }
 
-    @ProvidesIntoSet
-    InitializationOperation configureCapability(CapabilityProcessor capabilityProcessor, ImmutableMap<Class, ImapProcessor> processorMap) {
-        return InitilizationOperationBuilder
-            .forClass(IMAPServerFactory.class)
-            .init(() ->
-                processorMap.values().stream()
-                    .filter(CapabilityImplementingProcessor.class::isInstance)
-                    .map(CapabilityImplementingProcessor.class::cast)
-                    .forEach(capabilityProcessor::addProcessor));
+    private void configureCapability(CapabilityProcessor capabilityProcessor, ImmutableMap<Class, ImapProcessor> processorMap) {
+        processorMap.values().stream()
+            .filter(CapabilityImplementingProcessor.class::isInstance)
+            .map(CapabilityImplementingProcessor.class::cast)
+            .forEach(capabilityProcessor::addProcessor);
     }
 
     @Provides
diff --git a/server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/ImapGuiceProbe.java b/server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/ImapGuiceProbe.java
index 3786b3b999..a9bc25a856 100644
--- a/server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/ImapGuiceProbe.java
+++ b/server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/ImapGuiceProbe.java
@@ -22,6 +22,7 @@ import java.net.InetSocketAddress;
 import java.util.Optional;
 import java.util.function.Predicate;
 
+import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 
 import org.apache.james.imapserver.netty.IMAPServerFactory;
@@ -38,6 +39,11 @@ public class ImapGuiceProbe implements GuiceProbe {
         this.imapServerFactory = imapServerFactory;
     }
 
+    @PreDestroy
+    void destroy() {
+        imapServerFactory.destroy();
+    }
+
     public int getImapPort() {
         return getPort(Predicate.not(AbstractConfigurableAsyncServer::getStartTLSSupported))
             .orElseThrow(() -> new IllegalStateException("IMAP server not defined"));
diff --git a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServerFactory.java b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServerFactory.java
index 8ce292b35e..e51e43c628 100644
--- a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServerFactory.java
+++ b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServerFactory.java
@@ -22,6 +22,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import javax.inject.Inject;
+import javax.inject.Provider;
 
 import org.apache.commons.configuration2.HierarchicalConfiguration;
 import org.apache.commons.configuration2.tree.ImmutableNode;
@@ -37,16 +38,27 @@ import org.apache.james.protocols.lib.netty.AbstractServerFactory;
 public class IMAPServerFactory extends AbstractServerFactory {
 
     protected final FileSystem fileSystem;
-    protected final ImapDecoder decoder;
-    protected final ImapEncoder encoder;
-    protected final ImapProcessor processor;
+    protected final Provider<ImapDecoder> decoder;
+    protected final Provider<ImapEncoder> encoder;
+    protected final Provider<ImapProcessor> processor;
     protected final ImapMetrics imapMetrics;
     protected final GaugeRegistry gaugeRegistry;
 
     @Inject
+    @Deprecated
     public IMAPServerFactory(FileSystem fileSystem, ImapDecoder decoder, ImapEncoder encoder, ImapProcessor processor,
                              MetricFactory metricFactory, GaugeRegistry gaugeRegistry) {
         this.fileSystem = fileSystem;
+        this.decoder = () -> decoder;
+        this.encoder = () -> encoder;
+        this.processor = () -> processor;
+        this.imapMetrics = new ImapMetrics(metricFactory);
+        this.gaugeRegistry = gaugeRegistry;
+    }
+
+    public IMAPServerFactory(FileSystem fileSystem, Provider<ImapDecoder> decoder, Provider<ImapEncoder> encoder, Provider<ImapProcessor> processor,
+                             MetricFactory metricFactory, GaugeRegistry gaugeRegistry) {
+        this.fileSystem = fileSystem;
         this.decoder = decoder;
         this.encoder = encoder;
         this.processor = processor;
@@ -55,11 +67,10 @@ public class IMAPServerFactory extends AbstractServerFactory {
     }
 
     protected IMAPServer createServer() {
-       return new IMAPServer(decoder, encoder, processor, imapMetrics, gaugeRegistry);
+       return new IMAPServer(decoder.get(), encoder.get(), processor.get(), imapMetrics, gaugeRegistry);
     }
     
     @Override
-
     protected List<AbstractConfigurableAsyncServer> createServers(HierarchicalConfiguration<ImmutableNode> config) throws Exception {
         List<AbstractConfigurableAsyncServer> servers = new ArrayList<>();
         List<HierarchicalConfiguration<ImmutableNode>> configs = config.configurationsAt("imapserver");


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