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/01/19 03:21:53 UTC

[james-project] branch master updated (64f8e7470f -> 2dc84e79b3)

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

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


    from 64f8e7470f [JAMES-3877] enables configuration of jdbc pool max connections
     new e1377cdc6f JAMES-3867 Allow IMAP extensions configuration
     new f2f93ea269 JAMES-3867 Document IMAP extensions configuration
     new 2dc84e79b3 JAMES-3867 Fix Capability/Enable injection

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 examples/README.md                                 |  4 ++++
 .../apache/james/examples/imap/PingProcessor.java  | 28 +++++++++++++++++++---
 .../custom-imap/src/main/resources/imapserver.xml  | 15 ++----------
 .../examples/imap/ImapCustomPackagesTest.java      | 18 ++++++++++++--
 .../apache/james/imap/api/ImapConfiguration.java   | 23 +++++++++++++++---
 .../distributed-app/docs/modules/ROOT/nav.adoc     |  1 +
 .../docs/modules/ROOT/pages/configure/imap.adoc    | 21 ++++++++++++++++
 .../docs/modules/ROOT/pages/extending/imap.adoc    | 25 +++++++++++++++++++
 .../docs/modules/ROOT/pages/extending/index.adoc   |  2 ++
 .../james/modules/protocols/IMAPServerModule.java  | 19 ++++++++-------
 .../apache/james/imapserver/netty/IMAPServer.java  |  1 +
 .../netty/IMAPServerConfigurationTest.java         |  7 ++++++
 src/site/xdoc/server/config-imap4.xml              | 19 +++++++++++++++
 13 files changed, 154 insertions(+), 29 deletions(-)
 create mode 100644 server/apps/distributed-app/docs/modules/ROOT/pages/extending/imap.adoc


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


[james-project] 02/03: JAMES-3867 Document IMAP extensions configuration

Posted by bt...@apache.org.
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 f2f93ea2695631385e2173845667df8bb9983f97
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Mon Jan 16 15:05:37 2023 +0700

    JAMES-3867 Document IMAP extensions configuration
---
 examples/README.md                                 |  4 ++++
 .../examples/imap/ImapCustomPackagesTest.java      |  1 -
 .../distributed-app/docs/modules/ROOT/nav.adoc     |  1 +
 .../docs/modules/ROOT/pages/configure/imap.adoc    | 21 ++++++++++++++++++
 .../docs/modules/ROOT/pages/extending/imap.adoc    | 25 ++++++++++++++++++++++
 .../docs/modules/ROOT/pages/extending/index.adoc   |  2 ++
 src/site/xdoc/server/config-imap4.xml              | 19 ++++++++++++++++
 7 files changed, 72 insertions(+), 1 deletion(-)

diff --git a/examples/README.md b/examples/README.md
index a75beb75ff..484dcfa76d 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -54,6 +54,10 @@ interact with third party systems, do advance reporting...
 [This example](custom-healthcheck) demonstrates how to write custom healthchecks for Apache James.
 This enables writing new custom healthcheck that fits your monitoring need.
 
+## Configure Custom IMAP extensions
+
+James supports customizing IMAP handling, as demonstrated in [this example](custom-imap).
+
 ## Write Custom James server assembly
 
 [This example](custom-james-assembly) demonstrates how to write a custom assembly in order to write your own tailor-made server.
diff --git a/examples/custom-imap/src/test/java/org/apache/james/examples/imap/ImapCustomPackagesTest.java b/examples/custom-imap/src/test/java/org/apache/james/examples/imap/ImapCustomPackagesTest.java
index b9ff7387c5..922227ee91 100644
--- a/examples/custom-imap/src/test/java/org/apache/james/examples/imap/ImapCustomPackagesTest.java
+++ b/examples/custom-imap/src/test/java/org/apache/james/examples/imap/ImapCustomPackagesTest.java
@@ -49,7 +49,6 @@ class ImapCustomPackagesTest {
             .usersRepository(DEFAULT)
             .build())
         .server(MemoryJamesServerMain::createServer)
-        .lifeCycle(JamesServerExtension.Lifecycle.PER_CLASS)
         .build();
 
     @BeforeEach
