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 bt...@apache.org on 2019/08/26 02:07:46 UTC

[james-project] 12/14: JAMES-2856 Fix QuotaRoot serialization

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

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

commit 90f2f41a52195b800450b6a437cc2d051ea274cd
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri Aug 16 12:57:48 2019 +0700

    JAMES-2856 Fix QuotaRoot serialization
    
    Mailbox event serialization relies on their own logic for quotaRoot deserialization,
    which is duplicated from the standard one, and buggy (no management for domain)
    
    We need to have mailbox event serialization reusing logic for quotaRoot deserialization.
    
    That being said, the QuotaRootResolver, encapsulating this logic, comes with too much dependencies,
    and thus is not convenient for testing. That's why we split the deserializer away from the resolver
    (no dependencies)
    
    Feature relying on this is limited to quotaSearch domainFiltering on top of distributed James product.
---
 .../mailbox/quota/QuotaRootDeserializer.java}      | 15 ++++------
 .../james/mailbox/quota/QuotaRootResolver.java     |  4 +--
 .../events/CassandraEventDeadLettersDAOTest.java   |  3 +-
 .../events/CassandraEventDeadLettersTest.java      |  3 +-
 mailbox/event/event-rabbitmq/pom.xml               |  5 ++++
 .../james/mailbox/events/RabbitMQEventBusTest.java |  3 +-
 mailbox/event/json/pom.xml                         |  5 ++++
 .../apache/james/event/json/EventSerializer.scala  | 13 ++++----
 .../json/MailboxDeletionSerializationTest.java     | 19 ++++++------
 .../QuotaUsageUpdatedEventSerializationTest.java   | 14 ++++-----
 .../apache/james/event/json/SerializerFixture.java |  5 ++--
 .../james/event/json/dtos/QuotaRootTest.java       | 15 ++++++----
 .../store/quota/DefaultUserQuotaRootResolver.java  | 35 ++++++++++++++--------
 .../rabbitmq/host/RabbitMQEventBusHostSystem.java  |  3 +-
 .../modules/mailbox/CassandraQuotaModule.java      |  2 ++
 .../james/modules/mailbox/JpaQuotaModule.java      |  2 ++
 .../james/modules/mailbox/DefaultQuotaModule.java  |  2 ++
 .../james/modules/mailbox/MemoryQuotaModule.java   |  2 ++
 .../routes/EventDeadLettersRoutesTest.java         |  3 +-
 19 files changed, 92 insertions(+), 61 deletions(-)

diff --git a/mailbox/event/json/src/test/java/org/apache/james/event/json/SerializerFixture.java b/mailbox/api/src/main/java/org/apache/james/mailbox/quota/QuotaRootDeserializer.java
similarity index 67%
copy from mailbox/event/json/src/test/java/org/apache/james/event/json/SerializerFixture.java
copy to mailbox/api/src/main/java/org/apache/james/mailbox/quota/QuotaRootDeserializer.java
index 3cf904a..2e35d50 100644
--- a/mailbox/event/json/src/test/java/org/apache/james/event/json/SerializerFixture.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/quota/QuotaRootDeserializer.java
@@ -17,16 +17,11 @@
  * under the License.                                           *
  ****************************************************************/
 
-package org.apache.james.event.json;
+package org.apache.james.mailbox.quota;
 
-import org.apache.james.mailbox.events.Event;
-import org.apache.james.mailbox.model.TestId;
-import org.apache.james.mailbox.model.TestMessageId;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.QuotaRoot;
 
