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 <[email protected]>
Authored: Thu May 17 16:30:26 2018 +0200
Committer: Matthieu Baechler <[email protected]>
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("[email protected]")));
+        UserQuotaThresholds.Id.from(User.fromUsername("[email protected]"), 
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("[email protected]")));
+        UserQuotaThresholds.Id.from(User.fromUsername("[email protected]"), 
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("[email protected]")));
+        UserQuotaThresholds.Id.from(User.fromUsername("[email protected]"), 
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("[email protected]")));
+        UserQuotaThresholds.Id.from(User.fromUsername("[email protected]"), 
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": "[email protected]",
+ "aggregateId":"QuotaThreasholdEvents/default/[email protected]",
  "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":"[email protected]",
+  "aggregateId":"QuotaThreasholdEvents/default/[email protected]",
   "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":"[email protected]",
+  "aggregateId":"QuotaThreasholdEvents/default/[email protected]",
   "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":"[email protected]",
+  "aggregateId":"QuotaThreasholdEvents/default/[email protected]",
   "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: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to