diff --git a/server/apps/distributed-app/docs/modules/ROOT/nav.adoc b/server/apps/distributed-app/docs/modules/ROOT/nav.adoc
index dc8eb998e6..14b3a379f2 100644
--- a/server/apps/distributed-app/docs/modules/ROOT/nav.adoc
+++ b/server/apps/distributed-app/docs/modules/ROOT/nav.adoc
@@ -64,6 +64,7 @@
 *** xref:extending/mailbox-listeners.adoc[]
 *** xref:extending/smtp-hooks.adoc[]
 *** xref:extending/webadmin-routes.adoc[]
+*** xref:extending/imap.adoc[]
 ** xref:benchmark/index.adoc[Performance benchmark]
 *** xref:benchmark/db-benchmark.adoc[]
 *** xref:benchmark/james-benchmark.adoc[]
diff --git a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/imap.adoc b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/imap.adoc
index 817db9ce5e..33e28c977b 100644
--- a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/imap.adoc
+++ b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/imap.adoc
@@ -142,6 +142,27 @@ Please configure `auth.oidc` part to use this.
 We do supply an link:https://github.com/apache/james-project/tree/master/examples/oidc[example] of such a setup.
 It uses the Keycloak OIDC provider, but usage of similar technologies is definitely doable.
 
+== Extending IMAP
+
+IMAP decoders, processors and encoder can be customized. xref:extending/imap.adoc[Read more].
+
+Check this link:https://github.com/apache/james-project/tree/master/examples/custom-imap[example].
+
+The following configuration properties are available for extentions:
+
+.imapserver.xml content
+|===
+| Property name | explanation
+
+| imapPackages
+| Configure (union) of IMAP packages. IMAP packages bundles decoders (parsing IMAP commands) processors and encoders,
+thus enable implementing new IMAP commands or replace existing IMAP processors. List of FQDNs, which can be located in
+James extensions.
+
+| customProperties
+| Properties for custom extension. Each tag is a property entry, and holds a string under the form key=value.
+|===
+
 == Mail user agents auto-configuration
 
 Check this example on link:https://github.com/apache/james-project/tree/master/examples/imap-autoconf[Mail user agents auto-configuration].
diff --git a/server/apps/distributed-app/docs/modules/ROOT/pages/extending/imap.adoc b/server/apps/distributed-app/docs/modules/ROOT/pages/extending/imap.adoc
new file mode 100644
index 0000000000..76c9a5fef9
--- /dev/null
+++ b/server/apps/distributed-app/docs/modules/ROOT/pages/extending/imap.adoc
@@ -0,0 +1,25 @@
+= Distributed James Server &mdash; Custom IMAP processing
+:navtitle: Custom IMAP processing
+
+James allows defining your own handler packages.
+
+An Imap package is a simple class that bundles IMAP processing components:
+
+....
+public interface ImapPackage {
+    Collection<ClassName> processors();
+
+    Collection<ClassName> decoders();
+
+    Collection<ClassName> encoders();
+}
+....
+
+Processors needs to be of class `AbstractProcessor`, decoders of class `AbstractImapCommandParser`
+and encoders of class `ImapResponseEncoder`. Extensions-jar mechanism can be used to load custom classes.
+
+Custom configuration can be obtained through `ImapConfiguration` class via the `getCustomProperties` method.
+
+A full working example is available link:https://github.com/apache/james-project/tree/master/examples/custom-imap[here].
+
+See this page for xref:configure/imap.adoc#_extending_imap[more details on configuring IMAP extensions].
\ No newline at end of file
diff --git a/server/apps/distributed-app/docs/modules/ROOT/pages/extending/index.adoc b/server/apps/distributed-app/docs/modules/ROOT/pages/extending/index.adoc
index 6da3748e14..2211e6a1a3 100644
--- a/server/apps/distributed-app/docs/modules/ROOT/pages/extending/index.adoc
+++ b/server/apps/distributed-app/docs/modules/ROOT/pages/extending/index.adoc
@@ -22,6 +22,8 @@ add features to your SMTP server.
 Writing xref:extending/webadmin-routes.adoc[WebAdmin routes] enables to
 add features to the WebAdmin REST API.
 
+Writing xref:extending/imap.adoc[IMAP extensions].
+
 The link:https://github.com/apache/james-project/tree/master/examples[examples] are also a good reference.
 
 == Handling injections for your extensions