-public interface SerializerFixture {
-    JsonSerialize DTO_JSON_SERIALIZE = new JsonSerialize(new TestId.Factory(), new TestMessageId.Factory());
-    EventSerializer EVENT_SERIALIZER = new EventSerializer(new TestId.Factory(), new TestMessageId.Factory());
-
-    String SERIALIZED_EVENT_ID = "6e0dd59d-660e-4d9b-b22f-0354479f47b4";
-    Event.EventId EVENT_ID = Event.EventId.of(SERIALIZED_EVENT_ID);
+public interface QuotaRootDeserializer {
+    QuotaRoot fromString(String serializedQuotaRoot) throws MailboxException;
 }
diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/quota/QuotaRootResolver.java b/mailbox/api/src/main/java/org/apache/james/mailbox/quota/QuotaRootResolver.java
index 6adff1e..3bd3c01 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/quota/QuotaRootResolver.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/quota/QuotaRootResolver.java
@@ -27,7 +27,7 @@ import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.QuotaRoot;
 
-public interface QuotaRootResolver {
+public interface QuotaRootResolver extends QuotaRootDeserializer {
 
     /**
      * Return the quotaRoot associated with the given mailbox name.
@@ -40,7 +40,5 @@ public interface QuotaRootResolver {
 
     QuotaRoot getQuotaRoot(MailboxId mailboxId) throws MailboxException;
 
-    QuotaRoot fromString(String serializedQuotaRoot) throws MailboxException;
-
     List<MailboxPath> retrieveAssociatedMailboxes(QuotaRoot quotaRoot, MailboxSession mailboxSession) throws MailboxException;
 }
diff --git a/mailbox/event/event-cassandra/src/test/java/org/apache/james/mailbox/events/CassandraEventDeadLettersDAOTest.java b/mailbox/event/event-cassandra/src/test/java/org/apache/james/mailbox/events/CassandraEventDeadLettersDAOTest.java
index 2fba1d8..729c671 100644
--- a/mailbox/event/event-cassandra/src/test/java/org/apache/james/mailbox/events/CassandraEventDeadLettersDAOTest.java
+++ b/mailbox/event/event-cassandra/src/test/java/org/apache/james/mailbox/events/CassandraEventDeadLettersDAOTest.java
@@ -34,6 +34,7 @@ import org.apache.james.backends.cassandra.CassandraClusterExtension;
 import org.apache.james.event.json.EventSerializer;
 import org.apache.james.mailbox.model.TestId;
 import org.apache.james.mailbox.model.TestMessageId;
+import org.apache.james.mailbox.store.quota.DefaultUserQuotaRootResolver;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
@@ -47,7 +48,7 @@ class CassandraEventDeadLettersDAOTest {
 
     @BeforeEach
     void setUp(CassandraCluster cassandraCluster) {
-        EventSerializer eventSerializer = new EventSerializer(new TestId.Factory(), new TestMessageId.Factory());
+        EventSerializer eventSerializer = new EventSerializer(new TestId.Factory(), new TestMessageId.Factory(), new DefaultUserQuotaRootResolver.DefaultQuotaRootDeserializer());
         cassandraEventDeadLettersDAO = new CassandraEventDeadLettersDAO(cassandraCluster.getConf(), eventSerializer);
     }
 
diff --git a/mailbox/event/event-cassandra/src/test/java/org/apache/james/mailbox/events/CassandraEventDeadLettersTest.java b/mailbox/event/event-cassandra/src/test/java/org/apache/james/mailbox/events/CassandraEventDeadLettersTest.java
index 20810d3..fce1ee7 100644
--- a/mailbox/event/event-cassandra/src/test/java/org/apache/james/mailbox/events/CassandraEventDeadLettersTest.java
+++ b/mailbox/event/event-cassandra/src/test/java/org/apache/james/mailbox/events/CassandraEventDeadLettersTest.java
@@ -29,6 +29,7 @@ import org.apache.james.mailbox.events.EventDeadLettersContract.RemoveContract;
 import org.apache.james.mailbox.events.EventDeadLettersContract.StoreContract;
 import org.apache.james.mailbox.model.TestId;
 import org.apache.james.mailbox.model.TestMessageId;
+import org.apache.james.mailbox.store.quota.DefaultUserQuotaRootResolver;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
@@ -42,7 +43,7 @@ class CassandraEventDeadLettersTest implements StoreContract, RemoveContract, Fa
 
     @BeforeEach
     void setUp(CassandraCluster cassandraCluster) {
-        EventSerializer eventSerializer = new EventSerializer(new TestId.Factory(), new TestMessageId.Factory());
+        EventSerializer eventSerializer = new EventSerializer(new TestId.Factory(), new TestMessageId.Factory(), new DefaultUserQuotaRootResolver.DefaultQuotaRootDeserializer());
         eventDeadLetters = new CassandraEventDeadLetters(new CassandraEventDeadLettersDAO(cassandraCluster.getConf(), eventSerializer),
                                                          new CassandraEventDeadLettersGroupDAO(cassandraCluster.getConf()));
     }
diff --git a/mailbox/event/event-rabbitmq/pom.xml b/mailbox/event/event-rabbitmq/pom.xml
index 4ca69cc..599787d 100644
--- a/mailbox/event/event-rabbitmq/pom.xml
+++ b/mailbox/event/event-rabbitmq/pom.xml
@@ -63,6 +63,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>apache-james-mailbox-store</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>james-server-lifecycle-api</artifactId>
         </dependency>
         <dependency>
diff --git a/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RabbitMQEventBusTest.java b/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RabbitMQEventBusTest.java
index af9c60f..bbb169c 100644
--- a/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RabbitMQEventBusTest.java
+++ b/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RabbitMQEventBusTest.java
@@ -62,6 +62,7 @@ import org.apache.james.mailbox.events.EventBusTestFixture.GroupA;
 import org.apache.james.mailbox.events.EventBusTestFixture.MailboxListenerCountingSuccessfulExecution;
 import org.apache.james.mailbox.model.TestId;
 import org.apache.james.mailbox.model.TestMessageId;
+import org.apache.james.mailbox.store.quota.DefaultUserQuotaRootResolver;
 import org.apache.james.mailbox.util.EventCollector;
 import org.apache.james.metrics.api.NoopMetricFactory;
 import org.apache.james.util.concurrency.ConcurrentTestRunner;
@@ -107,7 +108,7 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
         memoryEventDeadLetters = new MemoryEventDeadLetters();
 
         TestId.Factory mailboxIdFactory = new TestId.Factory();
-        eventSerializer = new EventSerializer(mailboxIdFactory, new TestMessageId.Factory());
+        eventSerializer = new EventSerializer(mailboxIdFactory, new TestMessageId.Factory(), new DefaultUserQuotaRootResolver.DefaultQuotaRootDeserializer());
         routingKeyConverter = RoutingKeyConverter.forFactories(new MailboxIdRegistrationKey.Factory(mailboxIdFactory));
 
         eventBus = newEventBus();
diff --git a/mailbox/event/json/pom.xml b/mailbox/event/json/pom.xml
index 1f34acd..752c165 100644
--- a/mailbox/event/json/pom.xml
+++ b/mailbox/event/json/pom.xml
@@ -43,6 +43,11 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>apache-james-mailbox-store</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>com.beachape</groupId>
             <artifactId>enumeratum_${scala.base}</artifactId>
             <version>1.5.13</version>
diff --git a/mailbox/event/json/src/main/scala/org/apache/james/event/json/EventSerializer.scala b/mailbox/event/json/src/main/scala/org/apache/james/event/json/EventSerializer.scala
index 1837036..4bd09b2 100644
--- a/mailbox/event/json/src/main/scala/org/apache/james/event/json/EventSerializer.scala
+++ b/mailbox/event/json/src/main/scala/org/apache/james/event/json/EventSerializer.scala
@@ -20,12 +20,12 @@
 package org.apache.james.event.json
 
 import java.time.Instant
-import java.util.{Optional, TreeMap => JavaTreeMap}
+import java.util.{TreeMap => JavaTreeMap}
 
 import javax.inject.Inject
 import julienrf.json.derived
+import org.apache.james.core.User
 import org.apache.james.core.quota.{QuotaCount, QuotaSize, QuotaValue}
-import org.apache.james.core.{Domain, User}
 import org.apache.james.event.json.DTOs.SystemFlag.SystemFlag
 import org.apache.james.event.json.DTOs._
 import org.apache.james.mailbox.MailboxSession.SessionId
@@ -34,6 +34,7 @@ import org.apache.james.mailbox.events.Event.EventId
 import org.apache.james.mailbox.events.MailboxListener.{Added => JavaAdded, Expunged => JavaExpunged, FlagsUpdated => JavaFlagsUpdated, MailboxACLUpdated => JavaMailboxACLUpdated, MailboxAdded => JavaMailboxAdded, MailboxDeletion => JavaMailboxDeletion, MailboxRenamed => JavaMailboxRenamed, QuotaUsageUpdatedEvent => JavaQuotaUsageUpdatedEvent}
 import org.apache.james.mailbox.events.{Event => JavaEvent, MessageMoveEvent => JavaMessageMoveEvent}
 import org.apache.james.mailbox.model.{MailboxId, MessageId, MessageMoves, QuotaRoot, MailboxACL => JavaMailboxACL, MessageMetaData => JavaMessageMetaData, Quota => JavaQuota}
+import org.apache.james.mailbox.quota.QuotaRootDeserializer
 import play.api.libs.json._
 
 import scala.collection.JavaConverters._
@@ -200,7 +201,7 @@ private object ScalaConverter {
   }
 }
 
-class JsonSerialize(mailboxIdFactory: MailboxId.Factory, messageIdFactory: MessageId.Factory) {
+class JsonSerialize(mailboxIdFactory: MailboxId.Factory, messageIdFactory: MessageId.Factory, quotaRootDeserializer: QuotaRootDeserializer) {
   implicit val systemFlagsWrites: Writes[SystemFlag] = Writes.enumNameWrites
   implicit val userWriters: Writes[User] = (user: User) => JsString(user.asString)
   implicit val quotaRootWrites: Writes[QuotaRoot] = quotaRoot => JsString(quotaRoot.getValue)
@@ -243,7 +244,7 @@ class JsonSerialize(mailboxIdFactory: MailboxId.Factory, messageIdFactory: Messa
     case _ => JsError()
   }
   implicit val quotaRootReads: Reads[QuotaRoot] = {
-    case JsString(quotaRoot) => JsSuccess(QuotaRoot.quotaRoot(quotaRoot, Optional.empty[Domain]))
+    case JsString(quotaRoot) => JsSuccess(quotaRootDeserializer.fromString(quotaRoot))
     case _ => JsError()
   }
   implicit val quotaScopeReads: Reads[JavaQuota.Scope] = {
@@ -332,8 +333,8 @@ class JsonSerialize(mailboxIdFactory: MailboxId.Factory, messageIdFactory: Messa
     .map(event => event.toJava)
 }
 
-class EventSerializer @Inject() (mailboxIdFactory: MailboxId.Factory, messageIdFactory: MessageId.Factory) {
-  private val jsonSerialize = new JsonSerialize(mailboxIdFactory, messageIdFactory)
+class EventSerializer @Inject() (mailboxIdFactory: MailboxId.Factory, messageIdFactory: MessageId.Factory, quotaRootDeserializer: QuotaRootDeserializer) {
+  private val jsonSerialize = new JsonSerialize(mailboxIdFactory, messageIdFactory, quotaRootDeserializer)
 
   def toJson(event: JavaEvent): String = jsonSerialize.toJson(event)
   def fromJson(json: String): JsResult[JavaEvent] = jsonSerialize.fromJson(json)
diff --git a/mailbox/event/json/src/test/java/org/apache/james/event/json/MailboxDeletionSerializationTest.java b/mailbox/event/json/src/test/java/org/apache/james/event/json/MailboxDeletionSerializationTest.java
index a634b8a..535bcfe 100644
--- a/mailbox/event/json/src/test/java/org/apache/james/event/json/MailboxDeletionSerializationTest.java
+++ b/mailbox/event/json/src/test/java/org/apache/james/event/json/MailboxDeletionSerializationTest.java
@@ -29,6 +29,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import java.util.NoSuchElementException;
 import java.util.Optional;
 
+import org.apache.james.core.Domain;
 import org.apache.james.core.User;
 import org.apache.james.core.quota.QuotaCount;
 import org.apache.james.core.quota.QuotaSize;
@@ -47,7 +48,7 @@ class MailboxDeletionSerializationTest {
     private static final User USER = User.fromUsername("user");
     private static final MailboxPath MAILBOX_PATH = new MailboxPath(USER_NAMESPACE, USER.asString(), "mailboxName");
     private static final MailboxId MAILBOX_ID = TestId.of(789);
-    private static final QuotaRoot QUOTA_ROOT = QuotaRoot.quotaRoot("user@domain", Optional.empty());
+    private static final QuotaRoot QUOTA_ROOT = QuotaRoot.quotaRoot("#private&user@domain", Optional.of(Domain.of("domain")));
     private static final QuotaCount DELETED_MESSAGE_COUNT = QuotaCount.count(60);
     private static final QuotaSize TOTAL_DELETED_SIZE = QuotaSize.size(100);
     private static final MailboxListener.MailboxDeletion DEFAULT_MAILBOX_DELETION_EVENT = new MailboxListener.MailboxDeletion(
@@ -71,7 +72,7 @@ class MailboxDeletionSerializationTest {
         "      \"user\":\"user\"," +
         "      \"name\":\"mailboxName\"" +
         "    }," +
-        "    \"quotaRoot\":\"user@domain\"," +
+        "    \"quotaRoot\":\"#private&user@domain\"," +
         "    \"deletedMessageCount\":60," +
         "    \"totalDeletedSize\":100," +
         "    \"mailboxId\":\"789\"" +
@@ -104,7 +105,7 @@ class MailboxDeletionSerializationTest {
                     "      \"user\":\"user\"," +
                     "      \"name\":\"mailboxName\"" +
                     "    }," +
-                    "    \"quotaRoot\":\"user@domain\"," +
+                    "    \"quotaRoot\":\"#private&user@domain\"," +
                     "    \"deletedMessageCount\":60," +
                     "    \"totalDeletedSize\":100," +
                     "    \"mailboxId\":\"789\"" +
@@ -125,7 +126,7 @@ class MailboxDeletionSerializationTest {
                     "      \"user\":\"user\"," +
                     "      \"name\":\"mailboxName\"" +
                     "    }," +
-                    "    \"quotaRoot\":\"user@domain\"," +
+                    "    \"quotaRoot\":\"#private&user@domain\"," +
                     "    \"deletedMessageCount\":60," +
                     "    \"totalDeletedSize\":100," +
                     "    \"mailboxId\":\"789\"" +
@@ -146,7 +147,7 @@ class MailboxDeletionSerializationTest {
                     "      \"user\":\"user\"," +
                     "      \"name\":\"mailboxName\"" +
                     "    }," +
-                    "    \"quotaRoot\":\"user@domain\"," +
+                    "    \"quotaRoot\":\"#private&user@domain\"," +
                     "    \"deletedMessageCount\":60," +
                     "    \"totalDeletedSize\":100," +
                     "    \"mailboxId\":\"789\"" +
@@ -189,7 +190,7 @@ class MailboxDeletionSerializationTest {
                     "      \"user\":\"user\"," +
                     "      \"name\":\"mailboxName\"" +
                     "    }," +
-                    "    \"quotaRoot\":\"user@domain\"," +
+                    "    \"quotaRoot\":\"#private&user@domain\"," +
                     "    \"totalDeletedSize\":100," +
                     "    \"mailboxId\":\"789\"" +
                     "  }" +
@@ -210,7 +211,7 @@ class MailboxDeletionSerializationTest {
                     "      \"user\":\"user\"," +
                     "      \"name\":\"mailboxName\"" +
                     "    }," +
-                    "    \"quotaRoot\":\"user@domain\"," +
+                    "    \"quotaRoot\":\"#private&user@domain\"," +
                     "    \"deletedMessageCount\":60," +
                     "    \"mailboxId\":\"789\"" +
                     "  }" +
@@ -231,7 +232,7 @@ class MailboxDeletionSerializationTest {
                     "      \"user\":\"user\"," +
                     "      \"name\":\"mailboxName\"" +
                     "    }," +
-                    "    \"quotaRoot\":\"user@domain\"," +
+                    "    \"quotaRoot\":\"#private&user@domain\"," +
                     "    \"deletedMessageCount\":60," +
                     "    \"totalDeletedSize\":100" +
                     "  }" +
@@ -247,7 +248,7 @@ class MailboxDeletionSerializationTest {
                     "    \"eventId\":\"6e0dd59d-660e-4d9b-b22f-0354479f47b4\"," +
                     "    \"sessionId\":3652," +
                     "    \"user\":\"user\"," +
-                    "    \"quotaRoot\":\"user@domain\"," +
+                    "    \"quotaRoot\":\"#private&user@domain\"," +
                     "    \"deletedMessageCount\":60," +
                     "    \"totalDeletedSize\":100," +
                     "    \"mailboxId\":\"789\"" +
diff --git a/mailbox/event/json/src/test/java/org/apache/james/event/json/QuotaUsageUpdatedEventSerializationTest.java b/mailbox/event/json/src/test/java/org/apache/james/event/json/QuotaUsageUpdatedEventSerializationTest.java
index 1da0211..00627ea 100644
--- a/mailbox/event/json/src/test/java/org/apache/james/event/json/QuotaUsageUpdatedEventSerializationTest.java
+++ b/mailbox/event/json/src/test/java/org/apache/james/event/json/QuotaUsageUpdatedEventSerializationTest.java
@@ -38,7 +38,7 @@ import org.apache.james.mailbox.model.QuotaRoot;
 import org.junit.jupiter.api.Test;
 
 class QuotaUsageUpdatedEventSerializationTest {
-    private static final QuotaRoot QUOTA_ROOT = QuotaRoot.quotaRoot("foo", Optional.empty());
+    private static final QuotaRoot QUOTA_ROOT = QuotaRoot.quotaRoot("#private&foo", Optional.empty());
     private static final Quota<QuotaCount> QUOTA_COUNT = Quota.<QuotaCount>builder()
         .used(QuotaCount.count(12))
         .computedLimit(QuotaCount.count(100))
@@ -59,7 +59,7 @@ class QuotaUsageUpdatedEventSerializationTest {
         "{" +
         "    \"QuotaUsageUpdatedEvent\":{" +
         "        \"eventId\":\"6e0dd59d-660e-4d9b-b22f-0354479f47b4\"," +
-        "        \"quotaRoot\":\"foo\"," +
+        "        \"quotaRoot\":\"#private&foo\"," +
         "        \"countQuota\":{\"used\":12,\"limit\":100,\"limits\":{}}," +
         "        \"time\":\"2018-11-13T12:00:55Z\"," +
         "        \"sizeQuota\":{\"used\":1234,\"limit\":10000,\"limits\":{}}," +
@@ -85,7 +85,7 @@ class QuotaUsageUpdatedEventSerializationTest {
             "{" +
             "    \"QuotaUsageUpdatedEvent\":{" +
             "        \"eventId\":\"6e0dd59d-660e-4d9b-b22f-0354479f47b4\"," +
-            "        \"quotaRoot\":\"foo\"," +
+            "        \"quotaRoot\":\"#private&foo\"," +
             "        \"countQuota\":{\"used\":12,\"limit\":100,\"limits\":{}}," +
             "        \"time\":\"2018-11-13T12:00:55Z\"," +
             "        \"sizeQuota\":{\"used\":1234,\"limit\":10000,\"limits\":{}}" +
@@ -102,7 +102,7 @@ class QuotaUsageUpdatedEventSerializationTest {
             "{" +
             "    \"QuotaUsageUpdatedEvent\":{" +
             "        \"eventId\":\"6e0dd59d-660e-4d9b-b22f-0354479f47b4\"," +
-            "        \"quotaRoot\":\"foo\"," +
+            "        \"quotaRoot\":\"#private&foo\"," +
             "        \"time\":\"2018-11-13T12:00:55Z\"," +
             "        \"sizeQuota\":{\"used\":1234,\"limit\":10000,\"limits\":{}}," +
             "        \"user\":\"onlyUsername\"" +
@@ -119,7 +119,7 @@ class QuotaUsageUpdatedEventSerializationTest {
             "{" +
             "    \"QuotaUsageUpdatedEvent\":{" +
             "        \"eventId\":\"6e0dd59d-660e-4d9b-b22f-0354479f47b4\"," +
-            "        \"quotaRoot\":\"foo\"," +
+            "        \"quotaRoot\":\"#private&foo\"," +
             "        \"time\":\"2018-11-13T12:00:55Z\"," +
             "        \"countQuota\":{\"used\":12,\"limit\":100,\"limits\":{}}," +
             "        \"user\":\"onlyUsername\"" +
@@ -136,7 +136,7 @@ class QuotaUsageUpdatedEventSerializationTest {
             "{" +
             "    \"QuotaUsageUpdatedEvent\":{" +
             "        \"eventId\":\"6e0dd59d-660e-4d9b-b22f-0354479f47b4\"," +
-            "        \"quotaRoot\":\"foo\"," +
+            "        \"quotaRoot\":\"#private&foo\"," +
             "        \"countQuota\":{\"used\":12,\"limit\":100,\"limits\":{\"Domain\":100}}," +
             "        \"sizeQuota\":{\"used\":1234,\"limit\":10000,\"limits\":{}}," +
             "        \"user\":\"user\"" +
@@ -153,7 +153,7 @@ class QuotaUsageUpdatedEventSerializationTest {
             "{" +
             "    \"QuotaUsageUpdatedEvent\":{" +
             "        \"eventId\":\"6e0dd59d-660e-4d9b-b22f-0354479f47b4\"," +
-            "        \"quotaRoot\":\"foo\"," +
+            "        \"quotaRoot\":\"#private&foo\"," +
             "        \"countQuota\":{\"used\":12,\"limit\":100,\"limits\":{\"Domain\":100}}," +
             "        \"time\":\"\"," +
             "        \"sizeQuota\":{\"used\":1234,\"limit\":10000,\"limits\":{}}," +
diff --git a/mailbox/event/json/src/test/java/org/apache/james/event/json/SerializerFixture.java b/mailbox/event/json/src/test/java/org/apache/james/event/json/SerializerFixture.java
index 3cf904a..bd8ad0d 100644
--- a/mailbox/event/json/src/test/java/org/apache/james/event/json/SerializerFixture.java
+++ b/mailbox/event/json/src/test/java/org/apache/james/event/json/SerializerFixture.java
@@ -22,10 +22,11 @@ package org.apache.james.event.json;
 import org.apache.james.mailbox.events.Event;
 import org.apache.james.mailbox.model.TestId;
 import org.apache.james.mailbox.model.TestMessageId;
+import org.apache.james.mailbox.store.quota.DefaultUserQuotaRootResolver;
 
 public interface SerializerFixture {
-    JsonSerialize DTO_JSON_SERIALIZE = new JsonSerialize(new TestId.Factory(), new TestMessageId.Factory());
-    EventSerializer EVENT_SERIALIZER = new EventSerializer(new TestId.Factory(), new TestMessageId.Factory());
+    JsonSerialize DTO_JSON_SERIALIZE = new JsonSerialize(new TestId.Factory(), new TestMessageId.Factory(), new DefaultUserQuotaRootResolver.DefaultQuotaRootDeserializer());
+    EventSerializer EVENT_SERIALIZER = new EventSerializer(new TestId.Factory(), new TestMessageId.Factory(), new DefaultUserQuotaRootResolver.DefaultQuotaRootDeserializer());
 
     String SERIALIZED_EVENT_ID = "6e0dd59d-660e-4d9b-b22f-0354479f47b4";
     Event.EventId EVENT_ID = Event.EventId.of(SERIALIZED_EVENT_ID);
diff --git a/mailbox/event/json/src/test/java/org/apache/james/event/json/dtos/QuotaRootTest.java b/mailbox/event/json/src/test/java/org/apache/james/event/json/dtos/QuotaRootTest.java
index 4ba88b4..ab9df3c 100644
--- a/mailbox/event/json/src/test/java/org/apache/james/event/json/dtos/QuotaRootTest.java
+++ b/mailbox/event/json/src/test/java/org/apache/james/event/json/dtos/QuotaRootTest.java
@@ -21,10 +21,12 @@ package org.apache.james.event.json.dtos;
 
 import static org.apache.james.event.json.SerializerFixture.DTO_JSON_SERIALIZE;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import java.util.Optional;
 
 import org.apache.james.core.Domain;
+import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.QuotaRoot;
 import org.junit.jupiter.api.Test;
 
@@ -43,8 +45,8 @@ class QuotaRootTest {
 
     @Test
     void quotaRootWithDomainShouldBeWellDeSerialized() {
-        assertThat(DTO_JSON_SERIALIZE.quotaRootReads().reads(new JsString("bob@domain.tld")).get())
-            .isEqualTo(QuotaRoot.quotaRoot("bob@domain.tld", Optional.of(Domain.of("domain.tld"))));
+        assertThat(DTO_JSON_SERIALIZE.quotaRootReads().reads(new JsString("#private&bob@domain.tld")).get())
+            .isEqualTo(QuotaRoot.quotaRoot("#private&bob@domain.tld", Optional.of(Domain.of("domain.tld"))));
     }
 
     @Test
@@ -55,8 +57,8 @@ class QuotaRootTest {
 
     @Test
     void quotaRootShouldBeWellDeSerialized() {
-        assertThat(DTO_JSON_SERIALIZE.quotaRootReads().reads(new JsString("bob")).get())
-            .isEqualTo(QuotaRoot.quotaRoot("bob", Optional.empty()));
+        assertThat(DTO_JSON_SERIALIZE.quotaRootReads().reads(new JsString("#private&bob")).get())
+            .isEqualTo(QuotaRoot.quotaRoot("#private&bob", Optional.empty()));
     }
 
     @Test
@@ -67,8 +69,9 @@ class QuotaRootTest {
 
     @Test
     void emptyQuotaRootShouldBeWellDeSerialized() {
-        assertThat(DTO_JSON_SERIALIZE.quotaRootReads().reads(new JsString("")).get())
-            .isEqualTo(QuotaRoot.quotaRoot("", Optional.empty()));
+        assertThatThrownBy(() -> DTO_JSON_SERIALIZE.quotaRootReads().reads(new JsString("")).get())
+            .isInstanceOf(MailboxException.class)
+            .hasMessage(" used as QuotaRoot should contain exactly one \"&\"");
     }
 
     @Test
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/DefaultUserQuotaRootResolver.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/DefaultUserQuotaRootResolver.java
index df16947..3dcb7af 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/DefaultUserQuotaRootResolver.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/DefaultUserQuotaRootResolver.java
@@ -32,6 +32,7 @@ import org.apache.james.mailbox.model.MailboxConstants;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.QuotaRoot;
+import org.apache.james.mailbox.quota.QuotaRootDeserializer;
 import org.apache.james.mailbox.quota.UserQuotaRootResolver;
 import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
 import org.apache.james.mailbox.store.SessionProvider;
@@ -42,7 +43,26 @@ import com.google.common.collect.Lists;
 
 public class DefaultUserQuotaRootResolver implements UserQuotaRootResolver {
 
+    public static class DefaultQuotaRootDeserializer implements QuotaRootDeserializer {
+        @Override
+        public QuotaRoot fromString(String serializedQuotaRoot) throws MailboxException {
+            List<String> parts = toParts(serializedQuotaRoot);
+            User user = User.fromUsername(parts.get(1));
+
+            return QuotaRoot.quotaRoot(serializedQuotaRoot, user.getDomainPart());
+        }
+
+        private List<String> toParts(String serializedQuotaRoot) throws MailboxException {
+            List<String> parts = Splitter.on(SEPARATOR).splitToList(serializedQuotaRoot);
+            if (parts.size() != 2) {
+                throw new MailboxException(serializedQuotaRoot + " used as QuotaRoot should contain exactly one \"" + SEPARATOR + "\"");
+            }
+            return parts;
+        }
+    }
+
     public static final String SEPARATOR = "&"; // Character illegal for mailbox naming in regard of RFC 3501 section 5.1
+    private static final DefaultQuotaRootDeserializer QUOTA_ROOT_DESERIALIZER = new DefaultQuotaRootDeserializer();
 
     private final SessionProvider sessionProvider;
     private final MailboxSessionMapperFactory factory;
@@ -85,27 +105,16 @@ public class DefaultUserQuotaRootResolver implements UserQuotaRootResolver {
 
     @Override
     public QuotaRoot fromString(String serializedQuotaRoot) throws MailboxException {
-        List<String> parts = toParts(serializedQuotaRoot);
-        User user = User.fromUsername(parts.get(1));
-
-        return QuotaRoot.quotaRoot(serializedQuotaRoot, user.getDomainPart());
+        return QUOTA_ROOT_DESERIALIZER.fromString(serializedQuotaRoot);
     }
 
     @Override
     public List<MailboxPath> retrieveAssociatedMailboxes(QuotaRoot quotaRoot, MailboxSession mailboxSession) throws MailboxException {
-        List<String> parts = toParts(quotaRoot.getValue());
+        List<String> parts = QUOTA_ROOT_DESERIALIZER.toParts(quotaRoot.getValue());
         String namespace = parts.get(0);
         String user = parts.get(1);
         return Lists.transform(factory.getMailboxMapper(mailboxSession)
             .findMailboxWithPathLike(new MailboxPath(namespace, user, "%")),
             Mailbox::generateAssociatedPath);
     }
-
-    public List<String> toParts(String serializedQuotaRoot) throws MailboxException {
-        List<String> parts = Splitter.on(SEPARATOR).splitToList(serializedQuotaRoot);
-        if (parts.size() != 2) {
-            throw new MailboxException(serializedQuotaRoot + " used as QuotaRoot should contain exactly one \"" + SEPARATOR + "\"");
-        }
-        return parts;
-    }
 }
diff --git a/mpt/impl/imap-mailbox/rabbitmq/src/test/java/org/apache/james/mpt/imapmailbox/rabbitmq/host/RabbitMQEventBusHostSystem.java b/mpt/impl/imap-mailbox/rabbitmq/src/test/java/org/apache/james/mpt/imapmailbox/rabbitmq/host/RabbitMQEventBusHostSystem.java
index 87d6fe5..c21b185 100644
--- a/mpt/impl/imap-mailbox/rabbitmq/src/test/java/org/apache/james/mpt/imapmailbox/rabbitmq/host/RabbitMQEventBusHostSystem.java
+++ b/mpt/impl/imap-mailbox/rabbitmq/src/test/java/org/apache/james/mpt/imapmailbox/rabbitmq/host/RabbitMQEventBusHostSystem.java
@@ -42,6 +42,7 @@ import org.apache.james.mailbox.inmemory.InMemoryId;
 import org.apache.james.mailbox.inmemory.InMemoryMessageId;
 import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
 import org.apache.james.mailbox.store.StoreSubscriptionManager;
+import org.apache.james.mailbox.store.quota.DefaultUserQuotaRootResolver;
 import org.apache.james.metrics.api.NoopMetricFactory;
 import org.apache.james.metrics.logger.DefaultMetricFactory;
 import org.apache.james.mpt.api.ImapFeatures;
@@ -103,7 +104,7 @@ public class RabbitMQEventBusHostSystem extends JamesImapHostSystem {
     private RabbitMQEventBus createEventBus() throws URISyntaxException {
         InMemoryMessageId.Factory messageIdFactory = new InMemoryMessageId.Factory();
         InMemoryId.Factory mailboxIdFactory = new InMemoryId.Factory();
-        EventSerializer eventSerializer = new EventSerializer(mailboxIdFactory, messageIdFactory);
+        EventSerializer eventSerializer = new EventSerializer(mailboxIdFactory, messageIdFactory, new DefaultUserQuotaRootResolver.DefaultQuotaRootDeserializer());
         RoutingKeyConverter routingKeyConverter = new RoutingKeyConverter(ImmutableSet.of(new MailboxIdRegistrationKey.Factory(mailboxIdFactory)));
         return new RabbitMQEventBus(connectionPool, eventSerializer, RetryBackoffConfiguration.DEFAULT,
             routingKeyConverter, new MemoryEventDeadLetters(), new NoopMetricFactory());
diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraQuotaModule.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraQuotaModule.java
index 1850879..f0101d3 100644
--- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraQuotaModule.java
+++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraQuotaModule.java
@@ -29,6 +29,7 @@ import org.apache.james.mailbox.events.MailboxListener;
 import org.apache.james.mailbox.quota.CurrentQuotaManager;
 import org.apache.james.mailbox.quota.MaxQuotaManager;
 import org.apache.james.mailbox.quota.QuotaManager;
+import org.apache.james.mailbox.quota.QuotaRootDeserializer;
 import org.apache.james.mailbox.quota.QuotaRootResolver;
 import org.apache.james.mailbox.quota.UserQuotaRootResolver;
 import org.apache.james.mailbox.store.quota.DefaultUserQuotaRootResolver;
@@ -57,6 +58,7 @@ public class CassandraQuotaModule extends AbstractModule {
         bind(MaxQuotaManager.class).to(CassandraPerUserMaxQuotaManager.class);
         bind(QuotaManager.class).to(StoreQuotaManager.class);
         bind(QuotaRootResolver.class).to(DefaultUserQuotaRootResolver.class);
+        bind(QuotaRootDeserializer.class).to(DefaultUserQuotaRootResolver.class);
         bind(StoreCurrentQuotaManager.class).to(CassandraCurrentQuotaManager.class);
         bind(UserQuotaRootResolver.class).to(DefaultUserQuotaRootResolver.class);
 
diff --git a/server/container/guice/jpa-guice/src/main/java/org/apache/james/modules/mailbox/JpaQuotaModule.java b/server/container/guice/jpa-guice/src/main/java/org/apache/james/modules/mailbox/JpaQuotaModule.java
index 45c1b0b..d008c3d 100644
--- a/server/container/guice/jpa-guice/src/main/java/org/apache/james/modules/mailbox/JpaQuotaModule.java
+++ b/server/container/guice/jpa-guice/src/main/java/org/apache/james/modules/mailbox/JpaQuotaModule.java
@@ -25,6 +25,7 @@ import org.apache.james.mailbox.jpa.quota.JpaCurrentQuotaManager;
 import org.apache.james.mailbox.quota.CurrentQuotaManager;
 import org.apache.james.mailbox.quota.MaxQuotaManager;
 import org.apache.james.mailbox.quota.QuotaManager;
+import org.apache.james.mailbox.quota.QuotaRootDeserializer;
 import org.apache.james.mailbox.quota.QuotaRootResolver;
 import org.apache.james.mailbox.quota.UserQuotaRootResolver;
 import org.apache.james.mailbox.store.quota.DefaultUserQuotaRootResolver;
@@ -48,6 +49,7 @@ public class JpaQuotaModule extends AbstractModule {
 
         bind(UserQuotaRootResolver.class).to(DefaultUserQuotaRootResolver.class);
         bind(QuotaRootResolver.class).to(DefaultUserQuotaRootResolver.class);
+        bind(QuotaRootDeserializer.class).to(DefaultUserQuotaRootResolver.class);
         bind(MaxQuotaManager.class).to(JPAPerUserMaxQuotaManager.class);
         bind(QuotaManager.class).to(StoreQuotaManager.class);
         bind(CurrentQuotaManager.class).to(JpaCurrentQuotaManager.class);
diff --git a/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/DefaultQuotaModule.java b/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/DefaultQuotaModule.java
index 831288c..46c8b7c 100644
--- a/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/DefaultQuotaModule.java
+++ b/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/DefaultQuotaModule.java
@@ -21,6 +21,7 @@ package org.apache.james.modules.mailbox;
 
 import org.apache.james.mailbox.quota.MaxQuotaManager;
 import org.apache.james.mailbox.quota.QuotaManager;
+import org.apache.james.mailbox.quota.QuotaRootDeserializer;
 import org.apache.james.mailbox.quota.QuotaRootResolver;
 import org.apache.james.mailbox.quota.UserQuotaRootResolver;
 import org.apache.james.mailbox.store.quota.DefaultUserQuotaRootResolver;
@@ -41,6 +42,7 @@ public class DefaultQuotaModule extends AbstractModule {
         bind(MaxQuotaManager.class).toInstance(new NoMaxQuotaManager());
         bind(QuotaManager.class).to(NoQuotaManager.class);
         bind(QuotaRootResolver.class).to(DefaultUserQuotaRootResolver.class);
+        bind(QuotaRootDeserializer.class).to(DefaultUserQuotaRootResolver.class);
         bind(UserQuotaRootResolver.class).to(DefaultUserQuotaRootResolver.class);
     }
     
diff --git a/server/container/guice/memory-guice/src/main/java/org/apache/james/modules/mailbox/MemoryQuotaModule.java b/server/container/guice/memory-guice/src/main/java/org/apache/james/modules/mailbox/MemoryQuotaModule.java
index 6b81bbe..d16becb 100644
--- a/server/container/guice/memory-guice/src/main/java/org/apache/james/modules/mailbox/MemoryQuotaModule.java
+++ b/server/container/guice/memory-guice/src/main/java/org/apache/james/modules/mailbox/MemoryQuotaModule.java
@@ -25,6 +25,7 @@ import org.apache.james.mailbox.inmemory.quota.InMemoryPerUserMaxQuotaManager;
 import org.apache.james.mailbox.quota.CurrentQuotaManager;
 import org.apache.james.mailbox.quota.MaxQuotaManager;
 import org.apache.james.mailbox.quota.QuotaManager;
+import org.apache.james.mailbox.quota.QuotaRootDeserializer;
 import org.apache.james.mailbox.quota.QuotaRootResolver;
 import org.apache.james.mailbox.quota.UserQuotaRootResolver;
 import org.apache.james.mailbox.store.quota.DefaultUserQuotaRootResolver;
@@ -48,6 +49,7 @@ public class MemoryQuotaModule extends AbstractModule {
 
         bind(UserQuotaRootResolver.class).to(DefaultUserQuotaRootResolver.class);
         bind(QuotaRootResolver.class).to(DefaultUserQuotaRootResolver.class);
+        bind(QuotaRootDeserializer.class).to(DefaultUserQuotaRootResolver.class);
         bind(MaxQuotaManager.class).to(InMemoryPerUserMaxQuotaManager.class);
         bind(QuotaManager.class).to(StoreQuotaManager.class);
         bind(CurrentQuotaManager.class).to(InMemoryCurrentQuotaManager.class);
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/EventDeadLettersRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/EventDeadLettersRoutesTest.java
index b21b137..67998c8 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/EventDeadLettersRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/EventDeadLettersRoutesTest.java
@@ -47,6 +47,7 @@ import org.apache.james.mailbox.inmemory.InMemoryId;
 import org.apache.james.mailbox.inmemory.InMemoryMessageId;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.store.event.EventFactory;
+import org.apache.james.mailbox.store.quota.DefaultUserQuotaRootResolver;
 import org.apache.james.mailbox.util.EventCollector;
 import org.apache.james.metrics.api.NoopMetricFactory;
 import org.apache.james.task.MemoryTaskManager;
@@ -115,7 +116,7 @@ class EventDeadLettersRoutesTest {
     void beforeEach() {
         deadLetters = new MemoryEventDeadLetters();
         JsonTransformer jsonTransformer = new JsonTransformer();
-        EventSerializer eventSerializer = new EventSerializer(new InMemoryId.Factory(), new InMemoryMessageId.Factory());
+        EventSerializer eventSerializer = new EventSerializer(new InMemoryId.Factory(), new InMemoryMessageId.Factory(), new DefaultUserQuotaRootResolver.DefaultQuotaRootDeserializer());
         eventBus = new InVMEventBus(new InVmEventDelivery(new NoopMetricFactory()), RetryBackoffConfiguration.DEFAULT, deadLetters);
         EventDeadLettersRedeliverService redeliverService = new EventDeadLettersRedeliverService(eventBus, deadLetters);
         EventDeadLettersService service = new EventDeadLettersService(redeliverService, deadLetters);


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