You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by ma...@apache.org on 2018/05/22 08:04:39 UTC

[1/8] james-project git commit: JAMES-2399 Cassandra cucumber tests should add plugins

Repository: james-project
Updated Branches:
  refs/heads/master 92a15670f -> 015d9ae43


JAMES-2399 Cassandra cucumber tests should add plugins


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

Branch: refs/heads/master
Commit: aeb1f14ff11ac3d314df15ba9cfae3bea1c3278c
Parents: 92a1567
Author: benwa <bt...@linagora.com>
Authored: Mon May 21 10:03:07 2018 +0700
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue May 22 10:00:46 2018 +0200

----------------------------------------------------------------------
 .../org/apache/james/jmap/cassandra/CassandraJmapExtension.java    | 2 +-
 .../apache/james/jmap/cassandra/cucumber/CassandraStepdefs.java    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/aeb1f14f/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraJmapExtension.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraJmapExtension.java b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraJmapExtension.java
index c9a8ad2..223460d 100644
--- a/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraJmapExtension.java
+++ b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraJmapExtension.java
@@ -69,7 +69,7 @@ public class CassandraJmapExtension implements BeforeAllCallback, AfterAllCallba
             .build();
         return new JamesWithSpamAssassin(
                 new GuiceJamesServer(configuration)
-                    .combineWith(CassandraJamesServerMain.CASSANDRA_SERVER_MODULE, CassandraJamesServerMain.PROTOCOLS)
+                    .combineWith(CassandraJamesServerMain.CASSANDRA_SERVER_MODULE, CassandraJamesServerMain.PROTOCOLS, CassandraJamesServerMain.PLUGINS)
                     .overrideWith(binder -> binder.bind(TextExtractor.class).to(PDFTextExtractor.class))
                     .overrideWith(new TestJMAPServerModule(LIMIT_TO_20_MESSAGES))
                     .overrideWith(new TestESMetricReporterModule())

http://git-wip-us.apache.org/repos/asf/james-project/blob/aeb1f14f/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/cucumber/CassandraStepdefs.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/cucumber/CassandraStepdefs.java b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/cucumber/CassandraStepdefs.java
index d37ab17..f80ebe9 100644
--- a/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/cucumber/CassandraStepdefs.java
+++ b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/cucumber/CassandraStepdefs.java
@@ -69,7 +69,7 @@ public class CassandraStepdefs {
             .build();
 
         mainStepdefs.jmapServer = new GuiceJamesServer(configuration)
-                .combineWith(CassandraJamesServerMain.CASSANDRA_SERVER_MODULE, CassandraJamesServerMain.PROTOCOLS)
+                .combineWith(CassandraJamesServerMain.CASSANDRA_SERVER_MODULE, CassandraJamesServerMain.PROTOCOLS, CassandraJamesServerMain.PLUGINS)
                 .overrideWith(new CassandraJmapServerModule(embeddedElasticSearch, cassandraServer.getIp(), cassandraServer.getBindingPort()))
                 .overrideWith((binder) -> binder.bind(PersistenceAdapter.class).to(MemoryPersistenceAdapter.class));
         mainStepdefs.awaitMethod = () -> embeddedElasticSearch.awaitForElasticSearch();


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


[8/8] james-project git commit: Merge branch 'pr-1428'

Posted by ma...@apache.org.
Merge branch 'pr-1428'


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

Branch: refs/heads/master
Commit: 015d9ae43517940df3a3df21fe82cf4eba99fb8d
Parents: 956c098 e9cc502
Author: Matthieu Baechler <ma...@apache.org>
Authored: Tue May 22 10:04:23 2018 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue May 22 10:04:23 2018 +0200

----------------------------------------------------------------------
 .../mail/CassandraMessageIdMapper.java          |  5 ++-
 ...estCassandraMailboxSessionMapperFactory.java | 27 ++++++++-----
 .../mail/CassandraMessageIdMapperTest.java      | 40 +++++++++++++++++++-
 .../store/mail/model/MessageIdMapperTest.java   | 16 ++++----
 4 files changed, 69 insertions(+), 19 deletions(-)
----------------------------------------------------------------------



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


[4/8] james-project git commit: JAMES-2399 include listener name in aggregate id to prevent sharing events between two QuotaMailingListeners

Posted by ma...@apache.org.
JAMES-2399 include listener name in aggregate id to prevent sharing events between two QuotaMailingListeners


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

Branch: refs/heads/master
Commit: 8e5f2cc25c5e900f85fc8a1f7bada57a3a71ec44
Parents: 8040919
Author: Matthieu Baechler <ma...@apache.org>
Authored: Thu May 17 16:30:26 2018 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue May 22 10:02:27 2018 +0200

----------------------------------------------------------------------
 .../dto/QuotaThresholdChangedEventDTO.java      | 15 +++---
 .../mailbox/quota/cassandra/dto/DTOTest.java    |  9 ++--
 .../src/test/resources/json/event.json          |  2 +-
 .../src/test/resources/json/event2.json         |  2 +-
 .../src/test/resources/json/event3.json         |  2 +-
 .../src/test/resources/json/event4.json         |  2 +-
 mailbox/plugin/quota-mailing/pom.xml            |  4 ++
 .../QuotaMailingListenerConfiguration.java      | 54 ++++++++++++++++++--
 .../mailing/aggregates/UserQuotaThresholds.java | 43 +++++++++++++---
 .../DetectThresholdCrossingHandler.java         |  4 +-
 .../QuotaMailingListenerConfigurationTest.java  |  9 ++++
 .../aggregates/UserQuotaThresholdsTest.java     | 43 +++++++++++++++-
 .../org/apache/james/CassandraJmapTestRule.java |  5 +-
 .../org/apache/james/MemoryJmapTestRule.java    |  8 +--
 .../CassandraGetMessageListMethodTest.java      |  4 +-
 .../src/test/resources/listeners.xml            | 10 ++++
 .../integration/GetMessageListMethodTest.java   |  1 +
 .../methods/integration/QuotaMailingTest.java   | 19 +++++--
 .../memory/MemoryGetMessageListMethodTest.java  |  3 +-
 .../src/test/resources/listeners.xml            | 10 ++++
 20 files changed, 209 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaThresholdChangedEventDTO.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaThresholdChangedEventDTO.java b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaThresholdChangedEventDTO.java
index f229e2c..6d1ab84 100644
--- a/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaThresholdChangedEventDTO.java
+++ b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaThresholdChangedEventDTO.java
@@ -19,7 +19,6 @@
 
 package org.apache.james.mailbox.quota.cassandra.dto;
 
-import org.apache.james.core.User;
 import org.apache.james.eventsourcing.EventId;
 import org.apache.james.eventsourcing.eventstore.cassandra.dto.EventDTO;
 import org.apache.james.mailbox.quota.mailing.aggregates.UserQuotaThresholds;
@@ -35,7 +34,7 @@ class QuotaThresholdChangedEventDTO implements EventDTO {
     public static QuotaThresholdChangedEventDTO from(QuotaThresholdChangedEvent event, String type) {
         return new QuotaThresholdChangedEventDTO(
             type, event.eventId().serialize(),
-            event.getAggregateId().getUser().asString(),
+            event.getAggregateId().asAggregateKey(),
             QuotaDTO.from(event.getSizeQuota()),
             QuotaDTO.from(event.getCountQuota()),
             HistoryEvolutionDTO.toDto(event.getSizeHistoryEvolution()),
@@ -44,7 +43,7 @@ class QuotaThresholdChangedEventDTO implements EventDTO {
 
     private final String type;
     private final int eventId;
-    private final String user;
+    private final String aggregateId;
     private final QuotaDTO sizeQuota;
     private final QuotaDTO countQuota;
     private final HistoryEvolutionDTO sizeEvolution;
@@ -54,14 +53,14 @@ class QuotaThresholdChangedEventDTO implements EventDTO {
     private QuotaThresholdChangedEventDTO(
             @JsonProperty("type") String type,
             @JsonProperty("eventId") int eventId,
-            @JsonProperty("user") String user,
+            @JsonProperty("aggregateId") String aggregateId,
             @JsonProperty("sizeQuota") QuotaDTO sizeQuota,
             @JsonProperty("countQuota") QuotaDTO countQuota,
             @JsonProperty("sizeEvolution") HistoryEvolutionDTO sizeEvolution,
             @JsonProperty("countEvolution") HistoryEvolutionDTO countEvolution) {
         this.type = type;
         this.eventId = eventId;
-        this.user = user;
+        this.aggregateId = aggregateId;
         this.sizeQuota = sizeQuota;
         this.countQuota = countQuota;
         this.sizeEvolution = sizeEvolution;
@@ -76,8 +75,8 @@ class QuotaThresholdChangedEventDTO implements EventDTO {
         return eventId;
     }
 
-    public String getUser() {
-        return user;
+    public String getAggregateId() {
+        return aggregateId;
     }
 
     public QuotaDTO getSizeQuota() {
@@ -105,6 +104,6 @@ class QuotaThresholdChangedEventDTO implements EventDTO {
             countEvolution.toHistoryEvolution(),
             sizeQuota.asSizeQuota(),
             countQuota.asCountQuota(),
-            UserQuotaThresholds.Id.from(User.fromUsername(user)));
+            UserQuotaThresholds.Id.fromKey(aggregateId));
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/mailbox/quota/cassandra/dto/DTOTest.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/mailbox/quota/cassandra/dto/DTOTest.java b/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/mailbox/quota/cassandra/dto/DTOTest.java
index ca063d9..5ed61ab 100644
--- a/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/mailbox/quota/cassandra/dto/DTOTest.java
+++ b/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/mailbox/quota/cassandra/dto/DTOTest.java
@@ -49,20 +49,21 @@ class DTOTest {
     static final Quota<QuotaSize> SIZE_QUOTA = Quota.<QuotaSize>builder().used(QuotaSize.size(23)).computedLimit(QuotaSize.size(33)).build();
     static final Quota<QuotaCount> COUNT_QUOTA = Quota.<QuotaCount>builder().used(QuotaCount.count(12)).computedLimit(QuotaCount.count(45)).build();
     static final Instant INSTANT = Instant.ofEpochMilli(45554);
+    public static final String DEFAULT_LISTENER_NAME = "default";
     static final QuotaThresholdChangedEvent EVENT = new QuotaThresholdChangedEvent(
         EventId.first(),
         HistoryEvolution.noChanges(),
         HistoryEvolution.noChanges(),
         SIZE_QUOTA,
         COUNT_QUOTA,
-        UserQuotaThresholds.Id.from(User.fromUsername("foo@bar.com")));
+        UserQuotaThresholds.Id.from(User.fromUsername("foo@bar.com"), DEFAULT_LISTENER_NAME));
     static final QuotaThresholdChangedEvent EVENT_2 = new QuotaThresholdChangedEvent(
         EventId.first(),
         HistoryEvolution.lowerThresholdReached(new QuotaThresholdChange(_75, INSTANT)),
         HistoryEvolution.noChanges(),
         SIZE_QUOTA,
         Quota.<QuotaCount>builder().used(QuotaCount.count(12)).computedLimit(QuotaCount.unlimited()).build(),
-        UserQuotaThresholds.Id.from(User.fromUsername("foo@bar.com")));
+        UserQuotaThresholds.Id.from(User.fromUsername("foo@bar.com"), DEFAULT_LISTENER_NAME));
     static final QuotaThresholdChangedEvent EVENT_3 = new QuotaThresholdChangedEvent(
         EventId.first(),
         HistoryEvolution.lowerThresholdReached(new QuotaThresholdChange(_75, INSTANT)),
@@ -70,7 +71,7 @@ class DTOTest {
             HistoryEvolution.HighestThresholdRecentness.NotAlreadyReachedDuringGracePeriod),
         SIZE_QUOTA,
         Quota.<QuotaCount>builder().used(QuotaCount.count(12)).computedLimit(QuotaCount.unlimited()).build(),
-        UserQuotaThresholds.Id.from(User.fromUsername("foo@bar.com")));
+        UserQuotaThresholds.Id.from(User.fromUsername("foo@bar.com"), DEFAULT_LISTENER_NAME));
     static final QuotaThresholdChangedEvent EVENT_4 = new QuotaThresholdChangedEvent(
         EventId.first(),
         HistoryEvolution.lowerThresholdReached(new QuotaThresholdChange(_75, INSTANT)),
@@ -78,7 +79,7 @@ class DTOTest {
             HistoryEvolution.HighestThresholdRecentness.AlreadyReachedDuringGracePeriod),
         SIZE_QUOTA,
         Quota.<QuotaCount>builder().used(QuotaCount.count(12)).computedLimit(QuotaCount.unlimited()).build(),
-        UserQuotaThresholds.Id.from(User.fromUsername("foo@bar.com")));
+        UserQuotaThresholds.Id.from(User.fromUsername("foo@bar.com"), DEFAULT_LISTENER_NAME));
 
     static final String EVENT_JSON = ClassLoaderUtils.getSystemResourceAsString("json/event.json");
     static final String EVENT_JSON_2 = ClassLoaderUtils.getSystemResourceAsString("json/event2.json");

http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event.json
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event.json b/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event.json
index 4449047..93a78ce 100644
--- a/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event.json
+++ b/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event.json
@@ -1,7 +1,7 @@
 {
  "type": "quota-threshold-change",
  "eventId": 0,
- "user": "foo@bar.com",
+ "aggregateId":"QuotaThreasholdEvents/default/foo@bar.com",
  "sizeQuota": {
    "used": 23,
    "limit": 33

http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event2.json
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event2.json b/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event2.json
index b20cfab..6a8703d 100644
--- a/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event2.json
+++ b/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event2.json
@@ -1,7 +1,7 @@
 {
   "type":"quota-threshold-change",
   "eventId":0,
-  "user":"foo@bar.com",
+  "aggregateId":"QuotaThreasholdEvents/default/foo@bar.com",
   "sizeQuota":{
     "used":23,
     "limit":33

http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event3.json
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event3.json b/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event3.json
index 4bda126..552ce29 100644
--- a/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event3.json
+++ b/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event3.json
@@ -1,7 +1,7 @@
 {
   "type":"quota-threshold-change",
   "eventId":0,
-  "user":"foo@bar.com",
+  "aggregateId":"QuotaThreasholdEvents/default/foo@bar.com",
   "sizeQuota":{
     "used":23,
     "limit":33

http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event4.json
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event4.json b/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event4.json
index 0852dc5..ff62e9c 100644
--- a/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event4.json
+++ b/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event4.json
@@ -1,7 +1,7 @@
 {
   "type":"quota-threshold-change",
   "eventId":0,
-  "user":"foo@bar.com",
+  "aggregateId":"QuotaThreasholdEvents/default/foo@bar.com",
   "sizeQuota":{
     "used":23,
     "limit":33

http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/mailbox/plugin/quota-mailing/pom.xml
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing/pom.xml b/mailbox/plugin/quota-mailing/pom.xml
index 3cda088..65b8f62 100644
--- a/mailbox/plugin/quota-mailing/pom.xml
+++ b/mailbox/plugin/quota-mailing/pom.xml
@@ -94,6 +94,10 @@
             <artifactId>james-server-util</artifactId>
         </dependency>
         <dependency>
+            <groupId>commons-configuration</groupId>
+            <artifactId>commons-configuration</artifactId>
+        </dependency>
+        <dependency>
             <groupId>com.github.spullara.mustache.java</groupId>
             <artifactId>compiler</artifactId>
         </dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfiguration.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfiguration.java b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfiguration.java
index 8f680b4..6f2e7a6 100644
--- a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfiguration.java
+++ b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfiguration.java
@@ -44,6 +44,7 @@ public class QuotaMailingListenerConfiguration {
         String GRACE_PERIOD = "gracePeriod";
         String THRESHOLDS = "thresholds.threshold";
         String ROOT_KEY = "";
+        String NAME = "name";
     }
 
     public static QuotaMailingListenerConfiguration from(HierarchicalConfiguration config) {
@@ -52,9 +53,14 @@ public class QuotaMailingListenerConfiguration {
             .subjectTemplate(readSubjectTemplate(config))
             .bodyTemplate(readBodyTemplate(config))
             .gracePeriod(readGracePeriod(config))
+            .name(readName(config))
             .build();
     }
 
+    private static Optional<String> readName(HierarchicalConfiguration config) {
+        return Optional.ofNullable(config.getString(XmlKeys.NAME, null));
+    }
+
     private static Optional<String> readSubjectTemplate(HierarchicalConfiguration config) {
         return Optional.ofNullable(config.getString(XmlKeys.SUBJECT_TEMPLATE, null));
     }
@@ -82,12 +88,14 @@ public class QuotaMailingListenerConfiguration {
         private Optional<Duration> gradePeriod;
         private Optional<String> bodyTemplate;
         private Optional<String> subjectTemplate;
+        private Optional<String> name;
 
         private Builder() {
             thresholds = ImmutableList.builder();
             gradePeriod = Optional.empty();
             bodyTemplate = Optional.empty();
             subjectTemplate = Optional.empty();
+            name = Optional.empty();
         }
 
         public Builder addThreshold(QuotaThreshold quotaThreshold) {
@@ -122,33 +130,67 @@ public class QuotaMailingListenerConfiguration {
             return this;
         }
 
+        public Builder gracePeriod(Optional<Duration> duration) {
+            duration.ifPresent(this::gracePeriod);
+            return this;
+        }
+
+        public Builder bodyTemplate(Optional<String> bodyTemplate) {
+            bodyTemplate.ifPresent(this::bodyTemplate);
+            return this;
+        }
+
+        public Builder subjectTemplate(Optional<String> subjectTemplate) {
+            subjectTemplate.ifPresent(this::subjectTemplate);
+            return this;
+        }
+
+        public Builder name(String name) {
+            Preconditions.checkArgument(!Strings.isNullOrEmpty(name), "Pass a non null/empty name");
+            this.name = Optional.of(name);
+            return this;
+        }
+
+        public Builder name(Optional<String> name) {
+            name.ifPresent(this::name);
+            return this;
+        }
+
         public QuotaMailingListenerConfiguration build() {
             return new QuotaMailingListenerConfiguration(
                 new QuotaThresholds(thresholds.build()),
                 gradePeriod.orElse(DEFAULT_GRACE_PERIOD),
                 bodyTemplate.orElse(DEFAULT_BODY_TEMPLATE),
-                subjectTemplate.orElse(DEFAULT_SUBJECT_TEMPLATE));
+                subjectTemplate.orElse(DEFAULT_SUBJECT_TEMPLATE),
+                name.orElse(DEFAULT_NAME));
         }
     }
 
     public static final String DEFAULT_BODY_TEMPLATE = FileSystem.CLASSPATH_PROTOCOL + "//templates/QuotaThresholdMailBody.mustache";
     public static final String DEFAULT_SUBJECT_TEMPLATE = FileSystem.CLASSPATH_PROTOCOL + "//templates/QuotaThresholdMailSubject.mustache";
     public static final Duration DEFAULT_GRACE_PERIOD = Duration.ofDays(1);
+    private static final String DEFAULT_NAME = "default";
 
     public static Builder builder() {
         return new Builder();
     }
 
+    public static QuotaMailingListenerConfiguration defaultConfiguration() {
+        return builder().build();
+    }
+
     private final QuotaThresholds thresholds;
     private final Duration gracePeriod;
     private final String bodyTemplate;
     private final String subjectTemplate;
+    private final String name;
 
-    private QuotaMailingListenerConfiguration(QuotaThresholds thresholds, Duration gracePeriod, String bodyTemplate, String subjectTemplate) {
+    private QuotaMailingListenerConfiguration(QuotaThresholds thresholds, Duration gracePeriod, String bodyTemplate, String subjectTemplate, String name) {
         this.thresholds = thresholds;
         this.gracePeriod = gracePeriod;
         this.bodyTemplate = bodyTemplate;
         this.subjectTemplate = subjectTemplate;
+        this.name = name;
     }
 
     public QuotaThresholds getThresholds() {
@@ -167,6 +209,10 @@ public class QuotaMailingListenerConfiguration {
         return subjectTemplate;
     }
 
+    public String getName() {
+        return name;
+    }
+
     @Override
     public final boolean equals(Object o) {
         if (o instanceof QuotaMailingListenerConfiguration) {
@@ -175,6 +221,7 @@ public class QuotaMailingListenerConfiguration {
             return Objects.equals(this.thresholds, that.thresholds)
                 && Objects.equals(this.gracePeriod, that.gracePeriod)
                 && Objects.equals(this.bodyTemplate, that.bodyTemplate)
+                && Objects.equals(this.name, that.name)
                 && Objects.equals(this.subjectTemplate, that.subjectTemplate);
         }
         return false;
@@ -182,7 +229,7 @@ public class QuotaMailingListenerConfiguration {
 
     @Override
     public final int hashCode() {
-        return Objects.hash(thresholds, gracePeriod, bodyTemplate, subjectTemplate);
+        return Objects.hash(thresholds, gracePeriod, bodyTemplate, subjectTemplate, name);
     }
 
     @Override
@@ -192,6 +239,7 @@ public class QuotaMailingListenerConfiguration {
             .add("gracePeriod", gracePeriod)
             .add("bodyTemplate", bodyTemplate)
             .add("subjectTemplate", subjectTemplate)
+            .add("name", name)
             .toString();
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/aggregates/UserQuotaThresholds.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/aggregates/UserQuotaThresholds.java b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/aggregates/UserQuotaThresholds.java
index ae67d30..5ae7835 100644
--- a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/aggregates/UserQuotaThresholds.java
+++ b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/aggregates/UserQuotaThresholds.java
@@ -41,20 +41,42 @@ import org.apache.james.mailbox.quota.model.QuotaThresholds;
 import org.apache.james.util.OptionalUtils;
 
 import com.github.steveash.guavate.Guavate;
+import com.google.common.base.Joiner;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
 import com.google.common.collect.ImmutableList;
 
 public class UserQuotaThresholds {
 
     public static class Id implements AggregateId {
 
-        public static Id from(User user) {
-            return new Id(user);
+        private static final int PREFIX_INDEX = 0;
+        private static final int NAME_INDEX = 1;
+        private static final int USER_INDEX = 2;
+        private static final String SEPARATOR = "/";
+        private static final String PREFIX = "QuotaThreasholdEvents";
+
+        public static Id fromKey(String key) {
+            List<String> keyParts = Splitter.on(SEPARATOR).splitToList(key);
+            if (keyParts.size() != 3 || !keyParts.get(PREFIX_INDEX).equals(PREFIX)) {
+                throw new IllegalArgumentException();
+            }
+            return new Id(User.fromUsername(keyParts.get(USER_INDEX)), keyParts.get(NAME_INDEX));
+        }
+
+        public static Id from(User user, String name) {
+            return new Id(user, name);
         }
 
         private final User user;
+        private final String name;
 
-        private Id(User user) {
+        private Id(User user, String name) {
+            Preconditions.checkArgument(!user.asString().contains(SEPARATOR));
+            Preconditions.checkArgument(!name.contains(SEPARATOR));
             this.user = user;
+            this.name = name;
         }
 
         public User getUser() {
@@ -63,7 +85,7 @@ public class UserQuotaThresholds {
 
         @Override
         public String asAggregateKey() {
-            return "QuotaThreasholdEvents-" + user.asString();
+            return Joiner.on(SEPARATOR).join(PREFIX, name, user.asString());
         }
 
         @Override
@@ -71,14 +93,23 @@ public class UserQuotaThresholds {
             if (o instanceof Id) {
                 Id id = (Id) o;
 
-                return Objects.equals(this.user, id.user);
+                return Objects.equals(this.user, id.user)
+                    && Objects.equals(this.name, id.name);
             }
             return false;
         }
 
         @Override
         public final int hashCode() {
-            return Objects.hash(user);
+            return Objects.hash(user, name);
+        }
+
+        @Override
+        public String toString() {
+            return MoreObjects.toStringHelper(this)
+                .add("user", user)
+                .add("name", name)
+                .toString();
         }
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/commands/DetectThresholdCrossingHandler.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/commands/DetectThresholdCrossingHandler.java b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/commands/DetectThresholdCrossingHandler.java
index b44ab3e..54a9db3 100644
--- a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/commands/DetectThresholdCrossingHandler.java
+++ b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/commands/DetectThresholdCrossingHandler.java
@@ -32,10 +32,12 @@ public class DetectThresholdCrossingHandler implements CommandHandler<DetectThre
 
     private final EventStore eventStore;
     private final QuotaMailingListenerConfiguration quotaMailingListenerConfiguration;
+    private final String listenerName;
 
     public DetectThresholdCrossingHandler(EventStore eventStore, QuotaMailingListenerConfiguration quotaMailingListenerConfiguration) {
         this.eventStore = eventStore;
         this.quotaMailingListenerConfiguration = quotaMailingListenerConfiguration;
+        this.listenerName = quotaMailingListenerConfiguration.getName();
     }
 
     @Override
@@ -45,7 +47,7 @@ public class DetectThresholdCrossingHandler implements CommandHandler<DetectThre
     }
 
     private UserQuotaThresholds loadAggregate(DetectThresholdCrossing command) {
-        UserQuotaThresholds.Id aggregateId = UserQuotaThresholds.Id.from(command.getUser());
+        UserQuotaThresholds.Id aggregateId = UserQuotaThresholds.Id.from(command.getUser(), listenerName);
         History history = eventStore.getEventsOfAggregate(aggregateId);
         return UserQuotaThresholds.fromEvents(aggregateId, history);
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfigurationTest.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfigurationTest.java b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfigurationTest.java
index 50a4044..1668640 100644
--- a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfigurationTest.java
+++ b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfigurationTest.java
@@ -57,6 +57,7 @@ public class QuotaMailingListenerConfigurationTest {
                 "  <gracePeriod>3 days</gracePeriod>\n" +
                 "  <subjectTemplate>" + SUBJECT_TEMPLATE + "</subjectTemplate>\n" +
                 "  <bodyTemplate>" + BODY_TEMPLATE + "</bodyTemplate>\n" +
+                "  <name>listener-name</name>\n" +
                 "</configuration>"));
 
         QuotaMailingListenerConfiguration result = QuotaMailingListenerConfiguration.from(xmlConfiguration);
@@ -68,6 +69,7 @@ public class QuotaMailingListenerConfigurationTest {
                 .gracePeriod(Duration.ofDays(3))
                 .subjectTemplate(SUBJECT_TEMPLATE)
                 .bodyTemplate(BODY_TEMPLATE)
+                .name("listener-name")
                 .build());
     }
 
@@ -106,6 +108,13 @@ public class QuotaMailingListenerConfigurationTest {
     }
 
     @Test
+    public void defaultConfigurationShouldUseDefaultAsListenerName() throws Exception {
+        QuotaMailingListenerConfiguration result = QuotaMailingListenerConfiguration.defaultConfiguration();
+
+        assertThat(result.getName()).isEqualTo("default");
+    }
+
+    @Test
     public void fromShouldThrowOnNonParsableGracePeriod() throws Exception {
         DefaultConfigurationBuilder xmlConfiguration = new DefaultConfigurationBuilder();
         xmlConfiguration.load(toStream(

http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/aggregates/UserQuotaThresholdsTest.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/aggregates/UserQuotaThresholdsTest.java b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/aggregates/UserQuotaThresholdsTest.java
index 45aef96..52d7ff4 100644
--- a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/aggregates/UserQuotaThresholdsTest.java
+++ b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/aggregates/UserQuotaThresholdsTest.java
@@ -20,6 +20,7 @@
 package org.apache.james.mailbox.quota.mailing.aggregates;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import org.apache.james.core.User;
 import org.junit.jupiter.api.Test;
@@ -39,9 +40,47 @@ public class UserQuotaThresholdsTest {
 
     @Test
     public void asAggregationKeyShouldConvertAggregateToAStringRepresentation() {
-        assertThat(UserQuotaThresholds.Id.from(BOB)
+        assertThat(UserQuotaThresholds.Id.from(BOB, "listenerName")
             .asAggregateKey())
-            .isEqualTo("QuotaThreasholdEvents-bob@domain");
+            .isEqualTo("QuotaThreasholdEvents/listenerName/bob@domain");
     }
 
+    @Test
+    public void fromShouldThrowWhenUserWithSlash() {
+        assertThatThrownBy(() -> UserQuotaThresholds.Id.from(User.fromUsername("foo/bar@domain"), "listenerName"))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void fromShouldThrowWhenDomainWithSlash() {
+        assertThatThrownBy(() -> UserQuotaThresholds.Id.from(User.fromUsername("foo.bar@dom/ain"), "listenerName"))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void fromShouldThrowWhenListenerNameWithSlash() {
+        assertThatThrownBy(() -> UserQuotaThresholds.Id.from(BOB, "listener/Name"))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void asAggregationKeyShouldParseAsOriginalPojo() {
+        UserQuotaThresholds.Id id = UserQuotaThresholds.Id.from(BOB, "listenerName");
+        assertThat(UserQuotaThresholds.Id.fromKey(id.asAggregateKey())).isEqualTo(id);
+    }
+
+    @Test
+    public void fromKeyShouldThrowWhenLessThan3Parts() {
+        assertThatThrownBy(() -> UserQuotaThresholds.Id.fromKey("1/2")).isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void fromKeyShouldThrowWhenMoreThan3Parts() {
+        assertThatThrownBy(() -> UserQuotaThresholds.Id.fromKey("1/2/3/4")).isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void fromKeyShouldThrowWhenPrefixIsNotQuotaThreasholdEvents() {
+        assertThatThrownBy(() -> UserQuotaThresholds.Id.fromKey("WrongPrefix/bob@domain/name")).isInstanceOf(IllegalArgumentException.class);
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJmapTestRule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJmapTestRule.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJmapTestRule.java
index 08ded89..ef5585b 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJmapTestRule.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJmapTestRule.java
@@ -33,10 +33,9 @@ import org.junit.runners.model.Statement;
 
 import com.google.inject.Module;
 
-
 public class CassandraJmapTestRule implements TestRule {
 
-    private static final int LIMIT_TO_3_MESSAGES = 3;
+    private static final int LIMIT_TO_10_MESSAGES = 10;
     private final TemporaryFolder temporaryFolder;
 
     public static CassandraJmapTestRule defaultTestRule() {
@@ -65,7 +64,7 @@ public class CassandraJmapTestRule implements TestRule {
                 CassandraJamesServerMain.PROTOCOLS,
                 CassandraJamesServerMain.PLUGINS)
             .overrideWith(binder -> binder.bind(TextExtractor.class).to(PDFTextExtractor.class))
-            .overrideWith(new TestJMAPServerModule(LIMIT_TO_3_MESSAGES))
+            .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES))
             .overrideWith(new TestESMetricReporterModule())
             .overrideWith(guiceModuleTestRule.getModule())
             .overrideWith(additionals);

http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/server/container/guice/memory-guice/src/test/java/org/apache/james/MemoryJmapTestRule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/memory-guice/src/test/java/org/apache/james/MemoryJmapTestRule.java b/server/container/guice/memory-guice/src/test/java/org/apache/james/MemoryJmapTestRule.java
index 69762f2..b1ac91e 100644
--- a/server/container/guice/memory-guice/src/test/java/org/apache/james/MemoryJmapTestRule.java
+++ b/server/container/guice/memory-guice/src/test/java/org/apache/james/MemoryJmapTestRule.java
@@ -38,7 +38,7 @@ import com.google.inject.Module;
 
 public class MemoryJmapTestRule implements TestRule {
 
-    private static final int LIMIT_TO_3_MESSAGES = 3;
+    private static final int LIMIT_TO_10_MESSAGES = 10;
     
     public TemporaryFolder temporaryFolder = new TemporaryFolder();
 
@@ -49,11 +49,11 @@ public class MemoryJmapTestRule implements TestRule {
             .build();
         return new GuiceJamesServer(configuration)
             .combineWith(MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE)
-            .overrideWith(modules)
-            .overrideWith(new TestJMAPServerModule(LIMIT_TO_3_MESSAGES))
+            .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES))
             .overrideWith(binder -> binder.bind(PersistenceAdapter.class).to(MemoryPersistenceAdapter.class))
             .overrideWith(binder -> binder.bind(TextExtractor.class).to(PDFTextExtractor.class))
-            .overrideWith(binder -> binder.bind(MessageSearchIndex.class).to(SimpleMessageSearchIndex.class));
+            .overrideWith(binder -> binder.bind(MessageSearchIndex.class).to(SimpleMessageSearchIndex.class))
+            .overrideWith(modules);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraGetMessageListMethodTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraGetMessageListMethodTest.java b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraGetMessageListMethodTest.java
index 634da89..ed41abe 100644
--- a/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraGetMessageListMethodTest.java
+++ b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraGetMessageListMethodTest.java
@@ -26,6 +26,7 @@ import org.apache.james.DockerCassandraRule;
 import org.apache.james.GuiceJamesServer;
 import org.apache.james.backends.cassandra.ContainerLifecycleConfiguration;
 import org.apache.james.jmap.methods.integration.GetMessageListMethodTest;
+import org.apache.james.modules.TestJMAPServerModule;
 import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.rules.TestRule;
@@ -45,7 +46,8 @@ public class CassandraGetMessageListMethodTest extends GetMessageListMethodTest
 
     @Override
     protected GuiceJamesServer createJmapServer() throws IOException {
-        return rule.jmapServer(cassandra.getModule());
+        return rule.jmapServer(cassandra.getModule(),
+            new TestJMAPServerModule(LIMIT_TO_3_MESSAGES));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/resources/listeners.xml
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/resources/listeners.xml b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/resources/listeners.xml
index 8c82680..93fad5f 100644
--- a/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/resources/listeners.xml
+++ b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/resources/listeners.xml
@@ -31,6 +31,16 @@
       <thresholds>
         <threshold>0.1</threshold>
       </thresholds>
+      <name>first</name>
+    </configuration>
+  </listener>
+  <listener>
+    <class>org.apache.james.mailbox.quota.mailing.listeners.QuotaThresholdCrossingListener</class>
+    <configuration>
+      <thresholds>
+        <threshold>0.2</threshold>
+      </thresholds>
+      <name>second</name>
     </configuration>
   </listener>
 </listeners>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessageListMethodTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessageListMethodTest.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessageListMethodTest.java
index 055d1ce..8780771 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessageListMethodTest.java
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessageListMethodTest.java
@@ -79,6 +79,7 @@ import org.junit.Test;
 import com.jayway.restassured.RestAssured;
 
 public abstract class GetMessageListMethodTest {
+    public static final int LIMIT_TO_3_MESSAGES = 3;
     private static final String FORWARDED = "$Forwarded";
     private static final ZoneId ZONE_ID = ZoneId.of("Europe/Paris");
     private ACLProbeImpl aclProbe;

http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/QuotaMailingTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/QuotaMailingTest.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/QuotaMailingTest.java
index ec5d65a..4753add 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/QuotaMailingTest.java
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/QuotaMailingTest.java
@@ -49,6 +49,7 @@ import org.apache.james.modules.QuotaProbesImpl;
 import org.apache.james.probe.DataProbe;
 import org.apache.james.utils.DataProbeImpl;
 import org.apache.james.utils.JmapGuiceProbe;
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -88,6 +89,11 @@ public abstract class QuotaMailingTest {
         bartAccessToken = authenticateJamesUser(baseUri(jmapServer), BART, BOB_PASSWORD);
     }
 
+    @After
+    public void tearDown() {
+        jmapServer.stop();
+    }
+
     @Test
     public void shouldSendANoticeWhenThresholdExceeded() throws Exception {
         jmapServer.getProbe(QuotaProbesImpl.class)
@@ -96,6 +102,7 @@ public abstract class QuotaMailingTest {
 
         bartSendMessageToHomer();
         // Homer receives a mail big enough to trigger a configured threshold
+
         calmlyAwait.atMost(30, TimeUnit.SECONDS)
             .until(() -> listMessageIdsForAccount(homerAccessToken).size() == 2);
 
@@ -123,11 +130,15 @@ public abstract class QuotaMailingTest {
                 new SerializableQuotaValue<>(QuotaSize.size(100 * 1000)));
 
         bartSendMessageToHomer();
-        // Home receives a mail big enough to trigger a configured threshold
-
+        // Homer receives a mail big enough to trigger a 10% configured threshold
         calmlyAwait.atMost(30, TimeUnit.SECONDS)
             .until(() -> listMessageIdsForAccount(homerAccessToken).size() == 2);
 
+        bartSendMessageToHomer();
+        // Homer receives a mail big enough to trigger a 20% configured threshold
+        calmlyAwait.atMost(30, TimeUnit.SECONDS)
+            .until(() -> listMessageIdsForAccount(homerAccessToken).size() == 4);
+
         List<String> ids = listMessageIdsForAccount(homerAccessToken);
         String idString = ids.stream()
             .map(id -> "\"" + id + "\"")
@@ -142,7 +153,9 @@ public abstract class QuotaMailingTest {
             .statusCode(200)
             .log().ifValidationFails()
             .body(ARGUMENTS + ".list.textBody",
-                hasItem(containsString("You currently occupy more than 10 % of the total size allocated to you")));
+                hasItem(containsString("You currently occupy more than 10 % of the total size allocated to you")))
+            .body(ARGUMENTS + ".list.textBody",
+                hasItem(containsString("You currently occupy more than 20 % of the total size allocated to you")));
     }
 
     private void bartSendMessageToHomer() {

http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/java/org/apache/james/jmap/memory/MemoryGetMessageListMethodTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/java/org/apache/james/jmap/memory/MemoryGetMessageListMethodTest.java b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/java/org/apache/james/jmap/memory/MemoryGetMessageListMethodTest.java
index 79bc15d..23c495e 100644
--- a/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/java/org/apache/james/jmap/memory/MemoryGetMessageListMethodTest.java
+++ b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/java/org/apache/james/jmap/memory/MemoryGetMessageListMethodTest.java
@@ -24,6 +24,7 @@ import java.io.IOException;
 import org.apache.james.GuiceJamesServer;
 import org.apache.james.MemoryJmapTestRule;
 import org.apache.james.jmap.methods.integration.GetMessageListMethodTest;
+import org.apache.james.modules.TestJMAPServerModule;
 import org.junit.Rule;
 
 public class MemoryGetMessageListMethodTest extends GetMessageListMethodTest {
@@ -33,7 +34,7 @@ public class MemoryGetMessageListMethodTest extends GetMessageListMethodTest {
 
     @Override
     protected GuiceJamesServer createJmapServer() throws IOException {
-        return memoryJmap.jmapServer();
+        return memoryJmap.jmapServer(new TestJMAPServerModule(LIMIT_TO_3_MESSAGES));
     }
     
     @Override

http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/listeners.xml
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/listeners.xml b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/listeners.xml
index 47a3381..9d0a0fe 100644
--- a/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/listeners.xml
+++ b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/listeners.xml
@@ -28,6 +28,16 @@
       <thresholds>
         <threshold>0.1</threshold>
       </thresholds>
+      <name>first</name>
+    </configuration>
+  </listener>
+  <listener>
+    <class>org.apache.james.mailbox.quota.mailing.listeners.QuotaThresholdCrossingListener</class>
+    <configuration>
+      <thresholds>
+        <threshold>0.2</threshold>
+      </thresholds>
+      <name>second</name>
     </configuration>
   </listener>
 </listeners>
\ No newline at end of file


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


[2/8] james-project git commit: JAMES-2399 load listeners and their configuration from listeners.xml file

Posted by ma...@apache.org.
JAMES-2399 load listeners and their configuration from listeners.xml file


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

Branch: refs/heads/master
Commit: 8040919877a13b02bf24925b223b4243fe9a79db
Parents: cc4fb69
Author: Matthieu Baechler <ma...@apache.org>
Authored: Tue May 15 15:52:55 2018 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue May 22 10:02:27 2018 +0200

----------------------------------------------------------------------
 mailbox/plugin/quota-mailing/pom.xml            |  26 ++-
 .../QuotaMailingListenerConfiguration.java      |  46 +++++
 .../QuotaThresholdCrossingListener.java         |  40 ++++-
 .../mailbox/quota/model/QuotaThresholds.java    |  16 ++
 .../QuotaMailingListenerConfigurationTest.java  | 172 +++++++++++++++++++
 .../QuotaThresholdListenersTestSystem.java      |   4 +-
 .../quota/model/QuotaThresholdsTest.java        |   9 +
 server/container/guice/cassandra-guice/pom.xml  |   4 -
 .../mailbox/CassandraQuotaMailingModule.java    |   2 -
 .../guice/mailbox-plugin-quota-mailing/pom.xml  |  45 -----
 .../modules/mailbox/QuotaMailingModule.java     |  41 -----
 .../modules/mailbox/ListenerConfiguration.java  |  23 ++-
 .../mailbox/MailboxListenersLoaderImpl.java     |   7 +-
 .../mailbox/MailboxListenersLoaderImplTest.java |   8 +-
 server/container/guice/memory-guice/pom.xml     |   8 +-
 .../org/apache/james/MemoryJamesServerMain.java |   7 +-
 server/container/guice/pom.xml                  |   6 -
 .../src/test/resources/listeners.xml            |   5 +
 .../methods/integration/QuotaMailingTest.java   |  37 +++-
 .../src/test/resources/listeners.xml            |   5 +
 20 files changed, 367 insertions(+), 144 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/mailbox/plugin/quota-mailing/pom.xml
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing/pom.xml b/mailbox/plugin/quota-mailing/pom.xml
index b10bd8e..3cda088 100644
--- a/mailbox/plugin/quota-mailing/pom.xml
+++ b/mailbox/plugin/quota-mailing/pom.xml
@@ -36,20 +36,6 @@
     <dependencies>
         <dependency>
             <groupId>${project.groupId}</groupId>
-            <artifactId>event-sourcing-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>${project.groupId}</groupId>
-            <artifactId>event-sourcing-event-store-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>${project.groupId}</groupId>
-            <artifactId>event-sourcing-event-store-api</artifactId>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>${project.groupId}</groupId>
             <artifactId>apache-james-mailbox-api</artifactId>
         </dependency>
         <dependency>
@@ -75,6 +61,14 @@
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
+            <artifactId>event-sourcing-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>event-sourcing-event-store-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
             <artifactId>james-server-core</artifactId>
             <scope>test</scope>
         </dependency>
@@ -93,6 +87,10 @@
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
+            <artifactId>james-server-lifecycle-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
             <artifactId>james-server-util</artifactId>
         </dependency>
         <dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfiguration.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfiguration.java b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfiguration.java
index b501130..8f680b4 100644
--- a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfiguration.java
+++ b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfiguration.java
@@ -24,15 +24,59 @@ import java.util.Collection;
 import java.util.Objects;
 import java.util.Optional;
 
+import org.apache.commons.configuration.HierarchicalConfiguration;
 import org.apache.james.filesystem.api.FileSystem;
 import org.apache.james.mailbox.quota.model.QuotaThreshold;
 import org.apache.james.mailbox.quota.model.QuotaThresholds;
+import org.apache.james.util.TimeConverter;
 
+import com.github.steveash.guavate.Guavate;
 import com.google.common.base.MoreObjects;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableList;
 
 public class QuotaMailingListenerConfiguration {
 
+    interface XmlKeys {
+        String SUBJECT_TEMPLATE = "subjectTemplate";
+        String BODY_TEMPLATE = "bodyTemplate";
+        String GRACE_PERIOD = "gracePeriod";
+        String THRESHOLDS = "thresholds.threshold";
+        String ROOT_KEY = "";
+    }
+
+    public static QuotaMailingListenerConfiguration from(HierarchicalConfiguration config) {
+        return builder()
+            .addThresholds(readThresholds(config))
+            .subjectTemplate(readSubjectTemplate(config))
+            .bodyTemplate(readBodyTemplate(config))
+            .gracePeriod(readGracePeriod(config))
+            .build();
+    }
+
+    private static Optional<String> readSubjectTemplate(HierarchicalConfiguration config) {
+        return Optional.ofNullable(config.getString(XmlKeys.SUBJECT_TEMPLATE, null));
+    }
+
+    private static Optional<String> readBodyTemplate(HierarchicalConfiguration config) {
+        return Optional.ofNullable(config.getString(XmlKeys.BODY_TEMPLATE, null));
+    }
+
+    private static Optional<Duration> readGracePeriod(HierarchicalConfiguration config) {
+        return Optional.ofNullable(config.getString(XmlKeys.GRACE_PERIOD, null))
+            .map(string -> TimeConverter.getMilliSeconds(string, TimeConverter.Unit.DAYS))
+            .map(Duration::ofMillis);
+    }
+
+    private static ImmutableList<QuotaThreshold> readThresholds(HierarchicalConfiguration config) {
+        return config.configurationsAt(XmlKeys.THRESHOLDS)
+            .stream()
+            .map(node -> node.getDouble(XmlKeys.ROOT_KEY))
+            .map(QuotaThreshold::new)
+            .collect(Guavate.toImmutableList());
+    }
+
     public static class Builder {
         private ImmutableList.Builder<QuotaThreshold> thresholds;
         private Optional<Duration> gradePeriod;
@@ -67,11 +111,13 @@ public class QuotaMailingListenerConfiguration {
         }
         
         public Builder bodyTemplate(String bodyTemplate) {
+            Preconditions.checkArgument(!Strings.isNullOrEmpty(bodyTemplate), "Pass a non null/empty bodyTemplate");
             this.bodyTemplate = Optional.of(bodyTemplate);
             return this;
         }
 
         public Builder subjectTemplate(String subjectTemplate) {
+            Preconditions.checkArgument(!Strings.isNullOrEmpty(subjectTemplate), "Pass a non null/empty subjectTemplate");
             this.subjectTemplate = Optional.of(subjectTemplate);
             return this;
         }

http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/listeners/QuotaThresholdCrossingListener.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/listeners/QuotaThresholdCrossingListener.java b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/listeners/QuotaThresholdCrossingListener.java
index bf917f7..6aaf1cb 100644
--- a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/listeners/QuotaThresholdCrossingListener.java
+++ b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/listeners/QuotaThresholdCrossingListener.java
@@ -21,10 +21,14 @@ package org.apache.james.mailbox.quota.mailing.listeners;
 
 import javax.inject.Inject;
 
+import org.apache.commons.configuration.HierarchicalConfiguration;
 import org.apache.james.core.User;
+import org.apache.james.eventsourcing.CommandHandler;
 import org.apache.james.eventsourcing.EventSourcingSystem;
+import org.apache.james.eventsourcing.Subscriber;
 import org.apache.james.eventsourcing.eventstore.EventStore;
 import org.apache.james.filesystem.api.FileSystem;
+import org.apache.james.lifecycle.api.Configurable;
 import org.apache.james.mailbox.Event;
 import org.apache.james.mailbox.MailboxListener;
 import org.apache.james.mailbox.quota.mailing.QuotaMailingListenerConfiguration;
@@ -38,19 +42,36 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.collect.ImmutableSet;
 
-public class QuotaThresholdCrossingListener implements MailboxListener {
+public class QuotaThresholdCrossingListener implements MailboxListener, Configurable {
     private static final Logger LOGGER = LoggerFactory.getLogger(QuotaThresholdCrossingListener.class);
+    private final EventStore eventStore;
+    private final MailetContext mailetContext;
+    private final UsersRepository usersRepository;
+    private final FileSystem fileSystem;
 
-    private final EventSourcingSystem eventSourcingSystem;
+    private EventSourcingSystem eventSourcingSystem;
 
     @Inject
-    public QuotaThresholdCrossingListener(MailetContext mailetContext, UsersRepository usersRepository,
-                                          FileSystem fileSystem, EventStore eventStore, QuotaMailingListenerConfiguration configuration) {
-        this.eventSourcingSystem = new EventSourcingSystem(
-            ImmutableSet.of(new DetectThresholdCrossingHandler(eventStore, configuration)),
-            ImmutableSet.of(new QuotaThresholdMailer(mailetContext, usersRepository, fileSystem, configuration)),
-            eventStore
-        );
+    public QuotaThresholdCrossingListener(MailetContext mailetContext,
+                                          UsersRepository usersRepository,
+                                          FileSystem fileSystem,
+                                          EventStore eventStore) {
+        this.eventStore = eventStore;
+        this.mailetContext = mailetContext;
+        this.usersRepository = usersRepository;
+        this.fileSystem = fileSystem;
+    }
+
+    @Override
+    public void configure(HierarchicalConfiguration config) {
+        QuotaMailingListenerConfiguration configuration = QuotaMailingListenerConfiguration.from(config);
+        configure(configuration);
+    }
+
+    public void configure(QuotaMailingListenerConfiguration configuration) {
+        ImmutableSet<CommandHandler<?>> handlers = ImmutableSet.of(new DetectThresholdCrossingHandler(eventStore, configuration));
+        ImmutableSet<Subscriber> subscribers = ImmutableSet.of(new QuotaThresholdMailer(mailetContext, usersRepository, fileSystem, configuration));
+        eventSourcingSystem = new EventSourcingSystem(handlers, subscribers, eventStore);
     }
 
     @Override
@@ -85,4 +106,5 @@ public class QuotaThresholdCrossingListener implements MailboxListener {
                 .getUser()
                 .getUserName());
     }
+
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/model/QuotaThresholds.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/model/QuotaThresholds.java b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/model/QuotaThresholds.java
index 042799e..8f92ed3 100644
--- a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/model/QuotaThresholds.java
+++ b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/model/QuotaThresholds.java
@@ -22,6 +22,7 @@ package org.apache.james.mailbox.quota.model;
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.List;
+import java.util.Objects;
 
 import org.apache.james.mailbox.model.Quota;
 
@@ -50,6 +51,21 @@ public class QuotaThresholds {
     }
 
     @Override
+    public final boolean equals(Object o) {
+        if (o instanceof QuotaThresholds) {
+            QuotaThresholds that = (QuotaThresholds) o;
+
+            return Objects.equals(this.quotaThresholds, that.quotaThresholds);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(quotaThresholds);
+    }
+
+    @Override
     public String toString() {
         return MoreObjects.toStringHelper(this)
             .add("quotaThresholds", quotaThresholds)

http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfigurationTest.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfigurationTest.java b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfigurationTest.java
new file mode 100644
index 0000000..50a4044
--- /dev/null
+++ b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfigurationTest.java
@@ -0,0 +1,172 @@
+/****************************************************************
+ * 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.mailbox.quota.mailing;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.time.Duration;
+
+import org.apache.commons.configuration.DefaultConfigurationBuilder;
+import org.apache.james.mailbox.quota.model.QuotaThreshold;
+import org.junit.jupiter.api.Test;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+
+public class QuotaMailingListenerConfigurationTest {
+
+    private static final String SUBJECT_TEMPLATE = "sbj.mustache";
+    private static final String BODY_TEMPLATE = "body.mustache";
+
+    @Test
+    public void shouldMatchBeanContract() {
+        EqualsVerifier.forClass(QuotaMailingListenerConfiguration.class)
+            .allFieldsShouldBeUsed()
+            .verify();
+    }
+
+    @Test
+    public void fromShouldReadXMLConfiguration() throws Exception {
+        DefaultConfigurationBuilder xmlConfiguration = new DefaultConfigurationBuilder();
+        xmlConfiguration.load(toStream(
+            "<configuration>\n" +
+                "  <thresholds>\n" +
+                "    <threshold>0.85</threshold>\n" +
+                "    <threshold>0.98</threshold>\n" +
+                "  </thresholds>\n" +
+                "  <gracePeriod>3 days</gracePeriod>\n" +
+                "  <subjectTemplate>" + SUBJECT_TEMPLATE + "</subjectTemplate>\n" +
+                "  <bodyTemplate>" + BODY_TEMPLATE + "</bodyTemplate>\n" +
+                "</configuration>"));
+
+        QuotaMailingListenerConfiguration result = QuotaMailingListenerConfiguration.from(xmlConfiguration);
+
+        assertThat(result)
+            .isEqualTo(QuotaMailingListenerConfiguration.builder()
+                .addThresholds(new QuotaThreshold(0.85),
+                    new QuotaThreshold(0.98))
+                .gracePeriod(Duration.ofDays(3))
+                .subjectTemplate(SUBJECT_TEMPLATE)
+                .bodyTemplate(BODY_TEMPLATE)
+                .build());
+    }
+
+    @Test
+    public void fromShouldAcceptEmptyThreshold() throws Exception {
+        DefaultConfigurationBuilder xmlConfiguration = new DefaultConfigurationBuilder();
+        xmlConfiguration.load(toStream(
+            "<configuration>\n" +
+                "  <thresholds></thresholds>\n" +
+                "  <gracePeriod>3 days</gracePeriod>\n" +
+                "  <subjectTemplate>" + SUBJECT_TEMPLATE + "</subjectTemplate>\n" +
+                "  <bodyTemplate>" + BODY_TEMPLATE + "</bodyTemplate>\n" +
+                "</configuration>"));
+
+        QuotaMailingListenerConfiguration result = QuotaMailingListenerConfiguration.from(xmlConfiguration);
+
+        assertThat(result)
+            .isEqualTo(QuotaMailingListenerConfiguration.builder()
+                .gracePeriod(Duration.ofDays(3))
+                .subjectTemplate(SUBJECT_TEMPLATE)
+                .bodyTemplate(BODY_TEMPLATE)
+                .build());
+    }
+
+    @Test
+    public void fromShouldReturnDefaultWhenEmptyConfiguration() throws Exception {
+        DefaultConfigurationBuilder xmlConfiguration = new DefaultConfigurationBuilder();
+        xmlConfiguration.load(toStream(
+            "<configuration></configuration>"));
+
+        QuotaMailingListenerConfiguration result = QuotaMailingListenerConfiguration.from(xmlConfiguration);
+
+        assertThat(result)
+            .isEqualTo(QuotaMailingListenerConfiguration.builder()
+                .build());
+    }
+
+    @Test
+    public void fromShouldThrowOnNonParsableGracePeriod() throws Exception {
+        DefaultConfigurationBuilder xmlConfiguration = new DefaultConfigurationBuilder();
+        xmlConfiguration.load(toStream(
+            "<configuration><gracePeriod>nonParsable</gracePeriod></configuration>"));
+
+        assertThatThrownBy(() -> QuotaMailingListenerConfiguration.from(xmlConfiguration))
+            .isInstanceOf(NumberFormatException.class);
+    }
+
+    @Test
+    public void fromShouldThrowOnNegativeGracePeriod() throws Exception {
+        DefaultConfigurationBuilder xmlConfiguration = new DefaultConfigurationBuilder();
+        xmlConfiguration.load(toStream(
+            "<configuration><gracePeriod>-12 ms</gracePeriod></configuration>"));
+
+        assertThatThrownBy(() -> QuotaMailingListenerConfiguration.from(xmlConfiguration))
+            .isInstanceOf(NumberFormatException.class);
+    }
+
+    @Test
+    public void fromShouldLoadGracePeriodInMs() throws Exception {
+        DefaultConfigurationBuilder xmlConfiguration = new DefaultConfigurationBuilder();
+        xmlConfiguration.load(toStream(
+            "<configuration><gracePeriod>12 ms</gracePeriod></configuration>"));
+
+        assertThat(QuotaMailingListenerConfiguration.from(xmlConfiguration).getGracePeriod())
+            .isEqualTo(Duration.ofMillis(12));
+    }
+
+    @Test
+    public void defaultUnitShouldBeMilliseconds() throws Exception {
+        DefaultConfigurationBuilder xmlConfiguration = new DefaultConfigurationBuilder();
+        xmlConfiguration.load(toStream(
+            "<configuration><gracePeriod>12</gracePeriod></configuration>"));
+
+        assertThat(QuotaMailingListenerConfiguration.from(xmlConfiguration).getGracePeriod())
+            .isEqualTo(Duration.ofDays(12));
+    }
+
+    @Test
+    public void fromShouldThrowOnEmptySubjectTemplate() throws Exception {
+        DefaultConfigurationBuilder xmlConfiguration = new DefaultConfigurationBuilder();
+        xmlConfiguration.load(toStream(
+            "<configuration><subjectTemplate></subjectTemplate></configuration>"));
+
+        assertThatThrownBy(() -> QuotaMailingListenerConfiguration.from(xmlConfiguration))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void fromShouldThrowOnEmptyBodyTemplate() throws Exception {
+        DefaultConfigurationBuilder xmlConfiguration = new DefaultConfigurationBuilder();
+        xmlConfiguration.load(toStream(
+            "<configuration><bodyTemplate></bodyTemplate></configuration>"));
+
+        assertThatThrownBy(() -> QuotaMailingListenerConfiguration.from(xmlConfiguration))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    private InputStream toStream(String string) {
+        return new ByteArrayInputStream(string.getBytes(StandardCharsets.UTF_8));
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/listeners/QuotaThresholdListenersTestSystem.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/listeners/QuotaThresholdListenersTestSystem.java b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/listeners/QuotaThresholdListenersTestSystem.java
index 32f19e3..f6be2c0 100644
--- a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/listeners/QuotaThresholdListenersTestSystem.java
+++ b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/listeners/QuotaThresholdListenersTestSystem.java
@@ -41,7 +41,9 @@ public class QuotaThresholdListenersTestSystem {
         FileSystem fileSystem = new FileSystemImpl(new JamesServerResourceLoader("."));
 
         QuotaThresholdCrossingListener thresholdCrossingListener =
-            new QuotaThresholdCrossingListener(mailetContext, MemoryUsersRepository.withVirtualHosting(), fileSystem, eventStore, configuration);
+            new QuotaThresholdCrossingListener(mailetContext, MemoryUsersRepository.withVirtualHosting(), fileSystem, eventStore);
+
+        thresholdCrossingListener.configure(configuration);
 
         MockMailboxSession mailboxSession = new MockMailboxSession("system");
         delegatingListener.addGlobalListener(thresholdCrossingListener, mailboxSession);

http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdsTest.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdsTest.java b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdsTest.java
index 09245eb..b959c1d 100644
--- a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdsTest.java
+++ b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdsTest.java
@@ -32,9 +32,18 @@ import org.junit.jupiter.api.Test;
 
 import com.google.common.collect.ImmutableList;
 
+import nl.jqno.equalsverifier.EqualsVerifier;
+
 public class QuotaThresholdsTest {
 
     @Test
+    public void shouldMatchBeanContract() {
+        EqualsVerifier.forClass(QuotaThresholds.class)
+            .allFieldsShouldBeUsed()
+            .verify();
+    }
+
+    @Test
     public void highestExceededThresholdShouldReturnZeroWhenBelowAllThresholds() {
         assertThat(
             new QuotaThresholds(ImmutableList.of(_50, _80, _95, _99))

http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/container/guice/cassandra-guice/pom.xml
----------------------------------------------------------------------
diff --git a/server/container/guice/cassandra-guice/pom.xml b/server/container/guice/cassandra-guice/pom.xml
index 11725ec..54f4958 100644
--- a/server/container/guice/cassandra-guice/pom.xml
+++ b/server/container/guice/cassandra-guice/pom.xml
@@ -146,10 +146,6 @@
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
-            <artifactId>james-server-guice-mailbox-plugin-quota-mailing</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>${project.groupId}</groupId>
             <artifactId>james-server-guice-mailbox-plugin-spamassassin</artifactId>
         </dependency>
         <dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraQuotaMailingModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraQuotaMailingModule.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraQuotaMailingModule.java
index c8994d4..f81d572 100644
--- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraQuotaMailingModule.java
+++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraQuotaMailingModule.java
@@ -28,8 +28,6 @@ import com.google.inject.multibindings.Multibinder;
 public class CassandraQuotaMailingModule extends AbstractModule {
     @Override
     protected void configure() {
-        install(new QuotaMailingModule());
-
         Multibinder.newSetBinder(binder(), EventDTOModule.class)
             .addBinding()
             .to(QuotaThresholdChangedEventDTOModule.class);

http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/container/guice/mailbox-plugin-quota-mailing/pom.xml
----------------------------------------------------------------------
diff --git a/server/container/guice/mailbox-plugin-quota-mailing/pom.xml b/server/container/guice/mailbox-plugin-quota-mailing/pom.xml
deleted file mode 100644
index 1a96872..0000000
--- a/server/container/guice/mailbox-plugin-quota-mailing/pom.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>org.apache.james</groupId>
-        <artifactId>james-server-guice</artifactId>
-        <version>3.1.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>james-server-guice-mailbox-plugin-quota-mailing</artifactId>
-
-    <name>Apache James :: Server :: Guice :: Mailbox :: Plugin :: Quota Mailing</name>
-    <description>Mailbox modules for Guice implementation of Quota mailing</description>
-
-    <dependencies>
-        <dependency>
-            <groupId>${project.groupId}</groupId>
-            <artifactId>apache-james-mailbox-quota-mailing</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.google.inject</groupId>
-            <artifactId>guice</artifactId>
-        </dependency>
-    </dependencies>
-
-</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/container/guice/mailbox-plugin-quota-mailing/src/main/java/org/apache/james/modules/mailbox/QuotaMailingModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/mailbox-plugin-quota-mailing/src/main/java/org/apache/james/modules/mailbox/QuotaMailingModule.java b/server/container/guice/mailbox-plugin-quota-mailing/src/main/java/org/apache/james/modules/mailbox/QuotaMailingModule.java
deleted file mode 100644
index 7d13cc6..0000000
--- a/server/container/guice/mailbox-plugin-quota-mailing/src/main/java/org/apache/james/modules/mailbox/QuotaMailingModule.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/****************************************************************
- * 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 java.time.Duration;
-
-import org.apache.james.mailbox.quota.mailing.QuotaMailingListenerConfiguration;
-import org.apache.james.mailbox.quota.model.QuotaThreshold;
-
-import com.google.inject.AbstractModule;
-
-public class QuotaMailingModule extends AbstractModule {
-    @Override
-    protected void configure() {
-        bind(QuotaMailingListenerConfiguration.class)
-            .toInstance(
-                QuotaMailingListenerConfiguration.builder()
-                    .addThresholds(
-                        new QuotaThreshold(0.80),
-                        new QuotaThreshold(0.99))
-                    .gracePeriod(Duration.ofDays(1))
-                .build());
-    }
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/ListenerConfiguration.java
----------------------------------------------------------------------
diff --git a/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/ListenerConfiguration.java b/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/ListenerConfiguration.java
index 7258190..f2d5ea3 100644
--- a/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/ListenerConfiguration.java
+++ b/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/ListenerConfiguration.java
@@ -18,9 +18,10 @@
  ****************************************************************/
 package org.apache.james.modules.mailbox;
 
+import java.util.Optional;
+
 import org.apache.commons.configuration.HierarchicalConfiguration;
 
-import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 
@@ -29,16 +30,32 @@ public class ListenerConfiguration {
     public static ListenerConfiguration from(HierarchicalConfiguration configuration) {
         String listenerClass = configuration.getString("class");
         Preconditions.checkState(!Strings.isNullOrEmpty(listenerClass), "class name is mandatory");
-        return new ListenerConfiguration(listenerClass);
+        return new ListenerConfiguration(listenerClass, extractSubconfiguration(configuration));
+    }
+
+    public static ListenerConfiguration forClass(String clazz) {
+        return new ListenerConfiguration(clazz, Optional.empty());
+    }
+
+    private static Optional<HierarchicalConfiguration> extractSubconfiguration(HierarchicalConfiguration configuration) {
+        return configuration.configurationsAt("configuration")
+            .stream()
+            .findFirst();
     }
 
     private final String clazz;
+    private final Optional<HierarchicalConfiguration> configuration;
 
-    @VisibleForTesting ListenerConfiguration(String clazz) {
+    private ListenerConfiguration(String clazz, Optional<HierarchicalConfiguration> configuration) {
         this.clazz = clazz;
+        this.configuration = configuration;
     }
 
     public String getClazz() {
         return clazz;
     }
+
+    public Optional<HierarchicalConfiguration> getConfiguration() {
+        return configuration;
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/MailboxListenersLoaderImpl.java
----------------------------------------------------------------------
diff --git a/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/MailboxListenersLoaderImpl.java b/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/MailboxListenersLoaderImpl.java
index d8476be..68a8643 100644
--- a/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/MailboxListenersLoaderImpl.java
+++ b/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/MailboxListenersLoaderImpl.java
@@ -20,6 +20,7 @@ package org.apache.james.modules.mailbox;
 
 import java.util.Set;
 
+import org.apache.commons.configuration.ConfigurationException;
 import org.apache.commons.configuration.HierarchicalConfiguration;
 import org.apache.james.lifecycle.api.Configurable;
 import org.apache.james.mailbox.MailboxListener;
@@ -56,6 +57,7 @@ public class MailboxListenersLoaderImpl implements Configurable, MailboxListener
         ListenersConfiguration listenersConfiguration = ListenersConfiguration.from(configuration);
 
         guiceDefinedListeners.forEach(this::register);
+
         listenersConfiguration.getListenersConfiguration().stream()
             .map(this::createListener)
             .forEach(this::register);
@@ -78,8 +80,11 @@ public class MailboxListenersLoaderImpl implements Configurable, MailboxListener
             LOGGER.info("Loading user registered mailbox listener {}", listenerClass);
             Class<MailboxListener> clazz = classLoader.locateClass(listenerClass);
             MailboxListener listener = mailboxListenerFactory.createInstance(clazz);
+            if (listener instanceof Configurable && configuration.getConfiguration().isPresent()) {
+                ((Configurable)listener).configure(configuration.getConfiguration().get());
+            }
             return listener;
-        } catch (ClassNotFoundException e) {
+        } catch (ClassNotFoundException | ConfigurationException e) {
             LOGGER.error("Error while loading user registered global listener {}", listenerClass, e);
             throw new RuntimeException(e);
         }

http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/container/guice/mailbox/src/test/java/org/apache/james/modules/mailbox/MailboxListenersLoaderImplTest.java
----------------------------------------------------------------------
diff --git a/server/container/guice/mailbox/src/test/java/org/apache/james/modules/mailbox/MailboxListenersLoaderImplTest.java b/server/container/guice/mailbox/src/test/java/org/apache/james/modules/mailbox/MailboxListenersLoaderImplTest.java
index aeff77d..c592907 100644
--- a/server/container/guice/mailbox/src/test/java/org/apache/james/modules/mailbox/MailboxListenersLoaderImplTest.java
+++ b/server/container/guice/mailbox/src/test/java/org/apache/james/modules/mailbox/MailboxListenersLoaderImplTest.java
@@ -58,7 +58,7 @@ public class MailboxListenersLoaderImplTest {
 
     @Test
     public void createListenerShouldThrowWhenClassCantBeLoaded() {
-        ListenerConfiguration configuration = new ListenerConfiguration("MyUnknownClass");
+        ListenerConfiguration configuration = ListenerConfiguration.forClass("MyUnknownClass");
 
         assertThatThrownBy(() -> testee.createListener(configuration))
             .isInstanceOf(RuntimeException.class);
@@ -66,7 +66,7 @@ public class MailboxListenersLoaderImplTest {
 
     @Test
     public void createListenerShouldThrowWhenClassCantBeCastToMailboxListener() {
-        ListenerConfiguration configuration = new ListenerConfiguration("java.lang.String");
+        ListenerConfiguration configuration = ListenerConfiguration.forClass("java.lang.String");
 
         assertThatThrownBy(() -> testee.createListener(configuration))
             .isInstanceOf(RuntimeException.class);
@@ -74,7 +74,7 @@ public class MailboxListenersLoaderImplTest {
 
     @Test
     public void createListenerShouldThrowWhenNotFullClassName() {
-        ListenerConfiguration configuration = new ListenerConfiguration("NoopMailboxListener");
+        ListenerConfiguration configuration = ListenerConfiguration.forClass("NoopMailboxListener");
 
         assertThatThrownBy(() -> testee.createListener(configuration))
             .isInstanceOf(RuntimeException.class);
@@ -82,7 +82,7 @@ public class MailboxListenersLoaderImplTest {
 
     @Test
     public void createListenerShouldReturnMailboxListenerWhenConfigurationIsGood() {
-        ListenerConfiguration configuration = new ListenerConfiguration("org.apache.james.modules.mailbox.NoopMailboxListener");
+        ListenerConfiguration configuration = ListenerConfiguration.forClass("org.apache.james.modules.mailbox.NoopMailboxListener");
 
         MailboxListener listener = testee.createListener(configuration);
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/container/guice/memory-guice/pom.xml
----------------------------------------------------------------------
diff --git a/server/container/guice/memory-guice/pom.xml b/server/container/guice/memory-guice/pom.xml
index a62830e..be1e5a3 100644
--- a/server/container/guice/memory-guice/pom.xml
+++ b/server/container/guice/memory-guice/pom.xml
@@ -41,6 +41,10 @@
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
+            <artifactId>apache-james-mailbox-quota-mailing</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
             <artifactId>apache-james-mailbox-scanning-search</artifactId>
             <type>test-jar</type>
         </dependency>
@@ -92,10 +96,6 @@
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
-            <artifactId>james-server-guice-mailbox-plugin-quota-mailing</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>${project.groupId}</groupId>
             <artifactId>james-server-guice-mailbox-plugin-spamassassin</artifactId>
         </dependency>
         <dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java
----------------------------------------------------------------------
diff --git a/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java b/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java
index 30df53c..99783fd 100644
--- a/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java
+++ b/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java
@@ -25,7 +25,6 @@ import org.apache.james.modules.data.MemoryDataJmapModule;
 import org.apache.james.modules.data.MemoryDataModule;
 import org.apache.james.modules.eventstore.MemoryEventStoreModule;
 import org.apache.james.modules.mailbox.MemoryMailboxModule;
-import org.apache.james.modules.mailbox.QuotaMailingModule;
 import org.apache.james.modules.protocols.IMAPServerModule;
 import org.apache.james.modules.protocols.JMAPServerModule;
 import org.apache.james.modules.protocols.LMTPServerModule;
@@ -68,9 +67,6 @@ public class MemoryJamesServerMain {
         new SMTPServerModule(),
         new SpamAssassinListenerModule());
 
-    public static final Module PLUGINS = Modules.combine(
-        new QuotaMailingModule());
-
     public static final Module JMAP = Modules.combine(
         new MemoryDataJmapModule(),
         new JMAPServerModule());
@@ -99,8 +95,7 @@ public class MemoryJamesServerMain {
         IN_MEMORY_SERVER_MODULE,
         PROTOCOLS,
         JMAP,
-        WEBADMIN,
-        PLUGINS);
+        WEBADMIN);
 
     public static void main(String[] args) throws Exception {
         Configuration configuration = Configuration.builder().useWorkingDirectoryEnvProperty().build();

http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/container/guice/pom.xml
----------------------------------------------------------------------
diff --git a/server/container/guice/pom.xml b/server/container/guice/pom.xml
index 2bdaf1f..ab62bb7 100644
--- a/server/container/guice/pom.xml
+++ b/server/container/guice/pom.xml
@@ -45,7 +45,6 @@
         <module>jpa-guice</module>
         <module>jpa-smtp</module>
         <module>mailbox</module>
-        <module>mailbox-plugin-quota-mailing</module>
         <module>mailbox-plugin-spamassassin</module>
         <module>mailet</module>
         <module>memory-guice</module>
@@ -111,11 +110,6 @@
             </dependency>
             <dependency>
                 <groupId>${project.groupId}</groupId>
-                <artifactId>james-server-guice-mailbox-plugin-quota-mailing</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
                 <artifactId>james-server-guice-mailbox-plugin-spamassassin</artifactId>
                 <version>${project.version}</version>
             </dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/resources/listeners.xml
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/resources/listeners.xml b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/resources/listeners.xml
index 35cb6b5..8c82680 100644
--- a/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/resources/listeners.xml
+++ b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/resources/listeners.xml
@@ -27,5 +27,10 @@
   </listener>
   <listener>
     <class>org.apache.james.mailbox.quota.mailing.listeners.QuotaThresholdCrossingListener</class>
+    <configuration>
+      <thresholds>
+        <threshold>0.1</threshold>
+      </thresholds>
+    </configuration>
   </listener>
 </listeners>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/QuotaMailingTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/QuotaMailingTest.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/QuotaMailingTest.java
index 93be0a1..ec5d65a 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/QuotaMailingTest.java
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/QuotaMailingTest.java
@@ -29,6 +29,7 @@ import static org.apache.james.jmap.TestingConstants.ARGUMENTS;
 import static org.apache.james.jmap.TestingConstants.DOMAIN;
 import static org.apache.james.jmap.TestingConstants.calmlyAwait;
 import static org.apache.james.jmap.TestingConstants.jmapRequestSpecBuilder;
+import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.hasItem;
 
 import java.io.IOException;
@@ -94,8 +95,7 @@ public abstract class QuotaMailingTest {
                 new SerializableQuotaValue<>(QuotaSize.size(100 * 1000)));
 
         bartSendMessageToHomer();
-        // Homer receives a 83.995 Bytes mail, triggering the 0.80 threshold mailing
-
+        // Homer receives a mail big enough to trigger a configured threshold
         calmlyAwait.atMost(30, TimeUnit.SECONDS)
             .until(() -> listMessageIdsForAccount(homerAccessToken).size() == 2);
 
@@ -116,10 +116,39 @@ public abstract class QuotaMailingTest {
                 hasItem("Warning: Your email usage just exceeded a configured threshold"));
     }
 
+    @Test
+    public void configurationShouldBeWellLoaded() throws Exception {
+        jmapServer.getProbe(QuotaProbesImpl.class)
+            .setMaxStorage(MailboxConstants.USER_NAMESPACE + "&" + HOMER,
+                new SerializableQuotaValue<>(QuotaSize.size(100 * 1000)));
+
+        bartSendMessageToHomer();
+        // Home receives a mail big enough to trigger a configured threshold
+
+        calmlyAwait.atMost(30, TimeUnit.SECONDS)
+            .until(() -> listMessageIdsForAccount(homerAccessToken).size() == 2);
+
+        List<String> ids = listMessageIdsForAccount(homerAccessToken);
+        String idString = ids.stream()
+            .map(id -> "\"" + id + "\"")
+            .collect(Collectors.joining(","));
+
+        given()
+            .header("Authorization", homerAccessToken.serialize())
+            .body("[[\"getMessages\", {\"ids\": [" + idString + "]}, \"#0\"]]")
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .log().ifValidationFails()
+            .body(ARGUMENTS + ".list.textBody",
+                hasItem(containsString("You currently occupy more than 10 % of the total size allocated to you")));
+    }
+
     private void bartSendMessageToHomer() {
         String messageCreationId = "creationId";
         String outboxId = getOutboxId(bartAccessToken);
-        String eightyKBBody = Strings.repeat("123456789\n", 80 * 100);
+        String bigEnoughBody = Strings.repeat("123456789\n", 12 * 100);
         String requestBody = "[" +
             "  [" +
             "    \"setMessages\"," +
@@ -129,7 +158,7 @@ public abstract class QuotaMailingTest {
             "        \"from\": { \"name\": \"Bob\", \"email\": \"" + BART + "\"}," +
             "        \"to\": [{ \"name\": \"User\", \"email\": \"" + HOMER + "\"}]," +
             "        \"subject\": \"Message without an attachment\"," +
-            "        \"textBody\": \"" + eightyKBBody + "\"," +
+            "        \"textBody\": \"" + bigEnoughBody + "\"," +
             "        \"htmlBody\": \"Test <b>body</b>, HTML version\"," +
             "        \"mailboxIds\": [\"" + outboxId + "\"] " +
             "      }}" +

http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/listeners.xml
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/listeners.xml b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/listeners.xml
index f658226..47a3381 100644
--- a/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/listeners.xml
+++ b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/listeners.xml
@@ -24,5 +24,10 @@
   </listener>
   <listener>
     <class>org.apache.james.mailbox.quota.mailing.listeners.QuotaThresholdCrossingListener</class>
+    <configuration>
+      <thresholds>
+        <threshold>0.1</threshold>
+      </thresholds>
+    </configuration>
   </listener>
 </listeners>
\ No newline at end of file


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


[7/8] james-project git commit: MAILBOX-335 Cassandra specific test for chunking

Posted by ma...@apache.org.
MAILBOX-335 Cassandra specific test for chunking


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

Branch: refs/heads/master
Commit: e9cc5022ba233aca9b1255e160160cbeca050a40
Parents: 6052de6
Author: benwa <bt...@linagora.com>
Authored: Tue May 22 09:45:51 2018 +0700
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue May 22 10:04:13 2018 +0200

----------------------------------------------------------------------
 ...estCassandraMailboxSessionMapperFactory.java | 27 ++++++++-----
 .../mail/CassandraMessageIdMapperTest.java      | 40 +++++++++++++++++++-
 .../store/mail/model/MessageIdMapperTest.java   | 16 ++++----
 3 files changed, 65 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/e9cc5022/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/TestCassandraMailboxSessionMapperFactory.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/TestCassandraMailboxSessionMapperFactory.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/TestCassandraMailboxSessionMapperFactory.java
index 3afdf36..ec7ac05 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/TestCassandraMailboxSessionMapperFactory.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/TestCassandraMailboxSessionMapperFactory.java
@@ -47,15 +47,24 @@ import org.apache.james.mailbox.cassandra.mail.CassandraUserMailboxRightsDAO;
 import com.datastax.driver.core.Session;
 
 public class TestCassandraMailboxSessionMapperFactory {
+
     public static CassandraMailboxSessionMapperFactory forTests(Session session, CassandraTypesProvider typesProvider,
                                                                 CassandraMessageId.Factory factory) {
+        return forTests(session, typesProvider, factory, CassandraConfiguration.DEFAULT_CONFIGURATION);
+    }
+
+    public static CassandraMailboxSessionMapperFactory forTests(Session session, CassandraTypesProvider typesProvider,
+                                                                CassandraMessageId.Factory factory, CassandraConfiguration cassandraConfiguration) {
+
+        CassandraUtils utils = new CassandraUtils(cassandraConfiguration);
         CassandraBlobsDAO cassandraBlobsDAO = new CassandraBlobsDAO(session);
         CassandraBlobId.Factory blobIdFactory = new CassandraBlobId.Factory();
+
         return new CassandraMailboxSessionMapperFactory(
             new CassandraUidProvider(session),
             new CassandraModSeqProvider(session),
             session,
-            new CassandraMessageDAO(session, typesProvider, cassandraBlobsDAO, blobIdFactory, CassandraUtils.WITH_DEFAULT_CONFIGURATION, factory),
+            new CassandraMessageDAO(session, typesProvider, cassandraBlobsDAO, blobIdFactory, utils, factory),
             new CassandraMessageIdDAO(session, factory),
             new CassandraMessageIdToImapUidDAO(session, factory),
             new CassandraMailboxCounterDAO(session),
@@ -64,17 +73,17 @@ public class TestCassandraMailboxSessionMapperFactory {
             new CassandraMailboxPathDAO(session, typesProvider),
             new CassandraFirstUnseenDAO(session),
             new CassandraApplicableFlagDAO(session),
-            new CassandraAttachmentDAO(session, CassandraUtils.WITH_DEFAULT_CONFIGURATION, CassandraConfiguration.DEFAULT_CONFIGURATION),
+            new CassandraAttachmentDAO(session, utils, cassandraConfiguration),
             new CassandraAttachmentDAOV2(blobIdFactory, session),
             new CassandraDeletedMessageDAO(session),
-            cassandraBlobsDAO, new CassandraAttachmentMessageIdDAO(session, factory, CassandraUtils.WITH_DEFAULT_CONFIGURATION),
-            new CassandraAttachmentOwnerDAO(session, CassandraUtils.WITH_DEFAULT_CONFIGURATION),
+            cassandraBlobsDAO, new CassandraAttachmentMessageIdDAO(session, factory, utils),
+            new CassandraAttachmentOwnerDAO(session, utils),
             new CassandraACLMapper(session,
-                new CassandraUserMailboxRightsDAO(session, CassandraUtils.WITH_DEFAULT_CONFIGURATION),
-                CassandraConfiguration.DEFAULT_CONFIGURATION),
-            new CassandraUserMailboxRightsDAO(session, CassandraUtils.WITH_DEFAULT_CONFIGURATION),
-            CassandraUtils.WITH_DEFAULT_CONFIGURATION,
-            CassandraConfiguration.DEFAULT_CONFIGURATION);
+                new CassandraUserMailboxRightsDAO(session, utils),
+                cassandraConfiguration),
+            new CassandraUserMailboxRightsDAO(session, utils),
+            utils,
+            cassandraConfiguration);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/e9cc5022/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapperTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapperTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapperTest.java
index bc7f9b4..d6d0f65 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapperTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapperTest.java
@@ -19,10 +19,18 @@
 
 package org.apache.james.mailbox.cassandra.mail;
 
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.List;
+
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.DockerCassandraRule;
+import org.apache.james.backends.cassandra.init.CassandraConfiguration;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
 import org.apache.james.blob.cassandra.CassandraBlobModule;
+import org.apache.james.mailbox.cassandra.CassandraMailboxSessionMapperFactory;
+import org.apache.james.mailbox.cassandra.TestCassandraMailboxSessionMapperFactory;
+import org.apache.james.mailbox.cassandra.ids.CassandraMessageId;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule;
@@ -36,13 +44,20 @@ import org.apache.james.mailbox.cassandra.modules.CassandraMessageModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraModSeqModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraUidModule;
 import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.mock.MockMailboxSession;
+import org.apache.james.mailbox.store.mail.MessageMapper;
+import org.apache.james.mailbox.store.mail.model.MailboxMessage;
 import org.apache.james.mailbox.store.mail.model.MessageIdMapperTest;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.ClassRule;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableList;
 
 public class CassandraMessageIdMapperTest extends MessageIdMapperTest {
-    
+
+    public static final MockMailboxSession MAILBOX_SESSION = new MockMailboxSession("benwa");
     @ClassRule public static DockerCassandraRule cassandraServer = new DockerCassandraRule();
     
     private CassandraCluster cassandra;
@@ -77,4 +92,27 @@ public class CassandraMessageIdMapperTest extends MessageIdMapperTest {
     protected CassandraMapperProvider provideMapper() {
         return new CassandraMapperProvider(cassandra);
     }
+
+    @Test
+    public void findShouldReturnCorrectElementsWhenChunking() throws Exception {
+        CassandraMessageId.Factory messageIdFactory = new CassandraMessageId.Factory();
+        CassandraMailboxSessionMapperFactory mapperFactory = TestCassandraMailboxSessionMapperFactory.forTests(
+            cassandra.getConf(), cassandra.getTypesProvider(), messageIdFactory,
+            CassandraConfiguration.builder()
+                .messageReadChunkSize(3)
+                .build());
+
+        saveMessages();
+
+        List<MailboxMessage> messages = mapperFactory.getMessageIdMapper(MAILBOX_SESSION)
+            .find(
+                ImmutableList.of(message1.getMessageId(),
+                    message2.getMessageId(),
+                    message3.getMessageId(),
+                    message4.getMessageId()),
+                MessageMapper.FetchType.Metadata);
+
+        assertThat(messages)
+            .containsOnly(message1, message2, message3, message4);
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/e9cc5022/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java
index 676e1bb..054c44a 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java
@@ -61,19 +61,19 @@ public abstract class MessageIdMapperTest {
 
     private static final char DELIMITER = '.';
     private static final int BODY_START = 16;
-    private static final long UID_VALIDITY = 42;
+    protected static final long UID_VALIDITY = 42;
 
     private MessageMapper messageMapper;
     private MailboxMapper mailboxMapper;
     private MessageIdMapper sut;
 
-    private SimpleMailbox benwaInboxMailbox;
-    private SimpleMailbox benwaWorkMailbox;
+    protected SimpleMailbox benwaInboxMailbox;
+    protected SimpleMailbox benwaWorkMailbox;
     
-    private SimpleMailboxMessage message1;
-    private SimpleMailboxMessage message2;
-    private SimpleMailboxMessage message3;
-    private SimpleMailboxMessage message4;
+    protected SimpleMailboxMessage message1;
+    protected SimpleMailboxMessage message2;
+    protected SimpleMailboxMessage message3;
+    protected SimpleMailboxMessage message4;
 
     @Rule
     public ExpectedException expected = ExpectedException.none();
@@ -887,7 +887,7 @@ public abstract class MessageIdMapperTest {
         return mailbox;
     }
     
-    private void saveMessages() throws MailboxException {
+    protected void saveMessages() throws MailboxException {
         addMessageAndSetModSeq(benwaInboxMailbox, message1);
         addMessageAndSetModSeq(benwaInboxMailbox, message2);
         addMessageAndSetModSeq(benwaInboxMailbox, message3);


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


[6/8] james-project git commit: MAILBOX-335 Chuncks for CassandraMessageIdMapper::find

Posted by ma...@apache.org.
MAILBOX-335 Chuncks for CassandraMessageIdMapper::find


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

Branch: refs/heads/master
Commit: 6052de67601317f85e0ec5e282ec99fef42517c8
Parents: 92a1567
Author: benwa <bt...@linagora.com>
Authored: Wed May 16 12:47:04 2018 +0700
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue May 22 10:04:13 2018 +0200

----------------------------------------------------------------------
 .../james/mailbox/cassandra/mail/CassandraMessageIdMapper.java  | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/6052de67/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java
index ef039c6..4db9185 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java
@@ -50,6 +50,7 @@ import org.apache.james.mailbox.store.mail.ModSeqProvider;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
 import org.apache.james.mailbox.store.mail.model.impl.SimpleMailboxMessage;
 import org.apache.james.util.FluentFutureStream;
+import org.apache.james.util.streams.JamesCollectors;
 import org.apache.james.util.streams.Limit;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -90,7 +91,9 @@ public class CassandraMessageIdMapper implements MessageIdMapper {
 
     @Override
     public List<MailboxMessage> find(Collection<MessageId> messageIds, FetchType fetchType) {
-        return findAsStream(messageIds, fetchType)
+        return messageIds.stream()
+            .collect(JamesCollectors.chunker(cassandraConfiguration.getMessageReadChunkSize()))
+            .flatMap(chuckedIds -> findAsStream(messageIds, fetchType))
             .collect(Guavate.toImmutableList());
     }
 


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


[5/8] james-project git commit: Merge branch 'JAMES-2399'

Posted by ma...@apache.org.
Merge branch 'JAMES-2399'


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

Branch: refs/heads/master
Commit: 956c0983cf93cc5b70921caf93a6e78cd3280288
Parents: aeb1f14 8e5f2cc
Author: Matthieu Baechler <ma...@apache.org>
Authored: Tue May 22 10:02:50 2018 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue May 22 10:02:50 2018 +0200

----------------------------------------------------------------------
 .../dto/QuotaThresholdChangedEventDTO.java      |  15 +-
 .../mailbox/quota/cassandra/dto/DTOTest.java    |   9 +-
 .../src/test/resources/json/event.json          |   2 +-
 .../src/test/resources/json/event2.json         |   2 +-
 .../src/test/resources/json/event3.json         |   2 +-
 .../src/test/resources/json/event4.json         |   2 +-
 mailbox/plugin/quota-mailing/pom.xml            |  30 +--
 .../QuotaMailingListenerConfiguration.java      | 100 +++++++++-
 .../mailing/aggregates/UserQuotaThresholds.java |  43 ++++-
 .../DetectThresholdCrossingHandler.java         |   4 +-
 .../QuotaThresholdCrossingListener.java         |  40 +++-
 .../mailbox/quota/model/QuotaThresholds.java    |  16 ++
 .../QuotaMailingListenerConfigurationTest.java  | 181 +++++++++++++++++++
 .../aggregates/UserQuotaThresholdsTest.java     |  43 ++++-
 .../QuotaThresholdListenersTestSystem.java      |   4 +-
 .../quota/model/QuotaThresholdsTest.java        |   9 +
 server/container/guice/cassandra-guice/pom.xml  |   4 -
 .../mailbox/CassandraQuotaMailingModule.java    |   2 -
 .../org/apache/james/CassandraJmapTestRule.java |   5 +-
 .../guice/mailbox-plugin-quota-mailing/pom.xml  |  45 -----
 .../modules/mailbox/QuotaMailingModule.java     |  41 -----
 .../modules/mailbox/ListenerConfiguration.java  |  23 ++-
 .../mailbox/MailboxListenersLoaderImpl.java     |   7 +-
 .../mailbox/MailboxListenersLoaderImplTest.java |   8 +-
 server/container/guice/memory-guice/pom.xml     |   8 +-
 .../org/apache/james/MemoryJamesServerMain.java |   7 +-
 .../org/apache/james/MemoryJmapTestRule.java    |   8 +-
 server/container/guice/pom.xml                  |   6 -
 .../org/apache/james/util/TimeConverter.java    |  74 ++++----
 .../apache/james/util/TimeConverterTest.java    |  20 ++
 .../CassandraGetMessageListMethodTest.java      |   4 +-
 .../src/test/resources/listeners.xml            |  15 ++
 .../integration/GetMessageListMethodTest.java   |   1 +
 .../methods/integration/QuotaMailingTest.java   |  48 ++++-
 .../memory/MemoryGetMessageListMethodTest.java  |   3 +-
 .../src/test/resources/listeners.xml            |  15 ++
 36 files changed, 633 insertions(+), 213 deletions(-)
----------------------------------------------------------------------



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


[3/8] james-project git commit: JAMES-2399 Allow TimeConverter to specify a default Unit

Posted by ma...@apache.org.
JAMES-2399 Allow TimeConverter to specify a default Unit

Before this was always MS


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

Branch: refs/heads/master
Commit: cc4fb690ced9eed460e855129c4dd1347bfbb6f9
Parents: 92a1567
Author: benwa <bt...@linagora.com>
Authored: Thu May 17 15:17:49 2018 +0700
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue May 22 10:02:27 2018 +0200

----------------------------------------------------------------------
 .../org/apache/james/util/TimeConverter.java    | 74 +++++++++++---------
 .../apache/james/util/TimeConverterTest.java    | 20 ++++++
 2 files changed, 61 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/cc4fb690/server/container/util/src/main/java/org/apache/james/util/TimeConverter.java
----------------------------------------------------------------------
diff --git a/server/container/util/src/main/java/org/apache/james/util/TimeConverter.java b/server/container/util/src/main/java/org/apache/james/util/TimeConverter.java
index dbc68fe..6927802 100644
--- a/server/container/util/src/main/java/org/apache/james/util/TimeConverter.java
+++ b/server/container/util/src/main/java/org/apache/james/util/TimeConverter.java
@@ -18,39 +18,42 @@
  ****************************************************************/
 package org.apache.james.util;
 
-import java.util.HashMap;
+import java.util.Arrays;
+import java.util.List;
 import java.util.Locale;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-public class TimeConverter {
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
 
-    private static final HashMap<String, Integer> multipliers = new HashMap<>(10);
+public class TimeConverter {
 
     private static final String PATTERN_STRING = "\\s*([0-9]+)\\s*([a-z,A-Z]*)\\s*";
 
-    private static Pattern PATTERN = null;
-
-    static {
-        // add allowed units and their respective multiplier
-        multipliers.put("", 1);
-        multipliers.put("ms", 1);
-        multipliers.put("msec", 1);
-        multipliers.put("msecs", 1);
-        multipliers.put("s", 1000);
-        multipliers.put("sec", 1000);
-        multipliers.put("secs", 1000);
-        multipliers.put("m", 1000 * 60);
-        multipliers.put("minute", 1000 * 60);
-        multipliers.put("minutes", 1000 * 60);
-        multipliers.put("h", 1000 * 60 * 60);
-        multipliers.put("hour", 1000 * 60 * 60);
-        multipliers.put("hours", 1000 * 60 * 60);
-        multipliers.put("d", 1000 * 60 * 60 * 24);
-        multipliers.put("day", 1000 * 60 * 60 * 24);
-        multipliers.put("days", 1000 * 60 * 60 * 24);
-
-        PATTERN = Pattern.compile(PATTERN_STRING);
+    private static Pattern PATTERN = Pattern.compile(PATTERN_STRING);
+
+    public enum Unit {
+        MILLI_SECONDS(ImmutableList.of("ms", "msec", "msecs"), 1),
+        SECONDS(ImmutableList.of("s", "sec", "secs"), 1000),
+        MINUTES(ImmutableList.of("m", "min", "mins", "minute", "minutes"), 1000 * 60),
+        HOURS(ImmutableList.of("h", "hour", "hours"), 1000 * 60 * 60),
+        DAYS(ImmutableList.of("d", "day", "days"), 1000 * 60 * 60 * 24);
+
+        public static Unit parse(String string) {
+            return Arrays.stream(values())
+                .filter(value -> value.validPatterns.contains(string.toLowerCase(Locale.US)))
+                .findFirst()
+                .orElseThrow(() -> new NumberFormatException("Unknown unit: " + string));
+        }
+
+        private final List<String> validPatterns;
+        private final int multiplier;
+
+        Unit(List<String> validPatterns, int multiplier) {
+            this.validPatterns = validPatterns;
+            this.multiplier = multiplier;
+        }
 
     }
 
@@ -70,11 +73,11 @@ public class TimeConverter {
      *             Get thrown if an illegal unit was used
      */
     public static long getMilliSeconds(long amount, String unit) throws NumberFormatException {
-        Object multiplierObject = multipliers.get(unit.toLowerCase(Locale.US));
-        if (multiplierObject == null) {
-            throw new NumberFormatException("Unknown unit: " + unit);
-        }
-        int multiplier = (Integer) multiplierObject;
+        return getMilliSeconds(amount, Unit.parse(unit));
+    }
+
+    public static long getMilliSeconds(long amount, Unit unit) throws NumberFormatException {
+        int multiplier = unit.multiplier;
         return (amount * multiplier);
     }
 
@@ -89,16 +92,21 @@ public class TimeConverter {
      *             Get thrown if an illegal rawString was used
      */
     public static long getMilliSeconds(String rawString) throws NumberFormatException {
-        PATTERN = Pattern.compile(PATTERN_STRING);
+        return getMilliSeconds(rawString, Unit.MILLI_SECONDS);
+    }
+
+    public static long getMilliSeconds(String rawString, Unit defaultUnit) throws NumberFormatException {
         Matcher res = PATTERN.matcher(rawString);
         if (res.matches()) {
 
             if (res.group(1) != null && res.group(2) != null) {
                 long time = Integer.parseInt(res.group(1).trim());
                 String unit = res.group(2);
-                return getMilliSeconds(time, unit);
+                if (Strings.isNullOrEmpty(unit)) {
+                    return getMilliSeconds(time, defaultUnit);
+                }
+                return getMilliSeconds(time, Unit.parse(unit));
             } else {
-
                 // This should never Happen anyway throw an exception
                 throw new NumberFormatException("The supplied String is not a supported format " + rawString);
             }

http://git-wip-us.apache.org/repos/asf/james-project/blob/cc4fb690/server/container/util/src/test/java/org/apache/james/util/TimeConverterTest.java
----------------------------------------------------------------------
diff --git a/server/container/util/src/test/java/org/apache/james/util/TimeConverterTest.java b/server/container/util/src/test/java/org/apache/james/util/TimeConverterTest.java
index fc13f58..9c52e11 100644
--- a/server/container/util/src/test/java/org/apache/james/util/TimeConverterTest.java
+++ b/server/container/util/src/test/java/org/apache/james/util/TimeConverterTest.java
@@ -36,6 +36,26 @@ public class TimeConverterTest {
         assertThat(actual).isEqualTo(expected);
     }
 
+    @Test
+    public void getMilliSecondsShouldUseProvidedUnitWhenNoUnitAmountAsString() {
+        //Given
+        long expected = 2;
+        //When
+        long actual = TimeConverter.getMilliSeconds("2", TimeConverter.Unit.SECONDS);
+        //Then
+        assertThat(actual).isEqualTo(2000);
+    }
+
+    @Test
+    public void getMilliSecondsShouldNotUseProvidedUnitWhenNoUnitAmountAsString() {
+        //Given
+        long expected = 2;
+        //When
+        long actual = TimeConverter.getMilliSeconds("2 minutes", TimeConverter.Unit.SECONDS);
+        //Then
+        assertThat(actual).isEqualTo(120000);
+    }
+
     @Test 
     public void getMilliSecondsShouldConvertValueWhenMsecUnit() {
         //Given


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