diff --git a/src/site/xdoc/server/config-imap4.xml b/src/site/xdoc/server/config-imap4.xml
index a614c882ba..8a1cbfb620 100644
--- a/src/site/xdoc/server/config-imap4.xml
+++ b/src/site/xdoc/server/config-imap4.xml
@@ -132,6 +132,25 @@
             <a href="https://www.keycloak.org/">Keycloack</a> OIDC provider, but usage of similar technologies is definitely doable.</p>
     </subsection>
 
+    <subsection name="Extending IMAP">
+        <p><b>WARNING: </b>IMAP extension applies only for Guice based distributions</p>
+
+        <p>IMAP decoders, processors and encoder can be customized.</p>
+
+        <p>Check this <a href="https://github.com/apache/james-project/tree/master/examples/custom-imap">example</a>.</p>
+
+        <p>The following configuration properties are available for extentions:</p>
+        <dl>
+        <dt><strong>imapPackages</strong></dt>
+        <dd>Configure (union) of IMAP packages. IMAP packages bundles decoders (parsing IMAP commands) processors and encoders,
+            thus enable implementing new IMAP commands or replace existing IMAP processors. List of FQDNs, which can be located in
+            James extensions.</dd>
+        <dt><strong>customProperties</strong></dt>
+        <dd>Properties for custom extension. Each tag is a property entry, and holds a string under the form key=value.</dd>
+        </dl>
+
+    </subsection>
+
     <subsection name="Mail user agents auto-configuration">
         <p>Check this example on <a href="https://github.com/apache/james-project/tree/master/examples/imap-autoconf">Mail user agents auto-configuration</a>.</p>
     </subsection>


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


[james-project] 01/03: JAMES-3867 Allow IMAP extensions configuration

Posted by bt...@apache.org.
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 e1377cdc6fc9c0a419d290bf6b85cfa3e127a2e7
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Mon Jan 16 10:51:07 2023 +0700

    JAMES-3867 Allow IMAP extensions configuration
    
    One can define custom, per-IMAP server
    configuration values.
---
 .../apache/james/examples/imap/PingProcessor.java  | 16 +++++++++++++--
 .../custom-imap/src/main/resources/imapserver.xml  | 15 ++------------
 .../examples/imap/ImapCustomPackagesTest.java      |  9 ++++++++-
 .../apache/james/imap/api/ImapConfiguration.java   | 23 +++++++++++++++++++---
 .../apache/james/imapserver/netty/IMAPServer.java  |  1 +
 .../netty/IMAPServerConfigurationTest.java         |  7 +++++++
 6 files changed, 52 insertions(+), 19 deletions(-)

diff --git a/examples/custom-imap/src/main/java/org/apache/james/examples/imap/PingProcessor.java b/examples/custom-imap/src/main/java/org/apache/james/examples/imap/PingProcessor.java
index a308295870..fe26a5c6a3 100644
--- a/examples/custom-imap/src/main/java/org/apache/james/examples/imap/PingProcessor.java
+++ b/examples/custom-imap/src/main/java/org/apache/james/examples/imap/PingProcessor.java
@@ -19,8 +19,11 @@
 
 package org.apache.james.examples.imap;
 
+import java.util.Properties;
+
 import javax.inject.Inject;
 
+import org.apache.james.imap.api.ImapConfiguration;
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
 import org.apache.james.imap.api.process.ImapSession;
@@ -30,8 +33,8 @@ import org.apache.james.util.MDCBuilder;
 import reactor.core.publisher.Mono;
 
 public class PingProcessor extends AbstractProcessor<PingImapPackages.PingRequest> {
-
     private final StatusResponseFactory factory;
+    private String pongResponse;
 
     @Inject
     public PingProcessor(StatusResponseFactory factory) {
@@ -39,10 +42,19 @@ public class PingProcessor extends AbstractProcessor<PingImapPackages.PingReques
         this.factory = factory;
     }
 
+    @Override
+    public void configure(ImapConfiguration imapConfiguration) {
+        Properties customProperties = imapConfiguration.getCustomProperties();
+
+        pongResponse = (String) customProperties
+            .getOrDefault("pong.response", "completed.");
+    }
+
     @Override
     protected Mono<Void> doProcess(PingImapPackages.PingRequest request, Responder responder, ImapSession session) {
         return Mono.fromRunnable(() -> responder.respond(new PingImapPackages.PingResponse()))
-            .then(Mono.fromRunnable(() -> responder.respond(factory.taggedOk(request.getTag(), request.getCommand(), HumanReadableText.COMPLETED))));
+            .then(Mono.fromRunnable(() -> responder.respond(
+                factory.taggedOk(request.getTag(), request.getCommand(), new HumanReadableText("org.apache.james.imap.COMPLETED", pongResponse)))));
     }
 
     @Override
diff --git a/examples/custom-imap/src/main/resources/imapserver.xml b/examples/custom-imap/src/main/resources/imapserver.xml
index c9eff82382..a6c9d42c66 100644
--- a/examples/custom-imap/src/main/resources/imapserver.xml
+++ b/examples/custom-imap/src/main/resources/imapserver.xml
@@ -33,19 +33,8 @@ under the License.
         <connectionLimitPerIP>0</connectionLimitPerIP>
         <plainAuthDisallowed>false</plainAuthDisallowed>
         <gracefulShutdown>false</gracefulShutdown>
-    </imapserver>
-    <imapserver enabled="true">
-        <jmxName>imapserver-ssl</jmxName>
-        <bind>0.0.0.0:0</bind>
-        <connectionBacklog>200</connectionBacklog>
-        <tls socketTLS="false" startTLS="true">
-            <keystore>classpath://keystore</keystore>
-            <secret>james72laBalle</secret>
-            <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
-        </tls>
-        <connectionLimit>0</connectionLimit>
-        <connectionLimitPerIP>0</connectionLimitPerIP>
-        <gracefulShutdown>false</gracefulShutdown>
+        <customProperties>pong.response=customImapParameter</customProperties>
+        <customProperties>prop.b=anotherValue</customProperties>
     </imapserver>
     <imapPackages>org.apache.james.modules.protocols.DefaultImapPackage</imapPackages>
     <imapPackages>org.apache.james.examples.imap.PingImapPackages</imapPackages>
diff --git a/examples/custom-imap/src/test/java/org/apache/james/examples/imap/ImapCustomPackagesTest.java b/examples/custom-imap/src/test/java/org/apache/james/examples/imap/ImapCustomPackagesTest.java
index cc50e91782..b9ff7387c5 100644
--- a/examples/custom-imap/src/test/java/org/apache/james/examples/imap/ImapCustomPackagesTest.java
+++ b/examples/custom-imap/src/test/java/org/apache/james/examples/imap/ImapCustomPackagesTest.java
@@ -39,7 +39,7 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
-public class ImapCustomPackagesTest {
+class ImapCustomPackagesTest {
 
     @RegisterExtension
     static JamesServerExtension jamesServerExtension = new JamesServerBuilder<MemoryJamesConfiguration>(tmpDir ->
@@ -67,4 +67,11 @@ public class ImapCustomPackagesTest {
             .contains("PONG");
     }
 
+    @Test
+    void imapServerShouldSupportCustomConfigurationValues(GuiceJamesServer server) throws IOException {
+        assertThat(new TestIMAPClient().connect("127.0.0.1", server.getProbe(ImapGuiceProbe.class).getImapPort())
+            .login(BOB, BOB_PASSWORD)
+            .sendCommand("PING"))
+            .contains("customImapParameter");
+    }
 }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/api/ImapConfiguration.java b/protocols/imap/src/main/java/org/apache/james/imap/api/ImapConfiguration.java
index bb92d5b6e3..f42a9117d8 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/api/ImapConfiguration.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/api/ImapConfiguration.java
@@ -21,6 +21,7 @@ package org.apache.james.imap.api;
 
 import java.time.Duration;
 import java.util.Optional;
+import java.util.Properties;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.commons.lang3.StringUtils;
@@ -58,6 +59,7 @@ public class ImapConfiguration {
         private Optional<Boolean> enableIdle;
         private ImmutableSet<String> disabledCaps;
         private Optional<Boolean> isCondstoreEnable;
+        private Optional<Properties> customProperties;
 
         private Builder() {
             this.appendLimit = Optional.empty();
@@ -68,6 +70,7 @@ public class ImapConfiguration {
             this.enableIdle = Optional.empty();
             this.disabledCaps = ImmutableSet.of();
             this.isCondstoreEnable = Optional.empty();
+            this.customProperties = Optional.empty();
         }
 
         public Builder idleTimeInterval(long idleTimeInterval) {
@@ -127,6 +130,11 @@ public class ImapConfiguration {
             return this;
         }
 
+        public Builder withCustomProperties(Properties customProperties) {
+            this.customProperties = Optional.of(customProperties);
+            return this;
+        }
+
         public ImapConfiguration build() {
             ImmutableSet<Capability> normalizeDisableCaps = disabledCaps.stream()
                     .filter(Builder::noBlankString)
@@ -141,7 +149,8 @@ public class ImapConfiguration {
                     maxQueueSize.orElse(DEFAULT_QUEUE_SIZE),
                     idleTimeIntervalUnit.orElse(DEFAULT_HEARTBEAT_INTERVAL_UNIT),
                     normalizeDisableCaps,
-                    isCondstoreEnable.orElse(DEFAULT_CONDSTORE_DISABLE));
+                    isCondstoreEnable.orElse(DEFAULT_CONDSTORE_DISABLE),
+                    customProperties.orElseGet(Properties::new));
         }
     }
 
@@ -153,8 +162,9 @@ public class ImapConfiguration {
     private final ImmutableSet<Capability> disabledCaps;
     private final boolean enableIdle;
     private final boolean isCondstoreEnable;
+    private final Properties customProperties;
 
-    private ImapConfiguration(Optional<Long> appendLimit, boolean enableIdle, long idleTimeInterval, int concurrentRequests, int maxQueueSize, TimeUnit idleTimeIntervalUnit, ImmutableSet<Capability> disabledCaps, boolean isCondstoreEnable) {
+    private ImapConfiguration(Optional<Long> appendLimit, boolean enableIdle, long idleTimeInterval, int concurrentRequests, int maxQueueSize, TimeUnit idleTimeIntervalUnit, ImmutableSet<Capability> disabledCaps, boolean isCondstoreEnable, Properties customProperties) {
         this.appendLimit = appendLimit;
         this.enableIdle = enableIdle;
         this.idleTimeInterval = idleTimeInterval;
@@ -163,6 +173,7 @@ public class ImapConfiguration {
         this.idleTimeIntervalUnit = idleTimeIntervalUnit;
         this.disabledCaps = disabledCaps;
         this.isCondstoreEnable = isCondstoreEnable;
+        this.customProperties = customProperties;
     }
 
     public Optional<Long> getAppendLimit() {
@@ -201,6 +212,10 @@ public class ImapConfiguration {
         return Duration.of(getIdleTimeInterval(), getIdleTimeIntervalUnit().toChronoUnit());
     }
 
+    public Properties getCustomProperties() {
+        return customProperties;
+    }
+
     @Override
     public final boolean equals(Object obj) {
         if (obj instanceof ImapConfiguration) {
@@ -212,6 +227,7 @@ public class ImapConfiguration {
                 && Objects.equal(that.getConcurrentRequests(), concurrentRequests)
                 && Objects.equal(that.getMaxQueueSize(), maxQueueSize)
                 && Objects.equal(that.getDisabledCaps(), disabledCaps)
+                && Objects.equal(that.getCustomProperties(), customProperties)
                 && Objects.equal(that.isCondstoreEnable(), isCondstoreEnable);
         }
         return false;
@@ -220,7 +236,7 @@ public class ImapConfiguration {
     @Override
     public final int hashCode() {
         return Objects.hashCode(enableIdle, idleTimeInterval, idleTimeIntervalUnit, disabledCaps, isCondstoreEnable,
-            concurrentRequests, maxQueueSize, appendLimit);
+            concurrentRequests, maxQueueSize, appendLimit, customProperties);
     }
 
     @Override
@@ -234,6 +250,7 @@ public class ImapConfiguration {
                 .add("isCondstoreEnable", isCondstoreEnable)
                 .add("concurrentRequests", concurrentRequests)
                 .add("maxQueueSize", maxQueueSize)
+                .add("customProperties", customProperties)
                 .toString();
     }
 }
diff --git a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
index 073db65280..0ce7dd543e 100644
--- a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
+++ b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
@@ -202,6 +202,7 @@ public class IMAPServer extends AbstractConfigurableAsyncServer implements ImapC
                 .appendLimit(Optional.of(parseLiteralSizeLimit(configuration)).filter(i -> i > 0))
                 .maxQueueSize(configuration.getInteger("maxQueueSize", ImapConfiguration.DEFAULT_QUEUE_SIZE))
                 .concurrentRequests(configuration.getInteger("concurrentRequests", ImapConfiguration.DEFAULT_CONCURRENT_REQUESTS))
+                .withCustomProperties(configuration.getProperties("customProperties"))
                 .build();
     }
 
diff --git a/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerConfigurationTest.java b/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerConfigurationTest.java
index d8060a3fda..4a73081d1d 100644
--- a/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerConfigurationTest.java
+++ b/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerConfigurationTest.java
@@ -21,6 +21,7 @@ package org.apache.james.imapserver.netty;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
+import java.util.Properties;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.commons.configuration2.BaseHierarchicalConfiguration;
@@ -57,8 +58,13 @@ class IMAPServerConfigurationTest {
         configurationBuilder.addProperty("concurrentRequests", "42");
         configurationBuilder.addProperty("idleTimeIntervalUnit", "MINUTES");
         configurationBuilder.addProperty("disabledCaps", "ACL | MOVE");
+        configurationBuilder.addProperty("customProperties", "abc=def");
+        configurationBuilder.addProperty("customProperties", "ghi=jkl");
         ImapConfiguration imapConfiguration = IMAPServer.getImapConfiguration(configurationBuilder);
 
+        Properties customProperties = new Properties();
+        customProperties.put("abc", "def");
+        customProperties.put("ghi", "jkl");
         ImapConfiguration expectImapConfiguration = ImapConfiguration.builder()
                 .enableIdle(false)
                 .idleTimeInterval(1)
@@ -66,6 +72,7 @@ class IMAPServerConfigurationTest {
                 .disabledCaps(ImmutableSet.of("ACL", "MOVE"))
                 .maxQueueSize(12)
                 .concurrentRequests(42)
+                .withCustomProperties(customProperties)
                 .build();
 
         assertThat(imapConfiguration).isEqualTo(expectImapConfiguration);


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


[james-project] 03/03: JAMES-3867 Fix Capability/Enable injection

Posted by bt...@apache.org.
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 2dc84e79b393dcdfc6e8c610df44c00d815c0b7d
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Wed Jan 18 23:12:08 2023 +0700

    JAMES-3867 Fix Capability/Enable injection
---
 .../org/apache/james/examples/imap/PingProcessor.java | 12 +++++++++++-
 .../james/examples/imap/ImapCustomPackagesTest.java   |  8 ++++++++
 .../james/modules/protocols/IMAPServerModule.java     | 19 +++++++++++--------
 3 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/examples/custom-imap/src/main/java/org/apache/james/examples/imap/PingProcessor.java b/examples/custom-imap/src/main/java/org/apache/james/examples/imap/PingProcessor.java
index fe26a5c6a3..c7ec4687ea 100644
--- a/examples/custom-imap/src/main/java/org/apache/james/examples/imap/PingProcessor.java
+++ b/examples/custom-imap/src/main/java/org/apache/james/examples/imap/PingProcessor.java
@@ -19,20 +19,25 @@
 
 package org.apache.james.examples.imap;
 
+import java.util.List;
 import java.util.Properties;
 
 import javax.inject.Inject;
 
 import org.apache.james.imap.api.ImapConfiguration;
 import org.apache.james.imap.api.display.HumanReadableText;
+import org.apache.james.imap.api.message.Capability;
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
 import org.apache.james.imap.api.process.ImapSession;
+import org.apache.james.imap.processor.CapabilityImplementingProcessor;
 import org.apache.james.imap.processor.base.AbstractProcessor;
 import org.apache.james.util.MDCBuilder;
 
+import com.google.common.collect.ImmutableList;
+
 import reactor.core.publisher.Mono;
 
-public class PingProcessor extends AbstractProcessor<PingImapPackages.PingRequest> {
+public class PingProcessor extends AbstractProcessor<PingImapPackages.PingRequest> implements CapabilityImplementingProcessor {
     private final StatusResponseFactory factory;
     private String pongResponse;
 
@@ -42,6 +47,11 @@ public class PingProcessor extends AbstractProcessor<PingImapPackages.PingReques
         this.factory = factory;
     }
 
+    @Override
+    public List<Capability> getImplementedCapabilities(ImapSession session) {
+        return ImmutableList.of(Capability.of("PING"));
+    }
+
     @Override
     public void configure(ImapConfiguration imapConfiguration) {
         Properties customProperties = imapConfiguration.getCustomProperties();
diff --git a/examples/custom-imap/src/test/java/org/apache/james/examples/imap/ImapCustomPackagesTest.java b/examples/custom-imap/src/test/java/org/apache/james/examples/imap/ImapCustomPackagesTest.java
index 922227ee91..9450570f34 100644
--- a/examples/custom-imap/src/test/java/org/apache/james/examples/imap/ImapCustomPackagesTest.java
+++ b/examples/custom-imap/src/test/java/org/apache/james/examples/imap/ImapCustomPackagesTest.java
@@ -66,6 +66,14 @@ class ImapCustomPackagesTest {
             .contains("PONG");
     }
 
+    @Test
+    void imapServerShouldSupportModularCapability(GuiceJamesServer server) throws IOException {
+        assertThat(new TestIMAPClient().connect("127.0.0.1", server.getProbe(ImapGuiceProbe.class).getImapPort())
+            .login(BOB, BOB_PASSWORD)
+            .sendCommand("CAPABILITY"))
+            .contains("PING");
+    }
+
     @Test
     void imapServerShouldSupportCustomConfigurationValues(GuiceJamesServer server) throws IOException {
         assertThat(new TestIMAPClient().connect("127.0.0.1", server.getProbe(ImapGuiceProbe.class).getImapPort())
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 536aee23ac..bafd667fc8 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
@@ -93,8 +93,13 @@ public class IMAPServerModule extends AbstractModule {
     }
 
     @Provides
-    ImapProcessor provideImapProcessor(ImapPackage imapPackage, GuiceGenericLoader loader, StatusResponseFactory statusResponseFactory) {
-        ImmutableMap<Class, ImapProcessor> processorMap = imapPackage.processors()
+    ImapProcessor provideImapProcessor(ImmutableMap<Class, ImapProcessor> processorMap, StatusResponseFactory statusResponseFactory) {
+        return new DefaultProcessor(processorMap, new UnknownRequestProcessor(statusResponseFactory));
+    }
+
+    @Provides
+    ImmutableMap<Class, ImapProcessor> provideClassImapProcessors(ImapPackage imapPackage, GuiceGenericLoader loader) {
+        return imapPackage.processors()
             .stream()
             .map(Throwing.function(loader::instantiate))
             .map(AbstractProcessor.class::cast)
@@ -102,8 +107,6 @@ public class IMAPServerModule extends AbstractModule {
             .collect(ImmutableMap.toImmutableMap(
                 Pair::getLeft,
                 Pair::getRight));
-
-        return new DefaultProcessor(processorMap, new UnknownRequestProcessor(statusResponseFactory));
     }
 
     @Provides
@@ -158,22 +161,22 @@ public class IMAPServerModule extends AbstractModule {
     }
 
     @ProvidesIntoSet
-    InitializationOperation configureEnable(EnableProcessor enableProcessor, ImapPackage imapPackage) {
+    InitializationOperation configureEnable(EnableProcessor enableProcessor, ImmutableMap<Class, ImapProcessor> processorMap) {
         return InitilizationOperationBuilder
             .forClass(IMAPServerFactory.class)
             .init(() ->
-                imapPackage.processors().stream()
+                processorMap.values().stream()
                     .filter(PermitEnableCapabilityProcessor.class::isInstance)
                     .map(PermitEnableCapabilityProcessor.class::cast)
                     .forEach(enableProcessor::addProcessor));
     }
 
     @ProvidesIntoSet
-    InitializationOperation configureCapability(CapabilityProcessor capabilityProcessor, ImapPackage imapPackage) {
+    InitializationOperation configureCapability(CapabilityProcessor capabilityProcessor, ImmutableMap<Class, ImapProcessor> processorMap) {
         return InitilizationOperationBuilder
             .forClass(IMAPServerFactory.class)
             .init(() ->
-                imapPackage.processors().stream()
+                processorMap.values().stream()
                     .filter(CapabilityImplementingProcessor.class::isInstance)
                     .map(CapabilityImplementingProcessor.class::cast)
                     .forEach(capabilityProcessor::addProcessor));


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