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/01/16 06:59:09 UTC

[01/17] james-project git commit: MAILBOX-371 Registration should have a deserialization factory

Repository: james-project
Updated Branches:
  refs/heads/master 8ff801e7f -> 4cdfef08a


MAILBOX-371 Registration should have a deserialization factory


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

Branch: refs/heads/master
Commit: c754f3a53b8ad16511fb2383ee9a89e43e198b2f
Parents: 8ff801e
Author: datph <dp...@linagora.com>
Authored: Thu Jan 10 16:36:28 2019 +0700
Committer: datph <dp...@linagora.com>
Committed: Wed Jan 16 05:38:44 2019 +0700

----------------------------------------------------------------------
 .../events/MailboxIdRegistrationKey.java        | 26 ++++++++++++++++++
 .../james/mailbox/events/RegistrationKey.java   |  8 ++++++
 .../events/MailboxIdRegistrationKeyTest.java    | 28 ++++++++++++++++++++
 3 files changed, 62 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/c754f3a5/mailbox/api/src/main/java/org/apache/james/mailbox/events/MailboxIdRegistrationKey.java
----------------------------------------------------------------------
diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/events/MailboxIdRegistrationKey.java b/mailbox/api/src/main/java/org/apache/james/mailbox/events/MailboxIdRegistrationKey.java
index cc438a9..e132429 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/events/MailboxIdRegistrationKey.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/events/MailboxIdRegistrationKey.java
@@ -21,9 +21,30 @@ package org.apache.james.mailbox.events;
 
 import java.util.Objects;
 
+import javax.inject.Inject;
+
 import org.apache.james.mailbox.model.MailboxId;
 
 public class MailboxIdRegistrationKey implements RegistrationKey {
+    public static class Factory implements RegistrationKey.Factory {
+        private final MailboxId.Factory mailboxIdFactory;
+
+        @Inject
+        public Factory(MailboxId.Factory mailboxIdFactory) {
+            this.mailboxIdFactory = mailboxIdFactory;
+        }
+
+        @Override
+        public Class<? extends RegistrationKey> forClass() {
+            return MailboxIdRegistrationKey.class;
+        }
+
+        @Override
+        public RegistrationKey fromString(String asString) {
+            return new MailboxIdRegistrationKey(mailboxIdFactory.fromString(asString));
+        }
+    }
+
     private final MailboxId mailboxId;
 
     public MailboxIdRegistrationKey(MailboxId mailboxId) {
@@ -35,6 +56,11 @@ public class MailboxIdRegistrationKey implements RegistrationKey {
     }
 
     @Override
+    public String asString() {
+        return mailboxId.serialize();
+    }
+
+    @Override
     public final boolean equals(Object o) {
         if (o instanceof MailboxIdRegistrationKey) {
             MailboxIdRegistrationKey that = (MailboxIdRegistrationKey) o;

http://git-wip-us.apache.org/repos/asf/james-project/blob/c754f3a5/mailbox/api/src/main/java/org/apache/james/mailbox/events/RegistrationKey.java
----------------------------------------------------------------------
diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/events/RegistrationKey.java b/mailbox/api/src/main/java/org/apache/james/mailbox/events/RegistrationKey.java
index 82b6e31..1d0e320 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/events/RegistrationKey.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/events/RegistrationKey.java
@@ -20,4 +20,12 @@
 package org.apache.james.mailbox.events;
 
 public interface RegistrationKey {
+
+    interface Factory {
+        Class<? extends RegistrationKey> forClass();
+
+        RegistrationKey fromString(String asString);
+    }
+
+    String asString();
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/c754f3a5/mailbox/api/src/test/java/org/apache/james/mailbox/events/MailboxIdRegistrationKeyTest.java
----------------------------------------------------------------------
diff --git a/mailbox/api/src/test/java/org/apache/james/mailbox/events/MailboxIdRegistrationKeyTest.java b/mailbox/api/src/test/java/org/apache/james/mailbox/events/MailboxIdRegistrationKeyTest.java
index f1e28e1..0a361b6 100644
--- a/mailbox/api/src/test/java/org/apache/james/mailbox/events/MailboxIdRegistrationKeyTest.java
+++ b/mailbox/api/src/test/java/org/apache/james/mailbox/events/MailboxIdRegistrationKeyTest.java
@@ -19,14 +19,42 @@
 
 package org.apache.james.mailbox.events;
 
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.apache.james.mailbox.model.TestId;
 import org.junit.jupiter.api.Test;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 
 class MailboxIdRegistrationKeyTest {
+    private static final String ID = "42";
+
+    private static final MailboxIdRegistrationKey.Factory FACTORY = new MailboxIdRegistrationKey.Factory(new TestId.Factory());
+
+    private static final MailboxIdRegistrationKey MAILBOX_ID_REGISTRATION_KEY = new MailboxIdRegistrationKey((TestId.of(42)));
+
     @Test
     void shouldRespectBeanContract() {
         EqualsVerifier.forClass(MailboxIdRegistrationKey.class)
             .verify();
     }
+
+    @Test
+    void asStringShouldReturnSerializedMailboxId() {
+        assertThat(MAILBOX_ID_REGISTRATION_KEY.asString())
+            .isEqualTo(ID);
+    }
+
+    @Test
+    void fromStringShouldReturnCorrespondingRegistrationKey() {
+        assertThat(FACTORY.fromString(ID))
+            .isEqualTo(MAILBOX_ID_REGISTRATION_KEY);
+    }
+
+    @Test
+    void fromStringShouldThrowOnInvalidValues() {
+        assertThatThrownBy(() -> FACTORY.fromString("invalid"))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
 }
\ 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


[10/17] james-project git commit: JAMES-2637 Rely on asMailAddressString for MappingSource serialization

Posted by bt...@apache.org.
JAMES-2637 Rely on asMailAddressString for MappingSource serialization


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

Branch: refs/heads/master
Commit: 92f44f28455adb9f5017d58c02158e072cde13c1
Parents: 8ea2c22
Author: Rene Cordier <rc...@linagora.com>
Authored: Tue Jan 15 14:52:00 2019 +0700
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Wed Jan 16 13:48:56 2019 +0700

----------------------------------------------------------------------
 .../james/rrt/api/RecipientRewriteTable.java     |  3 ++-
 .../org/apache/james/rrt/lib/MappingSource.java  | 19 +------------------
 .../james/webadmin/dto/MappingSourceModule.java  | 13 ++-----------
 .../james/webadmin/routes/AliasRoutes.java       |  4 ++--
 4 files changed, 7 insertions(+), 32 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/92f44f28/server/data/data-api/src/main/java/org/apache/james/rrt/api/RecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/api/RecipientRewriteTable.java b/server/data/data-api/src/main/java/org/apache/james/rrt/api/RecipientRewriteTable.java
index 2c53f3a..378c10e 100644
--- a/server/data/data-api/src/main/java/org/apache/james/rrt/api/RecipientRewriteTable.java
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/api/RecipientRewriteTable.java
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.james.rrt.api;
 
+import java.util.Comparator;
 import java.util.EnumSet;
 import java.util.List;
 import java.util.Map;
@@ -127,7 +128,7 @@ public interface RecipientRewriteTable {
             .entrySet().stream()
             .filter(e -> e.getValue().contains(type))
             .map(Map.Entry::getKey)
-            .sorted()
+            .sorted(Comparator.comparing(MappingSource::asMailAddressString))
             .collect(Guavate.toImmutableList());
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/92f44f28/server/data/data-api/src/main/java/org/apache/james/rrt/lib/MappingSource.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/MappingSource.java b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/MappingSource.java
index 9e5d90f..92c5264 100644
--- a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/MappingSource.java
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/MappingSource.java
@@ -32,7 +32,7 @@ import org.apache.james.util.OptionalUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class MappingSource implements Serializable, Comparable<MappingSource> {
+public class MappingSource implements Serializable {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(MappingSource.class);
     private static final String WILDCARD = "*";
@@ -149,21 +149,4 @@ public class MappingSource implements Serializable, Comparable<MappingSource> {
     public String asMailAddressString() {
         return getFixedUser() + "@" + getFixedDomain();
     }
-
-    @Override
-    public int compareTo(MappingSource mappingSource) {
-        final int result;
-        final MailAddress mailAddress1 = this.asMailAddress().get();
-        final MailAddress mailAddress2 = mappingSource.asMailAddress().get();
-
-        if (mailAddress1 == null) {
-            result = mailAddress2 == null ? 0 : 1;
-        } else if (mailAddress2 == null) {
-            result = -1;
-        } else {
-            result = mailAddress1.asString().compareTo(mailAddress2.asString());
-        }
-
-        return result;
-    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/92f44f28/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/MappingSourceModule.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/MappingSourceModule.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/MappingSourceModule.java
index 424a04e..a8b4181 100644
--- a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/MappingSourceModule.java
+++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/MappingSourceModule.java
@@ -20,9 +20,7 @@
 package org.apache.james.webadmin.dto;
 
 import java.io.IOException;
-import java.util.Optional;
 
-import org.apache.james.core.MailAddress;
 import org.apache.james.rrt.lib.MappingSource;
 import org.apache.james.webadmin.utils.JsonTransformerModule;
 
@@ -40,15 +38,8 @@ public class MappingSourceModule implements JsonTransformerModule {
         simpleModule = new SimpleModule()
             .addSerializer(MappingSource.class, new JsonSerializer<MappingSource>() {
                 @Override
-                public void serialize(MappingSource t, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
-                    jsonGenerator.writeString(serialize(t.asMailAddress()));
-                }
-
-                private String serialize(Optional<MailAddress> mailAddress) {
-                    if (mailAddress.isPresent()) {
-                        return mailAddress.get().asString();
-                    }
-                    return "";
+                public void serialize(MappingSource mappingSource, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
+                    jsonGenerator.writeString(mappingSource.asMailAddressString());
                 }
             });
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/92f44f28/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AliasRoutes.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AliasRoutes.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AliasRoutes.java
index 43004d0..f039559 100644
--- a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AliasRoutes.java
+++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AliasRoutes.java
@@ -22,6 +22,7 @@ package org.apache.james.webadmin.routes;
 import static org.apache.james.webadmin.Constants.SEPARATOR;
 import static spark.Spark.halt;
 
+import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 
@@ -226,8 +227,7 @@ public class AliasRoutes implements Routes {
             .entrySet().stream()
             .filter(e -> e.getValue().contains(Mapping.alias(baseAddress.asString())))
             .map(Map.Entry::getKey)
-            .flatMap(source -> OptionalUtils.toStream(source.asMailAddress()))
-            .map(MailAddress::asString)
+            .map(MappingSource::asMailAddressString)
             .sorted()
             .map(AliasSourcesResponse::new)
             .collect(Guavate.toImmutableSet());


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


[11/17] james-project git commit: JAMES-2637 add asMailAddressString method to MappingSource

Posted by bt...@apache.org.
JAMES-2637 add asMailAddressString method to MappingSource


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

Branch: refs/heads/master
Commit: 8ea2c22ef39ada4de2b31161c37327bce40b1ffa
Parents: 331a888
Author: Rene Cordier <rc...@linagora.com>
Authored: Tue Jan 15 14:43:27 2019 +0700
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Wed Jan 16 13:48:56 2019 +0700

----------------------------------------------------------------------
 .../org/apache/james/rrt/lib/MappingSource.java |  4 ++
 .../apache/james/rrt/lib/MappingSourceTest.java | 67 ++++++++++++++++++++
 2 files changed, 71 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/8ea2c22e/server/data/data-api/src/main/java/org/apache/james/rrt/lib/MappingSource.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/MappingSource.java b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/MappingSource.java
index 68ad8b4..9e5d90f 100644
--- a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/MappingSource.java
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/MappingSource.java
@@ -146,6 +146,10 @@ public class MappingSource implements Serializable, Comparable<MappingSource> {
         return Objects.hash(domain, user, wildcard);
     }
 
+    public String asMailAddressString() {
+        return getFixedUser() + "@" + getFixedDomain();
+    }
+
     @Override
     public int compareTo(MappingSource mappingSource) {
         final int result;

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ea2c22e/server/data/data-api/src/test/java/org/apache/james/rrt/lib/MappingSourceTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/test/java/org/apache/james/rrt/lib/MappingSourceTest.java b/server/data/data-api/src/test/java/org/apache/james/rrt/lib/MappingSourceTest.java
new file mode 100644
index 0000000..9088b42
--- /dev/null
+++ b/server/data/data-api/src/test/java/org/apache/james/rrt/lib/MappingSourceTest.java
@@ -0,0 +1,67 @@
+/****************************************************************
+ * 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.rrt.lib;
+
+import org.apache.james.core.Domain;
+import org.apache.james.core.MailAddress;
+import org.apache.james.core.User;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+class MappingSourceTest {
+    private static final String DOMAIN = "domain.tld";
+    private static final  String USER = "alice";
+    private static final String MAIL_ADDRESS = USER + "@" + DOMAIN;
+
+    @Test
+    void asMailAddressStringShouldSerializeWilcard() {
+        MappingSource mappingSource = MappingSource.wildCard();
+
+        assertThat(mappingSource.asMailAddressString()).isEqualTo("*@*");
+    }
+
+    @Test
+    void asMailAddressStringShouldSerializeDomain() {
+        MappingSource mappingSource = MappingSource.fromDomain(Domain.of(DOMAIN));
+
+        assertThat(mappingSource.asMailAddressString()).isEqualTo("*@" + DOMAIN);
+    }
+
+    @Test
+    void asMailAddressStringShouldSerializeUser() {
+        MappingSource mappingSource = MappingSource.fromUser(USER, DOMAIN);
+
+        assertThat(mappingSource.asMailAddressString()).isEqualTo(MAIL_ADDRESS);
+    }
+
+    @Test
+    void asMailAddressStringShouldSerializeUserWithoutDomain() {
+        MappingSource mappingSource = MappingSource.fromUser(User.fromUsername(USER));
+
+        assertThat(mappingSource.asMailAddressString()).isEqualTo(USER + "@*");
+    }
+
+    @Test
+    void asMailAddressStringShouldSerializeMailAddress() throws Exception {
+        MappingSource mappingSource = MappingSource.fromMailAddress(new MailAddress(MAIL_ADDRESS));
+
+        assertThat(mappingSource.asMailAddressString()).isEqualTo(MAIL_ADDRESS);
+    }
+}
\ 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


[15/17] james-project git commit: JAMES-2637 return streams for getSourcesForType and getMappingsForType methods

Posted by bt...@apache.org.
JAMES-2637 return streams for getSourcesForType and getMappingsForType methods


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

Branch: refs/heads/master
Commit: dcb093e5a39aad79377a608d0443f72202befa0e
Parents: 03ee195
Author: Rene Cordier <rc...@linagora.com>
Authored: Tue Jan 15 15:50:52 2019 +0700
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Wed Jan 16 13:48:57 2019 +0700

----------------------------------------------------------------------
 .../java/org/apache/james/rrt/api/RecipientRewriteTable.java    | 5 ++---
 .../java/org/apache/james/webadmin/routes/ForwardRoutes.java    | 2 +-
 .../java/org/apache/james/webadmin/routes/GroupsRoutes.java     | 2 +-
 3 files changed, 4 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/dcb093e5/server/data/data-api/src/main/java/org/apache/james/rrt/api/RecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/api/RecipientRewriteTable.java b/server/data/data-api/src/main/java/org/apache/james/rrt/api/RecipientRewriteTable.java
index 3a15f72..ec0b363 100644
--- a/server/data/data-api/src/main/java/org/apache/james/rrt/api/RecipientRewriteTable.java
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/api/RecipientRewriteTable.java
@@ -126,13 +126,12 @@ public interface RecipientRewriteTable {
             .collect(Guavate.toImmutableList());
     }
 
-    default List<MappingSource> getSourcesForType(Mapping.Type type) throws RecipientRewriteTableException {
+    default Stream<MappingSource> getSourcesForType(Mapping.Type type) throws RecipientRewriteTableException {
         return getAllMappings()
             .entrySet().stream()
             .filter(e -> e.getValue().contains(type))
             .map(Map.Entry::getKey)
-            .sorted(Comparator.comparing(MappingSource::asMailAddressString))
-            .collect(Guavate.toImmutableList());
+            .sorted(Comparator.comparing(MappingSource::asMailAddressString));
     }
 
     default Stream<Mapping> getMappingsForType(Mapping.Type type) throws RecipientRewriteTableException {

http://git-wip-us.apache.org/repos/asf/james-project/blob/dcb093e5/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/ForwardRoutes.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/ForwardRoutes.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/ForwardRoutes.java
index 5484f58..85d6142 100644
--- a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/ForwardRoutes.java
+++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/ForwardRoutes.java
@@ -124,7 +124,7 @@ public class ForwardRoutes implements Routes {
             message = "Internal server error - Something went bad on the server side.")
     })
     public List<MappingSource> listForwards(Request request, Response response) throws RecipientRewriteTableException {
-        return recipientRewriteTable.getSourcesForType(Mapping.Type.Forward);
+        return recipientRewriteTable.getSourcesForType(Mapping.Type.Forward).collect(Guavate.toImmutableList());
     }
 
     @PUT

http://git-wip-us.apache.org/repos/asf/james-project/blob/dcb093e5/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/GroupsRoutes.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/GroupsRoutes.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/GroupsRoutes.java
index f191b31..fdb471b 100644
--- a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/GroupsRoutes.java
+++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/GroupsRoutes.java
@@ -121,7 +121,7 @@ public class GroupsRoutes implements Routes {
             message = "Internal server error - Something went bad on the server side.")
     })
     public List<MappingSource> listGroups(Request request, Response response) throws RecipientRewriteTableException {
-        return recipientRewriteTable.getSourcesForType(Mapping.Type.Group);
+        return recipientRewriteTable.getSourcesForType(Mapping.Type.Group).collect(Guavate.toImmutableList());
     }
 
     @PUT


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


[13/17] james-project git commit: JAMES-2637 getAliasSources should use rrt.listSources

Posted by bt...@apache.org.
JAMES-2637 getAliasSources should use rrt.listSources


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

Branch: refs/heads/master
Commit: c8264529f4aa2be595cbc160b365955fc675170d
Parents: 03420da
Author: Rene Cordier <rc...@linagora.com>
Authored: Tue Jan 15 15:03:31 2019 +0700
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Wed Jan 16 13:48:56 2019 +0700

----------------------------------------------------------------------
 .../java/org/apache/james/webadmin/routes/AliasRoutes.java  | 9 ++++-----
 .../org/apache/james/webadmin/routes/AliasRoutesTest.java   | 4 ++--
 2 files changed, 6 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/c8264529/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AliasRoutes.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AliasRoutes.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AliasRoutes.java
index e88febf..ceb29af 100644
--- a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AliasRoutes.java
+++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AliasRoutes.java
@@ -55,6 +55,7 @@ import org.eclipse.jetty.http.HttpStatus;
 import com.github.steveash.guavate.Guavate;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableSet;
+
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
@@ -221,12 +222,10 @@ public class AliasRoutes implements Routes {
             message = "Internal server error - Something went bad on the server side.")
     })
     public ImmutableSet<AliasSourcesResponse> listAliasesOfAddress(Request request, Response response) throws RecipientRewriteTableException {
-        MailAddress baseAddress = MailAddressParser.parseMailAddress(request.params(ALIAS_DESTINATION_ADDRESS), ADDRESS_TYPE);
+        MailAddress destinationAddress = MailAddressParser.parseMailAddress(request.params(ALIAS_DESTINATION_ADDRESS), ADDRESS_TYPE);
 
-        return recipientRewriteTable.getAllMappings()
-            .entrySet().stream()
-            .filter(e -> e.getValue().contains(Mapping.alias(baseAddress.asString())))
-            .map(Map.Entry::getKey)
+        return recipientRewriteTable.listSources(Mapping.alias(destinationAddress.asString()))
+            .stream()
             .sorted(Comparator.comparing(MappingSource::asMailAddressString))
             .map(AliasSourcesResponse::new)
             .collect(Guavate.toImmutableSet());

http://git-wip-us.apache.org/repos/asf/james-project/blob/c8264529/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/AliasRoutesTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/AliasRoutesTest.java b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/AliasRoutesTest.java
index 3142b8d..5835e49 100644
--- a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/AliasRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/AliasRoutesTest.java
@@ -610,7 +610,7 @@ class AliasRoutesTest {
         void getShouldReturnErrorWhenRecipientRewriteTableExceptionIsThrown() throws Exception {
             doThrow(RecipientRewriteTableException.class)
                 .when(memoryRecipientRewriteTable)
-                .getAllMappings();
+                .listSources(any());
 
             when()
                 .get(BOB)
@@ -622,7 +622,7 @@ class AliasRoutesTest {
         void getShouldReturnErrorWhenRuntimeExceptionIsThrown() throws Exception {
             doThrow(RuntimeException.class)
                 .when(memoryRecipientRewriteTable)
-                .getAllMappings();
+                .listSources(any());
 
             when()
                 .get(BOB)


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


[05/17] james-project git commit: MAILBOX-371 Conversion between RoutingKeys And RegistrationKeys

Posted by bt...@apache.org.
MAILBOX-371 Conversion between RoutingKeys And RegistrationKeys


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

Branch: refs/heads/master
Commit: 74fa711f8c633cf9978ab5c19eb1291d9f3decb2
Parents: c754f3a
Author: datph <dp...@linagora.com>
Authored: Fri Jan 11 10:34:08 2019 +0700
Committer: datph <dp...@linagora.com>
Committed: Wed Jan 16 05:38:45 2019 +0700

----------------------------------------------------------------------
 .../mailbox/events/RoutingKeyConverter.java     |  90 ++++++++++++
 .../mailbox/events/RoutingKeyConverterTest.java | 143 +++++++++++++++++++
 2 files changed, 233 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/74fa711f/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/RoutingKeyConverter.java
----------------------------------------------------------------------
diff --git a/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/RoutingKeyConverter.java b/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/RoutingKeyConverter.java
new file mode 100644
index 0000000..c8a23d1
--- /dev/null
+++ b/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/RoutingKeyConverter.java
@@ -0,0 +1,90 @@
+/****************************************************************
+ * 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.events;
+
+import static org.apache.james.backend.rabbitmq.Constants.EMPTY_ROUTING_KEY;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+
+import javax.inject.Inject;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Joiner;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+
+class RoutingKeyConverter {
+    private static final String SEPARATOR = ":";
+
+    static class RoutingKey {
+
+        static RoutingKey empty() {
+            return new RoutingKey(Optional.empty());
+        }
+
+        static RoutingKey of(RegistrationKey key) {
+            return new RoutingKey(Optional.of(key));
+        }
+
+        private final Optional<RegistrationKey> registrationKey;
+
+        private RoutingKey(Optional<RegistrationKey> registrationKey) {
+            this.registrationKey = registrationKey;
+        }
+
+        String asString() {
+            return registrationKey.map(key -> key.getClass().getName() + SEPARATOR + key.asString())
+                .orElse(EMPTY_ROUTING_KEY);
+        }
+    }
+
+    @VisibleForTesting
+    static RoutingKeyConverter forFactories(RegistrationKey.Factory... factories) {
+        return new RoutingKeyConverter(ImmutableSet.copyOf(factories));
+    }
+
+    private final Set<RegistrationKey.Factory> factories;
+
+    @Inject
+    RoutingKeyConverter(Set<RegistrationKey.Factory> factories) {
+        this.factories = factories;
+    }
+
+    RegistrationKey toRegistrationKey(String routingKey) {
+        return toRegistrationKey(Splitter.on(SEPARATOR).splitToList(routingKey));
+    }
+
+    private RegistrationKey toRegistrationKey(List<String> parts) {
+        Preconditions.checkArgument(parts.size() >= 2, "Routing key needs to match the 'classFQDN:value' pattern");
+
+        String registrationClass = parts.get(0);
+        String value = Joiner.on(SEPARATOR).join(Iterables.skip(parts, 1));
+
+        return factories.stream()
+            .filter(factory -> factory.forClass().getName().equals(registrationClass))
+            .findAny()
+            .orElseThrow(() -> new IllegalArgumentException("No factory for " + registrationClass))
+            .fromString(value);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/74fa711f/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RoutingKeyConverterTest.java
----------------------------------------------------------------------
diff --git a/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RoutingKeyConverterTest.java b/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RoutingKeyConverterTest.java
new file mode 100644
index 0000000..4b158dc
--- /dev/null
+++ b/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RoutingKeyConverterTest.java
@@ -0,0 +1,143 @@
+/****************************************************************
+ * 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.events;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.util.Objects;
+
+import org.apache.james.mailbox.model.TestId;
+import org.junit.jupiter.api.Test;
+
+class RoutingKeyConverterTest {
+    static class TestRegistrationKey implements RegistrationKey {
+        static class Factory implements RegistrationKey.Factory {
+            @Override
+            public Class<? extends RegistrationKey> forClass() {
+                return TestRegistrationKey.class;
+            }
+
+            @Override
+            public RegistrationKey fromString(String asString) {
+                return new TestRegistrationKey(asString);
+            }
+        }
+
+        private final String value;
+
+        TestRegistrationKey(String value) {
+            this.value = value;
+        }
+
+        @Override
+        public String asString() {
+            return value;
+        }
+
+        @Override
+        public final boolean equals(Object o) {
+            if (o instanceof TestRegistrationKey) {
+                TestRegistrationKey that = (TestRegistrationKey) o;
+
+                return Objects.equals(this.value, that.value);
+            }
+            return false;
+        }
+
+        @Override
+        public final int hashCode() {
+            return Objects.hash(value);
+        }
+    }
+
+    private static final RegistrationKey REGISTRATION_KEY_1 = new MailboxIdRegistrationKey(TestId.of(42));
+    private static final String ROUTING_KEY_1 = "org.apache.james.mailbox.events.MailboxIdRegistrationKey:42";
+
+    private RoutingKeyConverter testee = RoutingKeyConverter.forFactories(
+        new TestRegistrationKey.Factory(),
+        new MailboxIdRegistrationKey.Factory(new TestId.Factory()));
+
+    @Test
+    void toRoutingKeyShouldTransformAKeyIntoAString() {
+        assertThat(RoutingKeyConverter.RoutingKey.of(REGISTRATION_KEY_1).asString())
+            .isEqualTo(ROUTING_KEY_1);
+    }
+
+    @Test
+    void toRegistrationKeyShouldReturnCorrespondingRoutingKey() {
+        assertThat(testee.toRegistrationKey(ROUTING_KEY_1))
+            .isEqualTo(REGISTRATION_KEY_1);
+    }
+
+    @Test
+    void toRoutingKeyShouldAcceptSeparator() {
+        assertThat(RoutingKeyConverter.RoutingKey.of(new TestRegistrationKey("a:b")).asString())
+            .isEqualTo("org.apache.james.mailbox.events.RoutingKeyConverterTest$TestRegistrationKey:a:b");
+    }
+
+    @Test
+    void toRegistrationKeyShouldAcceptSeparator() {
+        assertThat(testee.toRegistrationKey("org.apache.james.mailbox.events.RoutingKeyConverterTest$TestRegistrationKey:a:b"))
+            .isEqualTo(new TestRegistrationKey("a:b"));
+    }
+
+    @Test
+    void toRoutingKeyShouldAcceptEmptyValue() {
+        assertThat(RoutingKeyConverter.RoutingKey.of(new TestRegistrationKey("")).asString())
+            .isEqualTo("org.apache.james.mailbox.events.RoutingKeyConverterTest$TestRegistrationKey:");
+    }
+
+    @Test
+    void toRegistrationKeyShouldAcceptEmptyValue() {
+        assertThat(testee.toRegistrationKey("org.apache.james.mailbox.events.RoutingKeyConverterTest$TestRegistrationKey:"))
+            .isEqualTo(new TestRegistrationKey(""));
+    }
+
+    @Test
+    void toRegistrationKeyShouldRejectNull() {
+        assertThatThrownBy(() -> testee.toRegistrationKey(null))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    void toRegistrationKeyShouldRejectEmptyString() {
+        assertThatThrownBy(() -> testee.toRegistrationKey(""))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    void toRegistrationKeyShouldRejectNoSeparator() {
+        assertThatThrownBy(() -> testee.toRegistrationKey("noSeparator"))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    void toRegistrationKeyShouldRejectUnknownRegistrationKeyClass() {
+        assertThatThrownBy(() -> testee.toRegistrationKey("unknown:"))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    void toRegistrationKeyShouldRejectInvalidValue() {
+        assertThatThrownBy(() -> testee.toRegistrationKey("org.apache.james.mailbox.events.MailboxIdRegistrationKey:invalid"))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+}


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


[07/17] james-project git commit: MAILBOX-371 Add Concurrent Test for RabbitMQEventBus with Key Registration

Posted by bt...@apache.org.
MAILBOX-371 Add Concurrent Test for RabbitMQEventBus with Key Registration


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

Branch: refs/heads/master
Commit: af95d7b1fab41a476d947a1aa66f6aaa73304405
Parents: 9f3b7ec
Author: datph <dp...@linagora.com>
Authored: Mon Jan 14 13:42:37 2019 +0700
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Wed Jan 16 13:47:08 2019 +0700

----------------------------------------------------------------------
 .../events/EventBusConcurrentTestContract.java  | 127 +++++++++++++++++++
 .../mailbox/events/EventBusTestFixture.java     |   2 +
 .../james/mailbox/events/KeyContract.java       |   3 +
 .../mailbox/events/RabbitMQEventBusTest.java    |  29 +++--
 4 files changed, 148 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/af95d7b1/mailbox/api/src/test/java/org/apache/james/mailbox/events/EventBusConcurrentTestContract.java
----------------------------------------------------------------------
diff --git a/mailbox/api/src/test/java/org/apache/james/mailbox/events/EventBusConcurrentTestContract.java b/mailbox/api/src/test/java/org/apache/james/mailbox/events/EventBusConcurrentTestContract.java
index 0746612..2f6e9cb 100644
--- a/mailbox/api/src/test/java/org/apache/james/mailbox/events/EventBusConcurrentTestContract.java
+++ b/mailbox/api/src/test/java/org/apache/james/mailbox/events/EventBusConcurrentTestContract.java
@@ -21,16 +21,22 @@ package org.apache.james.mailbox.events;
 
 import static com.jayway.awaitility.Awaitility.await;
 import static org.apache.james.mailbox.events.EventBusTestFixture.EVENT;
+import static org.apache.james.mailbox.events.EventBusTestFixture.KEY_1;
+import static org.apache.james.mailbox.events.EventBusTestFixture.KEY_2;
+import static org.apache.james.mailbox.events.EventBusTestFixture.KEY_3;
 import static org.apache.james.mailbox.events.EventBusTestFixture.NO_KEYS;
+import static org.apache.james.mailbox.events.EventDeadLettersContract.GROUP_A;
 import static org.assertj.core.api.Assertions.assertThat;
 
 import java.time.Duration;
+import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.james.util.concurrency.ConcurrentTestRunner;
 import org.junit.jupiter.api.Test;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
 import com.jayway.awaitility.core.ConditionFactory;
 
 public interface EventBusConcurrentTestContract {
@@ -42,6 +48,8 @@ public interface EventBusConcurrentTestContract {
     int OPERATION_COUNT = 30;
     int TOTAL_DISPATCH_OPERATIONS = THREAD_COUNT * OPERATION_COUNT;
 
+    Set<RegistrationKey> ALL_KEYS = ImmutableSet.of(KEY_1, KEY_2, KEY_3);
+
     static EventBusTestFixture.MailboxListenerCountingSuccessfulExecution newCountingListener() {
         return new EventBusTestFixture.MailboxListenerCountingSuccessfulExecution();
     }
@@ -75,10 +83,65 @@ public interface EventBusConcurrentTestContract {
                     .of(countingListener1, countingListener2, countingListener3)))
                 .isEqualTo(totalGlobalRegistrations * TOTAL_DISPATCH_OPERATIONS));
         }
+
+        @Test
+        default void concurrentDispatchKeyShouldDeliverAllEventsToListenersWithSingleEventBus() throws Exception {
+            EventBusTestFixture.MailboxListenerCountingSuccessfulExecution countingListener1 = newCountingListener();
+            EventBusTestFixture.MailboxListenerCountingSuccessfulExecution countingListener2 = newCountingListener();
+            EventBusTestFixture.MailboxListenerCountingSuccessfulExecution countingListener3 = newCountingListener();
+            eventBus().register(countingListener1, KEY_1);
+            eventBus().register(countingListener2, KEY_2);
+            eventBus().register(countingListener3, KEY_3);
+
+            int totalKeyListenerRegistrations = 3; // KEY1 + KEY2 + KEY3
+            int totalEventBus = 1;
+
+            ConcurrentTestRunner.builder()
+                .operation((threadNumber, operationNumber) -> eventBus().dispatch(EVENT, ALL_KEYS))
+                .threadCount(THREAD_COUNT)
+                .operationCount(OPERATION_COUNT)
+                .runSuccessfullyWithin(FIVE_SECONDS);
+
+            AWAIT_CONDITION.until(() -> assertThat(totalEventsReceived(ImmutableList
+                    .of(countingListener1, countingListener2, countingListener3)))
+                .isEqualTo(totalKeyListenerRegistrations * totalEventBus * TOTAL_DISPATCH_OPERATIONS));
+        }
+
+        @Test
+        default void concurrentDispatchShouldDeliverAllEventsToListenersWithSingleEventBus() throws Exception {
+            EventBusTestFixture.MailboxListenerCountingSuccessfulExecution countingListener1 = newCountingListener();
+            EventBusTestFixture.MailboxListenerCountingSuccessfulExecution countingListener2 = newCountingListener();
+            EventBusTestFixture.MailboxListenerCountingSuccessfulExecution countingListener3 = newCountingListener();
+
+            eventBus().register(countingListener1, new EventBusTestFixture.GroupA());
+            eventBus().register(countingListener2, new EventBusTestFixture.GroupB());
+            eventBus().register(countingListener3, new EventBusTestFixture.GroupC());
+
+            int totalGlobalRegistrations = 3; // GroupA + GroupB + GroupC
+            int totalEventDeliveredGlobally = totalGlobalRegistrations * TOTAL_DISPATCH_OPERATIONS;
+
+            eventBus().register(countingListener1, KEY_1);
+            eventBus().register(countingListener2, KEY_2);
+            eventBus().register(countingListener3, KEY_3);
+            int totalKeyListenerRegistrations = 3; // KEY1 + KEY2 + KEY3
+            int totalEventDeliveredByKeys = totalKeyListenerRegistrations * TOTAL_DISPATCH_OPERATIONS;
+
+            ConcurrentTestRunner.builder()
+                .operation((threadNumber, operationNumber) -> eventBus().dispatch(EVENT, ALL_KEYS))
+                .threadCount(THREAD_COUNT)
+                .operationCount(OPERATION_COUNT)
+                .runSuccessfullyWithin(FIVE_SECONDS);
+
+            AWAIT_CONDITION.until(() -> assertThat(totalEventsReceived(ImmutableList
+                    .of(countingListener1, countingListener2, countingListener3)))
+                .isEqualTo(totalEventDeliveredGlobally + totalEventDeliveredByKeys));
+        }
     }
 
     interface MultiEventBusConcurrentContract extends EventBusContract.MultipleEventBusContract {
 
+        EventBus eventBus3();
+
         @Test
         default void concurrentDispatchGroupShouldDeliverAllEventsToListenersWithMultipleEventBus() throws Exception {
             EventBusTestFixture.MailboxListenerCountingSuccessfulExecution countingListener1 = newCountingListener();
@@ -105,5 +168,69 @@ public interface EventBusConcurrentTestContract {
                     .of(countingListener1, countingListener2, countingListener3)))
                 .isEqualTo(totalGlobalRegistrations * TOTAL_DISPATCH_OPERATIONS));
         }
+
+        @Test
+        default void concurrentDispatchKeyShouldDeliverAllEventsToListenersWithMultipleEventBus() throws Exception {
+            EventBusTestFixture.MailboxListenerCountingSuccessfulExecution countingListener1 = newCountingListener();
+            EventBusTestFixture.MailboxListenerCountingSuccessfulExecution countingListener2 = newCountingListener();
+            EventBusTestFixture.MailboxListenerCountingSuccessfulExecution countingListener3 = newCountingListener();
+
+            eventBus().register(countingListener1, KEY_1);
+            eventBus().register(countingListener2, KEY_2);
+            eventBus().register(countingListener3, KEY_3);
+
+            eventBus2().register(countingListener1, KEY_1);
+            eventBus2().register(countingListener2, KEY_2);
+            eventBus2().register(countingListener3, KEY_3);
+
+            int totalKeyListenerRegistrations = 3; // KEY1 + KEY2 + KEY3
+            int totalEventBus = 2; // eventBus1 + eventBus2
+
+            ConcurrentTestRunner.builder()
+                .operation((threadNumber, operationNumber) -> eventBus().dispatch(EVENT, ALL_KEYS))
+                .threadCount(THREAD_COUNT)
+                .operationCount(OPERATION_COUNT)
+                .runSuccessfullyWithin(FIVE_SECONDS);
+
+            AWAIT_CONDITION.until(() -> assertThat(totalEventsReceived(ImmutableList
+                    .of(countingListener1, countingListener2, countingListener3)))
+                .isEqualTo(totalKeyListenerRegistrations * totalEventBus * TOTAL_DISPATCH_OPERATIONS));
+        }
+
+        @Test
+        default void concurrentDispatchShouldDeliverAllEventsToListenersWithMultipleEventBus() throws Exception {
+            EventBusTestFixture.MailboxListenerCountingSuccessfulExecution countingListener1 = newCountingListener();
+            EventBusTestFixture.MailboxListenerCountingSuccessfulExecution countingListener2 = newCountingListener();
+            EventBusTestFixture.MailboxListenerCountingSuccessfulExecution countingListener3 = newCountingListener();
+
+            eventBus2().register(countingListener1, GROUP_A);
+            eventBus2().register(countingListener2, new EventBusTestFixture.GroupB());
+            eventBus2().register(countingListener3, new EventBusTestFixture.GroupC());
+            int totalGlobalRegistrations = 3; // GroupA + GroupB + GroupC
+            int totalEventDeliveredGlobally = totalGlobalRegistrations * TOTAL_DISPATCH_OPERATIONS;
+
+            eventBus().register(countingListener1, KEY_1);
+            eventBus().register(countingListener2, KEY_2);
+
+            eventBus2().register(countingListener1, KEY_1);
+            eventBus2().register(countingListener2, KEY_2);
+
+            eventBus3().register(countingListener3, KEY_1);
+            eventBus3().register(countingListener3, KEY_2);
+
+            int totalKeyListenerRegistrations = 2; // KEY1 + KEY2
+            int totalEventBus = 3; // eventBus1 + eventBus2 + eventBus3
+            int totalEventDeliveredByKeys = totalKeyListenerRegistrations * totalEventBus * TOTAL_DISPATCH_OPERATIONS;
+
+            ConcurrentTestRunner.builder()
+                .operation((threadNumber, operationNumber) -> eventBus().dispatch(EVENT, ALL_KEYS))
+                .threadCount(THREAD_COUNT)
+                .operationCount(OPERATION_COUNT)
+                .runSuccessfullyWithin(FIVE_SECONDS);
+
+            AWAIT_CONDITION.until(() -> assertThat(totalEventsReceived(ImmutableList
+                    .of(countingListener1, countingListener2, countingListener3)))
+                .isEqualTo(totalEventDeliveredGlobally + totalEventDeliveredByKeys));
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/af95d7b1/mailbox/api/src/test/java/org/apache/james/mailbox/events/EventBusTestFixture.java
----------------------------------------------------------------------
diff --git a/mailbox/api/src/test/java/org/apache/james/mailbox/events/EventBusTestFixture.java b/mailbox/api/src/test/java/org/apache/james/mailbox/events/EventBusTestFixture.java
index 90f5ff5..e6920c0 100644
--- a/mailbox/api/src/test/java/org/apache/james/mailbox/events/EventBusTestFixture.java
+++ b/mailbox/api/src/test/java/org/apache/james/mailbox/events/EventBusTestFixture.java
@@ -92,9 +92,11 @@ public interface EventBusTestFixture {
     int FIVE_HUNDRED_MS = 500;
     MailboxId ID_1 = TEST_ID;
     MailboxId ID_2 = TestId.of(24);
+    MailboxId ID_3 = TestId.of(36);
     ImmutableSet<RegistrationKey> NO_KEYS = ImmutableSet.of();
     MailboxIdRegistrationKey KEY_1 = new MailboxIdRegistrationKey(ID_1);
     MailboxIdRegistrationKey KEY_2 = new MailboxIdRegistrationKey(ID_2);
+    MailboxIdRegistrationKey KEY_3 = new MailboxIdRegistrationKey(ID_3);
     List<Class<? extends Group>> ALL_GROUPS = ImmutableList.of(GroupA.class, GroupB.class, GroupC.class);
 
     GroupA GROUP_A = new GroupA();

http://git-wip-us.apache.org/repos/asf/james-project/blob/af95d7b1/mailbox/api/src/test/java/org/apache/james/mailbox/events/KeyContract.java
----------------------------------------------------------------------
diff --git a/mailbox/api/src/test/java/org/apache/james/mailbox/events/KeyContract.java b/mailbox/api/src/test/java/org/apache/james/mailbox/events/KeyContract.java
index f50a66d..1421174 100644
--- a/mailbox/api/src/test/java/org/apache/james/mailbox/events/KeyContract.java
+++ b/mailbox/api/src/test/java/org/apache/james/mailbox/events/KeyContract.java
@@ -251,6 +251,9 @@ public interface KeyContract extends EventBusContract {
         default void failingRegisteredListenersShouldNotAbortRegisteredDelivery() {
             EventBusTestFixture.MailboxListenerCountingSuccessfulExecution listener = spy(new EventBusTestFixture.MailboxListenerCountingSuccessfulExecution());
             doThrow(new RuntimeException())
+                .doThrow(new RuntimeException())
+                .doThrow(new RuntimeException())
+                .doThrow(new RuntimeException())
                 .doCallRealMethod()
                 .when(listener).event(any());
             eventBus().register(listener, KEY_1);

http://git-wip-us.apache.org/repos/asf/james-project/blob/af95d7b1/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RabbitMQEventBusTest.java
----------------------------------------------------------------------
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 aa4c5c6..52a6e50 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
@@ -116,6 +116,7 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
 
     private RabbitMQEventBus eventBus;
     private RabbitMQEventBus eventBus2;
+    private RabbitMQEventBus eventBus3;
     private Sender sender;
     private RabbitMQConnectionFactory connectionFactory;
     private EventSerializer eventSerializer;
@@ -132,8 +133,10 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
 
         eventBus = new RabbitMQEventBus(connectionFactory, eventSerializer, routingKeyConverter);
         eventBus2 = new RabbitMQEventBus(connectionFactory, eventSerializer, routingKeyConverter);
+        eventBus3 = new RabbitMQEventBus(connectionFactory, eventSerializer, routingKeyConverter);
         eventBus.start();
         eventBus2.start();
+        eventBus3.start();
         sender = RabbitFlux.createSender(new SenderOptions().connectionMono(connectionMono));
     }
 
@@ -141,6 +144,7 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
     void tearDown() {
         eventBus.stop();
         eventBus2.stop();
+        eventBus3.stop();
         ALL_GROUPS.stream()
             .map(groupClass -> GroupRegistration.WorkQueueName.of(groupClass).asString())
             .forEach(queueName -> sender.delete(QueueSpecification.queue(queueName)).block());
@@ -159,6 +163,18 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
     }
 
     @Override
+    public EventBus eventBus3() {
+        return eventBus3;
+    }
+
+    @Override
+    @Test
+    @Disabled("This test is failing by RabbitMQEventBus exponential backoff is not implemented at this time")
+    public void failingRegisteredListenersShouldNotAbortRegisteredDelivery() {
+
+    }
+
+    @Override
     @Test
     @Disabled("This test is failing by design as the different registration keys are handled by distinct messages")
     public void dispatchShouldCallListenerOnceWhenSeveralKeysMatching() {
@@ -304,19 +320,6 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
         @Nested
         class MultiEventBus {
 
-            private RabbitMQEventBus eventBus3;
-
-            @BeforeEach
-            void setUp() {
-                eventBus3 = new RabbitMQEventBus(connectionFactory, eventSerializer, routingKeyConverter);
-                eventBus3.start();
-            }
-
-            @AfterEach
-            void tearDown() {
-                eventBus3.stop();
-            }
-
             @Test
             void multipleEventBusStartShouldCreateOnlyOneEventExchange() {
                 assertThat(rabbitManagementAPI.listExchanges())


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


[12/17] james-project git commit: JAMES-2637 add rest of the routes for alias routes

Posted by bt...@apache.org.
JAMES-2637 add rest of the routes for alias routes


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

Branch: refs/heads/master
Commit: b312b877cf92e2930d15f222462e97c7bd1799fc
Parents: 5b9b106
Author: Rene Cordier <rc...@linagora.com>
Authored: Thu Jan 10 17:33:34 2019 +0700
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Wed Jan 16 13:48:56 2019 +0700

----------------------------------------------------------------------
 .../rrt/api/MappingAlreadyExistsException.java  |   4 -
 .../api/SameSourceAndDestinationException.java  |   4 -
 .../integration/UnauthorizedEndpointsTest.java  |   3 +
 .../webadmin/dto/AliasSourcesResponse.java      |  32 ++
 .../james/webadmin/routes/AliasRoutes.java      |  95 +++++-
 .../james/webadmin/routes/AliasRoutesTest.java  | 299 +++++++++++++++++--
 src/site/markdown/server/manage-webadmin.md     |  53 ++++
 7 files changed, 457 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/b312b877/server/data/data-api/src/main/java/org/apache/james/rrt/api/MappingAlreadyExistsException.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/api/MappingAlreadyExistsException.java b/server/data/data-api/src/main/java/org/apache/james/rrt/api/MappingAlreadyExistsException.java
index 4d80ad8..ef0d49f 100644
--- a/server/data/data-api/src/main/java/org/apache/james/rrt/api/MappingAlreadyExistsException.java
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/api/MappingAlreadyExistsException.java
@@ -23,8 +23,4 @@ public class MappingAlreadyExistsException extends RecipientRewriteTableExceptio
     public MappingAlreadyExistsException(String msg) {
         super(msg);
     }
-
-    public MappingAlreadyExistsException(String msg, Throwable t) {
-        super(msg, t);
-    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/b312b877/server/data/data-api/src/main/java/org/apache/james/rrt/api/SameSourceAndDestinationException.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/api/SameSourceAndDestinationException.java b/server/data/data-api/src/main/java/org/apache/james/rrt/api/SameSourceAndDestinationException.java
index d76ffcb..c675c2c 100644
--- a/server/data/data-api/src/main/java/org/apache/james/rrt/api/SameSourceAndDestinationException.java
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/api/SameSourceAndDestinationException.java
@@ -24,8 +24,4 @@ public class SameSourceAndDestinationException extends RecipientRewriteTableExce
     public SameSourceAndDestinationException(String msg) {
         super(msg);
     }
-
-    public SameSourceAndDestinationException(String msg, Throwable t) {
-        super(msg, t);
-    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/b312b877/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/UnauthorizedEndpointsTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/UnauthorizedEndpointsTest.java b/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/UnauthorizedEndpointsTest.java
index f20b041..14abe53 100644
--- a/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/UnauthorizedEndpointsTest.java
+++ b/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/UnauthorizedEndpointsTest.java
@@ -79,6 +79,8 @@ class UnauthorizedEndpointsTest {
             UserRoutes.USERS,
             ForwardRoutes.ROOT_PATH,
             ForwardRoutes.ROOT_PATH + "/alice@james.org",
+            AliasRoutes.ROOT_PATH,
+            AliasRoutes.ROOT_PATH + "/bob@james.org",
             GlobalQuotaRoutes.QUOTA_ENDPOINT,
             GlobalQuotaRoutes.QUOTA_ENDPOINT + "/count",
             GlobalQuotaRoutes.QUOTA_ENDPOINT + "/size",
@@ -157,6 +159,7 @@ class UnauthorizedEndpointsTest {
             UserQuotaRoutes.USERS_QUOTA_ENDPOINT + "/joe@perdu.com/size",
             UserRoutes.USERS + "/user@james.org",
             ForwardRoutes.ROOT_PATH + "/alice@james.org/bob@james.org",
+            AliasRoutes.ROOT_PATH + "/bob@james.org/sources/bob-alias@james.org",
             GlobalQuotaRoutes.QUOTA_ENDPOINT + "/count",
             GlobalQuotaRoutes.QUOTA_ENDPOINT + "/size",
             GroupsRoutes.ROOT_PATH + "/group@james.org/user@james.org",

http://git-wip-us.apache.org/repos/asf/james-project/blob/b312b877/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/AliasSourcesResponse.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/AliasSourcesResponse.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/AliasSourcesResponse.java
new file mode 100644
index 0000000..a57988b
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/AliasSourcesResponse.java
@@ -0,0 +1,32 @@
+/****************************************************************
+ * 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.webadmin.dto;
+
+public class AliasSourcesResponse {
+    private final String source;
+
+    public AliasSourcesResponse(String source) {
+        this.source = source;
+    }
+
+    public String getSource() {
+        return source;
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/b312b877/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AliasRoutes.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AliasRoutes.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AliasRoutes.java
index 0a06aa0..43004d0 100644
--- a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AliasRoutes.java
+++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AliasRoutes.java
@@ -22,7 +22,12 @@ package org.apache.james.webadmin.routes;
 import static org.apache.james.webadmin.Constants.SEPARATOR;
 import static spark.Spark.halt;
 
+import java.util.List;
+import java.util.Map;
+
 import javax.inject.Inject;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
@@ -33,15 +38,22 @@ import org.apache.james.rrt.api.MappingAlreadyExistsException;
 import org.apache.james.rrt.api.RecipientRewriteTable;
 import org.apache.james.rrt.api.RecipientRewriteTableException;
 import org.apache.james.rrt.api.SameSourceAndDestinationException;
+import org.apache.james.rrt.lib.Mapping;
 import org.apache.james.rrt.lib.MappingSource;
+import org.apache.james.rrt.lib.Mappings;
 import org.apache.james.user.api.UsersRepository;
 import org.apache.james.user.api.UsersRepositoryException;
+import org.apache.james.util.OptionalUtils;
 import org.apache.james.webadmin.Constants;
 import org.apache.james.webadmin.Routes;
+import org.apache.james.webadmin.dto.AliasSourcesResponse;
 import org.apache.james.webadmin.utils.ErrorResponder;
+import org.apache.james.webadmin.utils.JsonTransformer;
 import org.eclipse.jetty.http.HttpStatus;
 
+import com.github.steveash.guavate.Guavate;
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableSet;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
@@ -70,12 +82,14 @@ public class AliasRoutes implements Routes {
     private static final String ADDRESS_TYPE = "alias";
 
     private final UsersRepository usersRepository;
+    private final JsonTransformer jsonTransformer;
     private final RecipientRewriteTable recipientRewriteTable;
 
     @Inject
     @VisibleForTesting
-    AliasRoutes(RecipientRewriteTable recipientRewriteTable, UsersRepository usersRepository) {
+    AliasRoutes(RecipientRewriteTable recipientRewriteTable, UsersRepository usersRepository, JsonTransformer jsonTransformer) {
         this.usersRepository = usersRepository;
+        this.jsonTransformer = jsonTransformer;
         this.recipientRewriteTable = recipientRewriteTable;
     }
 
@@ -86,7 +100,29 @@ public class AliasRoutes implements Routes {
 
     @Override
     public void define(Service service) {
-        service.put(USER_IN_ALIAS_SOURCES_ADDRESSES_PATH, this::addToAliasSources);
+        service.get(ROOT_PATH, this::listAddressesWithAliases, jsonTransformer);
+        service.get(ALIAS_ADDRESS_PATH, this::listAliasesOfAddress, jsonTransformer);
+        service.put(USER_IN_ALIAS_SOURCES_ADDRESSES_PATH, this::addAlias);
+        service.delete(USER_IN_ALIAS_SOURCES_ADDRESSES_PATH, this::deleteAlias);
+    }
+
+    @GET
+    @Path(ROOT_PATH)
+    @ApiOperation(value = "getting addresses containing aliases list")
+    @ApiResponses(value = {
+        @ApiResponse(code = HttpStatus.OK_200, message = "OK", response = List.class),
+        @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500,
+            message = "Internal server error - Something went bad on the server side.")
+    })
+    public ImmutableSet<String> listAddressesWithAliases(Request request, Response response) throws RecipientRewriteTableException {
+        return recipientRewriteTable.getAllMappings()
+            .entrySet().stream()
+            .filter(e -> e.getValue().contains(Mapping.Type.Alias))
+            .map(Map.Entry::getValue)
+            .flatMap(Mappings::asStream)
+            .flatMap(mapping -> OptionalUtils.toStream(mapping.asMailAddress()))
+            .map(MailAddress::asString)
+            .collect(Guavate.toImmutableSortedSet());
     }
 
     @PUT
@@ -106,10 +142,11 @@ public class AliasRoutes implements Routes {
         @ApiResponse(code = HttpStatus.NO_CONTENT_204, message = "OK"),
         @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = ALIAS_DESTINATION_ADDRESS + " or alias structure format is not valid"),
         @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "The alias source exists as an user already"),
+        @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Source and destination can't be the same!"),
         @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500,
             message = "Internal server error - Something went bad on the server side.")
     })
-    public HaltException addToAliasSources(Request request, Response response) throws UsersRepositoryException, RecipientRewriteTableException {
+    public HaltException addAlias(Request request, Response response) throws UsersRepositoryException, RecipientRewriteTableException {
         MailAddress aliasSourceAddress = MailAddressParser.parseMailAddress(request.params(ALIAS_SOURCE_ADDRESS), ADDRESS_TYPE);
         ensureUserDoesNotExist(aliasSourceAddress);
         MailAddress destinationAddress = MailAddressParser.parseMailAddress(request.params(ALIAS_DESTINATION_ADDRESS), ADDRESS_TYPE);
@@ -143,4 +180,56 @@ public class AliasRoutes implements Routes {
                 .haltError();
         }
     }
+
+    @DELETE
+    @Path(ROOT_PATH + "/{" + ALIAS_DESTINATION_ADDRESS + "}/sources/{" + ALIAS_SOURCE_ADDRESS + "}")
+    @ApiOperation(value = "remove an alias from a destination address")
+    @ApiImplicitParams({
+        @ApiImplicitParam(required = true, dataType = "string", name = ALIAS_DESTINATION_ADDRESS, paramType = "path",
+            value = "Destination mail address of the alias to remove.\n" +
+                MAILADDRESS_ASCII_DISCLAIMER),
+        @ApiImplicitParam(required = true, dataType = "string", name = ALIAS_SOURCE_ADDRESS, paramType = "path",
+            value = "Source mail address of the alias to remove.\n" +
+                MAILADDRESS_ASCII_DISCLAIMER)
+    })
+    @ApiResponses(value = {
+        @ApiResponse(code = HttpStatus.NO_CONTENT_204, message = "OK"),
+        @ApiResponse(code = HttpStatus.BAD_REQUEST_400,
+            message = ALIAS_DESTINATION_ADDRESS + " or alias structure format is not valid"),
+        @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500,
+            message = "Internal server error - Something went bad on the server side.")
+    })
+    public HaltException deleteAlias(Request request, Response response) throws RecipientRewriteTableException {
+        MailAddress destinationAddress = MailAddressParser.parseMailAddress(request.params(ALIAS_DESTINATION_ADDRESS), ADDRESS_TYPE);
+        MailAddress aliasToBeRemoved = MailAddressParser.parseMailAddress(request.params(ALIAS_SOURCE_ADDRESS), ADDRESS_TYPE);
+        MappingSource source = MappingSource.fromMailAddress(aliasToBeRemoved);
+        recipientRewriteTable.removeAliasMapping(source, destinationAddress.asString());
+        return halt(HttpStatus.NO_CONTENT_204);
+    }
+
+    @GET
+    @Path(ROOT_PATH + "/{" + ALIAS_DESTINATION_ADDRESS + "}")
+    @ApiOperation(value = "listing alias sources of an address")
+    @ApiImplicitParams({
+        @ApiImplicitParam(required = true, dataType = "string", name = ALIAS_DESTINATION_ADDRESS, paramType = "path")
+    })
+    @ApiResponses(value = {
+        @ApiResponse(code = HttpStatus.OK_200, message = "OK", response = List.class),
+        @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "The destination is not an address"),
+        @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500,
+            message = "Internal server error - Something went bad on the server side.")
+    })
+    public ImmutableSet<AliasSourcesResponse> listAliasesOfAddress(Request request, Response response) throws RecipientRewriteTableException {
+        MailAddress baseAddress = MailAddressParser.parseMailAddress(request.params(ALIAS_DESTINATION_ADDRESS), ADDRESS_TYPE);
+
+        return recipientRewriteTable.getAllMappings()
+            .entrySet().stream()
+            .filter(e -> e.getValue().contains(Mapping.alias(baseAddress.asString())))
+            .map(Map.Entry::getKey)
+            .flatMap(source -> OptionalUtils.toStream(source.asMailAddress()))
+            .map(MailAddress::asString)
+            .sorted()
+            .map(AliasSourcesResponse::new)
+            .collect(Guavate.toImmutableSet());
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/b312b877/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/AliasRoutesTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/AliasRoutesTest.java b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/AliasRoutesTest.java
index 5faad03..af6e4e1 100644
--- a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/AliasRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/AliasRoutesTest.java
@@ -31,13 +31,13 @@ import org.apache.james.domainlist.memory.MemoryDomainList;
 import org.apache.james.metrics.logger.DefaultMetricFactory;
 import org.apache.james.rrt.api.RecipientRewriteTable;
 import org.apache.james.rrt.api.RecipientRewriteTableException;
-import org.apache.james.rrt.lib.Mapping;
 import org.apache.james.rrt.lib.MappingSource;
 import org.apache.james.rrt.memory.MemoryRecipientRewriteTable;
 import org.apache.james.user.api.UsersRepository;
 import org.apache.james.user.memory.MemoryUsersRepository;
 import org.apache.james.webadmin.WebAdminServer;
 import org.apache.james.webadmin.WebAdminUtils;
+import org.apache.james.webadmin.utils.JsonTransformer;
 import org.eclipse.jetty.http.HttpStatus;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
@@ -45,6 +45,7 @@ import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
 
+import java.util.List;
 import java.util.Map;
 
 import static io.restassured.RestAssured.given;
@@ -53,6 +54,8 @@ import static io.restassured.RestAssured.with;
 import static org.apache.james.webadmin.Constants.SEPARATOR;
 import static org.apache.james.webadmin.WebAdminServer.NO_CONFIGURATION;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.CoreMatchers.hasItems;
+import static org.hamcrest.CoreMatchers.is;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.doThrow;
@@ -69,15 +72,11 @@ class AliasRoutesTest {
     public static final String BOB_ALIAS_WITH_SLASH = "bob-alias/@" + DOMAIN.name();
     public static final String BOB_ALIAS_WITH_ENCODED_SLASH = "bob-alias%2F@" + DOMAIN.name();
     public static final String ALICE = "alice@" + DOMAIN.name();
+    public static final String ALICE_ALIAS = "alice-alias@" + DOMAIN.name();
     public static final String BOB_PASSWORD = "123456";
     public static final String BOB_WITH_SLASH_PASSWORD = "abcdef";
     public static final String ALICE_PASSWORD = "789123";
 
-    private static final MappingSource BOB_ALIAS_SOURCE = MappingSource.fromUser("bob-alias", DOMAIN);
-    private static final MappingSource BOB_ALIAS_WITH_ENCODED_SLASH_SOURCE = MappingSource.fromUser("bob-alias/", DOMAIN);
-    private static final Mapping BOB_MAPPING = Mapping.alias(BOB);
-    private static final Mapping BOB_WITH_ENCODED_SLASH_MAPPING = Mapping.alias(BOB_WITH_SLASH);
-
     private WebAdminServer webAdminServer;
 
     private void createServer(AliasRoutes aliasRoutes) throws Exception {
@@ -123,7 +122,58 @@ class AliasRoutesTest {
             usersRepository.addUser(BOB_WITH_SLASH, BOB_WITH_SLASH_PASSWORD);
             usersRepository.addUser(ALICE, ALICE_PASSWORD);
 
-            createServer(new AliasRoutes(memoryRecipientRewriteTable, usersRepository));
+            createServer(new AliasRoutes(memoryRecipientRewriteTable, usersRepository, new JsonTransformer()));
+        }
+
+        @Test
+        void getAliasesShouldBeEmpty() {
+            when()
+                .get()
+            .then()
+                .contentType(ContentType.JSON)
+                .statusCode(HttpStatus.OK_200)
+                .body(is("[]"));
+        }
+
+        @Test
+        void getAliasesShouldListExistingAliasesInAlphabeticOrder() {
+            with()
+                .put(ALICE + SEPARATOR + "sources" + SEPARATOR + ALICE_ALIAS);
+
+            with()
+                .put(BOB + SEPARATOR + "sources" + SEPARATOR + BOB_ALIAS);
+
+            List<String> addresses =
+                when()
+                    .get()
+                .then()
+                    .contentType(ContentType.JSON)
+                    .statusCode(HttpStatus.OK_200)
+                    .extract()
+                    .body()
+                    .jsonPath()
+                    .getList(".");
+            assertThat(addresses).containsExactly(ALICE, BOB);
+        }
+
+        @Test
+        void getNotRegisteredAliasesShouldReturnEmptyList() {
+            when()
+                .get("unknown@domain.travel")
+            .then()
+                .contentType(ContentType.JSON)
+                .statusCode(HttpStatus.OK_200)
+                .body(is("[]"));
+        }
+
+        @Test
+        void getAliasesShouldReturnEmptyListWhenNoAliasMappings() {
+            when()
+                .get(BOB)
+            .then()
+                .contentType(ContentType.JSON)
+                .statusCode(HttpStatus.OK_200)
+                .body(is("[]"));
         }
 
         @Test
@@ -202,7 +252,12 @@ class AliasRoutesTest {
             with()
                 .put(BOB + SEPARATOR + "sources" + SEPARATOR + BOB_ALIAS);
 
-            assertThat(memoryRecipientRewriteTable.getStoredMappings(BOB_ALIAS_SOURCE)).containsOnly(BOB_MAPPING);
+            when()
+                .get(BOB)
+            .then()
+                .contentType(ContentType.JSON)
+                .statusCode(HttpStatus.OK_200)
+                .body("source", hasItems(BOB_ALIAS));
         }
 
         @Test
@@ -210,15 +265,25 @@ class AliasRoutesTest {
             with()
                 .put(BOB + SEPARATOR + "sources" + SEPARATOR + BOB_ALIAS_WITH_ENCODED_SLASH);
 
-            assertThat(memoryRecipientRewriteTable.getStoredMappings(BOB_ALIAS_WITH_ENCODED_SLASH_SOURCE)).containsOnly(BOB_MAPPING);
+            when()
+                .get(BOB)
+            .then()
+                .contentType(ContentType.JSON)
+                .statusCode(HttpStatus.OK_200)
+                .body("source", hasItems(BOB_ALIAS_WITH_SLASH));
         }
 
         @Test
-        void putAliasForUserWithEncodedSlashShouldCreateForward() {
+        void putAliasForUserWithEncodedSlashShouldCreateAlias() {
             with()
                 .put(BOB_WITH_ENCODED_SLASH + SEPARATOR + "sources" + SEPARATOR + BOB_ALIAS);
 
-            assertThat(memoryRecipientRewriteTable.getStoredMappings(BOB_ALIAS_SOURCE)).containsOnly(BOB_WITH_ENCODED_SLASH_MAPPING);
+            when()
+                .get(BOB_WITH_ENCODED_SLASH)
+            .then()
+                .contentType(ContentType.JSON)
+                .statusCode(HttpStatus.OK_200)
+                .body("source", hasItems(BOB_ALIAS));
         }
 
         @Test
@@ -229,34 +294,106 @@ class AliasRoutesTest {
             with()
                 .put(BOB + SEPARATOR + "sources" + SEPARATOR + BOB_ALIAS);
 
-            assertThat(memoryRecipientRewriteTable.getStoredMappings(BOB_ALIAS_SOURCE)).containsOnly(BOB_MAPPING);
+            when()
+                .get(BOB)
+            .then()
+                .contentType(ContentType.JSON)
+                .statusCode(HttpStatus.OK_200)
+                .body("source", hasItems(BOB_ALIAS));
         }
 
         @Test
-        void putAliasForUserShouldAllowSeveralSources() {
-            MappingSource source2 = MappingSource.fromUser("bob-alias2", DOMAIN);
-
+        void putAliasForUserShouldAllowSeveralSourcesAndReturnThemInAlphabeticalOrder() {
             with()
                 .put(BOB + SEPARATOR + "sources" + SEPARATOR + BOB_ALIAS);
 
             with()
                 .put(BOB + SEPARATOR + "sources" + SEPARATOR + BOB_ALIAS_2);
 
-            assertThat(memoryRecipientRewriteTable.getStoredMappings(BOB_ALIAS_SOURCE)).containsOnly(BOB_MAPPING);
-            assertThat(memoryRecipientRewriteTable.getStoredMappings(source2)).containsOnly(BOB_MAPPING);
+            when()
+                .get(BOB)
+            .then()
+                .contentType(ContentType.JSON)
+                .statusCode(HttpStatus.OK_200)
+                .body("source", hasItems(BOB_ALIAS, BOB_ALIAS_2));
         }
 
         @Test
         void putAliasForUserShouldAllowSeveralDestinations() {
-            Mapping aliceMapping = Mapping.alias(ALICE);
-
             with()
                 .put(BOB + SEPARATOR + "sources" + SEPARATOR + BOB_ALIAS);
 
             with()
                 .put(ALICE + SEPARATOR + "sources" + SEPARATOR + BOB_ALIAS);
 
-            assertThat(memoryRecipientRewriteTable.getStoredMappings(BOB_ALIAS_SOURCE)).containsOnly(BOB_MAPPING, aliceMapping);
+            when()
+                .get(BOB)
+            .then()
+                .contentType(ContentType.JSON)
+                .statusCode(HttpStatus.OK_200)
+                .body("source", hasItems(BOB_ALIAS));
+
+            when()
+                .get(ALICE)
+            .then()
+                .contentType(ContentType.JSON)
+                .statusCode(HttpStatus.OK_200)
+                .body("source", hasItems(BOB_ALIAS));
+        }
+
+        @Test
+        void putAliasForUserShouldNotRequireExistingBaseUser() {
+            String notExistingAddress = "notFound@" + DOMAIN.name();
+
+            with()
+                .put(notExistingAddress + SEPARATOR + "sources" + SEPARATOR + BOB_ALIAS);
+
+            when()
+                .get(notExistingAddress)
+            .then()
+                .contentType(ContentType.JSON)
+                .statusCode(HttpStatus.OK_200)
+                .body("source", hasItems(BOB_ALIAS));
+        }
+
+        @Test
+        void deleteAliasNotInAliasesShouldReturnOK() {
+            when()
+                .delete(BOB + SEPARATOR + "sources" + SEPARATOR + BOB_ALIAS)
+            .then()
+                .statusCode(HttpStatus.NO_CONTENT_204);
+        }
+
+        @Test
+        void deleteAliasInAliasesShouldDeleteAliasForUser() {
+            with()
+                .put(BOB + SEPARATOR + "sources" + SEPARATOR + BOB_ALIAS);
+
+            with()
+                .delete(BOB + SEPARATOR + "sources" + SEPARATOR + BOB_ALIAS);
+
+            when()
+                .get(BOB_ALIAS)
+            .then()
+                .contentType(ContentType.JSON)
+                .statusCode(HttpStatus.OK_200)
+                .body(is("[]"));
+        }
+
+        @Test
+        void deleteLastAliasOfUserInAliasesShouldDeleteUserFromAliasList() {
+            with()
+                .put(BOB + SEPARATOR + "sources" + SEPARATOR + BOB_ALIAS);
+
+            with()
+                .delete(BOB + SEPARATOR + "sources" + SEPARATOR + BOB_ALIAS);
+
+            when()
+                .get()
+            .then()
+                .contentType(ContentType.JSON)
+                .statusCode(HttpStatus.OK_200)
+                .body(is("[]"));
         }
     }
 
@@ -284,7 +421,7 @@ class AliasRoutesTest {
             UsersRepository userRepository = mock(UsersRepository.class);
             DomainList domainList = mock(DomainList.class);
             Mockito.when(domainList.containsDomain(any())).thenReturn(true);
-            createServer(new AliasRoutes(memoryRecipientRewriteTable, userRepository));
+            createServer(new AliasRoutes(memoryRecipientRewriteTable, userRepository, new JsonTransformer()));
         }
 
         @Test
@@ -326,7 +463,7 @@ class AliasRoutesTest {
         }
 
         @Test
-        void putUserDestinationInForwardWithSlashShouldReturnNotFound() {
+        void putUserDestinationInAliasWithSlashShouldReturnNotFound() {
             when()
                 .put(BOB_WITH_SLASH + SEPARATOR + "sources" + SEPARATOR + BOB_ALIAS)
             .then()
@@ -350,6 +487,52 @@ class AliasRoutesTest {
         }
 
         @Test
+        void deleteMalformedUserDestinationShouldReturnBadRequest() {
+            Map<String, Object> errors = when()
+                .delete("not-an-address" + SEPARATOR + "sources" + SEPARATOR + BOB_ALIAS)
+            .then()
+                .statusCode(HttpStatus.BAD_REQUEST_400)
+                .contentType(ContentType.JSON)
+                .extract()
+                .body()
+                .jsonPath()
+                .getMap(".");
+
+            assertThat(errors)
+                .containsEntry("statusCode", HttpStatus.BAD_REQUEST_400)
+                .containsEntry("type", "InvalidArgument")
+                .containsEntry("message", "The alias is not an email address")
+                .containsEntry("details", "Out of data at position 1 in 'not-an-address'");
+        }
+
+        @Test
+        void deleteMalformedAliasShouldReturnBadRequest() {
+            Map<String, Object> errors = when()
+                .delete(BOB + SEPARATOR + "sources" + SEPARATOR + "not-an-address")
+            .then()
+                .statusCode(HttpStatus.BAD_REQUEST_400)
+                .contentType(ContentType.JSON)
+                .extract()
+                .body()
+                .jsonPath()
+                .getMap(".");
+
+            assertThat(errors)
+                .containsEntry("statusCode", HttpStatus.BAD_REQUEST_400)
+                .containsEntry("type", "InvalidArgument")
+                .containsEntry("message", "The alias is not an email address")
+                .containsEntry("details", "Out of data at position 1 in 'not-an-address'");
+        }
+
+        @Test
+        void deleteRequiresTwoPathParams() {
+            when()
+                .delete(BOB)
+            .then()
+                .statusCode(HttpStatus.NOT_FOUND_404);
+        }
+
+        @Test
         void putShouldReturnErrorWhenRecipientRewriteTableExceptionIsThrown() throws Exception {
             doThrow(RecipientRewriteTableException.class)
                 .when(memoryRecipientRewriteTable)
@@ -372,5 +555,77 @@ class AliasRoutesTest {
             .then()
                 .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
         }
+
+        @Test
+        void getAllShouldReturnErrorWhenRecipientRewriteTableExceptionIsThrown() throws Exception {
+            doThrow(RecipientRewriteTableException.class)
+                .when(memoryRecipientRewriteTable)
+                .getAllMappings();
+
+            when()
+                .get()
+            .then()
+                .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+        }
+
+        @Test
+        void getAllShouldReturnErrorWhenRuntimeExceptionIsThrown() throws Exception {
+            doThrow(RuntimeException.class)
+                .when(memoryRecipientRewriteTable)
+                .getAllMappings();
+
+            when()
+                .get()
+            .then()
+                .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+        }
+
+        @Test
+        void deleteShouldReturnErrorWhenRecipientRewriteTableExceptionIsThrown() throws Exception {
+            doThrow(RecipientRewriteTableException.class)
+                .when(memoryRecipientRewriteTable)
+                .removeAliasMapping(any(), anyString());
+
+            when()
+                .delete(BOB + SEPARATOR + "sources" + SEPARATOR + BOB_ALIAS)
+            .then()
+                .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+        }
+
+        @Test
+        void deleteShouldReturnErrorWhenRuntimeExceptionIsThrown() throws Exception {
+            doThrow(RuntimeException.class)
+                .when(memoryRecipientRewriteTable)
+                .removeAliasMapping(any(), anyString());
+
+            when()
+                .delete(BOB + SEPARATOR + "sources" + SEPARATOR + BOB_ALIAS)
+            .then()
+                .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+        }
+
+        @Test
+        void getShouldReturnErrorWhenRecipientRewriteTableExceptionIsThrown() throws Exception {
+            doThrow(RecipientRewriteTableException.class)
+                .when(memoryRecipientRewriteTable)
+                .getAllMappings();
+
+            when()
+                .get(BOB)
+            .then()
+                .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+        }
+
+        @Test
+        void getShouldReturnErrorWhenRuntimeExceptionIsThrown() throws Exception {
+            doThrow(RuntimeException.class)
+                .when(memoryRecipientRewriteTable)
+                .getAllMappings();
+
+            when()
+                .get(BOB)
+            .then()
+                .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/b312b877/src/site/markdown/server/manage-webadmin.md
----------------------------------------------------------------------
diff --git a/src/site/markdown/server/manage-webadmin.md b/src/site/markdown/server/manage-webadmin.md
index c0a7b8b..65d28d6 100644
--- a/src/site/markdown/server/manage-webadmin.md
+++ b/src/site/markdown/server/manage-webadmin.md
@@ -1314,7 +1314,46 @@ to be configured.
 
 Note that email addresses are restricted to ASCII character set. Mail addresses not matching this criteria will be rejected.
 
+ - [Listing users with aliases](#Listing_users_with_aliases)
+ - [Listing alias sources of an user](#Listing_alias_sources_of_an_user)
  - [Adding a new alias to an user](#Adding_a_new_alias_to_an_user)
+ - [Removing an alias of an user](#Removing_an_alias_of_an_user)
+
+### Listing users with aliases
+
+```
+curl -XGET http://ip:port/address/aliases
+```
+
+Will return the users having aliases configured as a list of JSON Strings representing mail addresses. For instance:
+
+```
+["user1@domain.com", "user2@domain.com"]
+```
+
+Response codes:
+
+ - 200: Success
+
+### Listing alias sources of an user
+
+```
+curl -XGET http://ip:port/address/aliases/user@domain.com
+```
+
+Will return the aliases of this user as a list of JSON Strings representing mail addresses. For instance:
+
+```
+[
+  {"source":"alias1@domain.com"},
+  {"source":"alias2@domain.com"}
+]
+```
+
+Response codes:
+
+ - 200: Success
+ - 400: Alias structure is not valid
 
 ### Adding a new alias to an user
 
@@ -1329,6 +1368,20 @@ Response codes:
  - 204: OK
  - 400: Alias structure or member is not valid
  - 400: The alias source exists as an user already
+ - 400: Source and destination can't be the same!
+
+### Removing an alias of an user
+
+```
+curl -XDELETE http://ip:port/address/aliases/user@domain.com/sources/alias@domain.com
+```
+
+Will remove alias@domain.com from user@domain.com, removing the alias if needed
+
+Response codes:
+
+ - 204: OK
+ - 400: Alias structure or member is not valid
 
 ## Administrating mail repositories
 


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


[17/17] james-project git commit: JAMES-2637 add test to MappingSource to be sure it matches the bean contract

Posted by bt...@apache.org.
JAMES-2637 add test to MappingSource to be sure it matches the bean contract


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

Branch: refs/heads/master
Commit: 4cdfef08ac033b99e5c31e9dd4c53379ea568425
Parents: dcb093e
Author: Rene Cordier <rc...@linagora.com>
Authored: Tue Jan 15 17:37:13 2019 +0700
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Wed Jan 16 13:48:57 2019 +0700

----------------------------------------------------------------------
 .../org/apache/james/rrt/lib/MappingSourceTest.java     | 12 +++++++++++-
 .../rrt/lib/AbstractRecipientRewriteTableTest.java      |  4 ++--
 2 files changed, 13 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/4cdfef08/server/data/data-api/src/test/java/org/apache/james/rrt/lib/MappingSourceTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/test/java/org/apache/james/rrt/lib/MappingSourceTest.java b/server/data/data-api/src/test/java/org/apache/james/rrt/lib/MappingSourceTest.java
index 9088b42..c467bb7 100644
--- a/server/data/data-api/src/test/java/org/apache/james/rrt/lib/MappingSourceTest.java
+++ b/server/data/data-api/src/test/java/org/apache/james/rrt/lib/MappingSourceTest.java
@@ -19,18 +19,28 @@
 
 package org.apache.james.rrt.lib;
 
+import static org.assertj.core.api.Assertions.assertThat;
+
 import org.apache.james.core.Domain;
 import org.apache.james.core.MailAddress;
 import org.apache.james.core.User;
 import org.junit.jupiter.api.Test;
 
-import static org.assertj.core.api.Assertions.assertThat;
+import nl.jqno.equalsverifier.EqualsVerifier;
+
 class MappingSourceTest {
     private static final String DOMAIN = "domain.tld";
     private static final  String USER = "alice";
     private static final String MAIL_ADDRESS = USER + "@" + DOMAIN;
 
     @Test
+    void shouldRespectBeanContract() {
+        EqualsVerifier.forClass(MappingSource.class)
+            .withIgnoredFields("wildcard")
+            .verify();
+    }
+
+    @Test
     void asMailAddressStringShouldSerializeWilcard() {
         MappingSource mappingSource = MappingSource.wildCard();
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/4cdfef08/server/data/data-library/src/test/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTableTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/test/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTableTest.java b/server/data/data-library/src/test/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTableTest.java
index f5e26af..955fe75 100644
--- a/server/data/data-library/src/test/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTableTest.java
+++ b/server/data/data-library/src/test/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTableTest.java
@@ -474,7 +474,7 @@ public abstract class AbstractRecipientRewriteTableTest {
     }
 
     @Test
-    public void getSourcesForTypeShouldReturnSortedList() throws Exception {
+    public void getSourcesForTypeShouldReturnSortedStream() throws Exception {
         MappingSource source1 = MappingSource.fromUser("alice", Domain.LOCALHOST);
         MappingSource source2 = MappingSource.fromUser("bob", Domain.LOCALHOST);
         MappingSource source3 = MappingSource.fromUser("cedric", Domain.LOCALHOST);
@@ -517,7 +517,7 @@ public abstract class AbstractRecipientRewriteTableTest {
     }
 
     @Test
-    public void getMappingsForTypeShouldReturnSortedList() throws Exception {
+    public void getMappingsForTypeShouldReturnSortedStream() throws Exception {
         String address1 = "alice@domain.com";
         String address2 = "bob@domain.com";
         String address3 = "cedric@domain.com";


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


[03/17] james-project git commit: MAILBOX-371 RabbitMQEventBus impl for key registrations

Posted by bt...@apache.org.
MAILBOX-371 RabbitMQEventBus impl for key registrations


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

Branch: refs/heads/master
Commit: 68735a2219435677d9bf2e9a85abf9dd6b20407e
Parents: 74fa711
Author: datph <dp...@linagora.com>
Authored: Fri Jan 11 15:36:01 2019 +0700
Committer: datph <dp...@linagora.com>
Committed: Wed Jan 16 05:38:45 2019 +0700

----------------------------------------------------------------------
 .../james/mailbox/events/KeyContract.java       |  76 ++++++
 .../james/mailbox/events/EventDispatcher.java   |  24 +-
 .../james/mailbox/events/KeyRegistration.java   |  33 +++
 .../mailbox/events/KeyRegistrationHandler.java  | 124 +++++++++
 .../mailbox/events/MailboxListenerRegistry.java |  58 +++++
 .../james/mailbox/events/RabbitMQEventBus.java  |  16 +-
 .../mailbox/events/RegistrationBinder.java      |  54 ++++
 .../mailbox/events/RegistrationQueueName.java   |  42 +++
 .../events/MailboxListenerRegistryTest.java     | 256 +++++++++++++++++++
 .../mailbox/events/RabbitMQEventBusTest.java    |  21 +-
 10 files changed, 689 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/68735a22/mailbox/api/src/test/java/org/apache/james/mailbox/events/KeyContract.java
----------------------------------------------------------------------
diff --git a/mailbox/api/src/test/java/org/apache/james/mailbox/events/KeyContract.java b/mailbox/api/src/test/java/org/apache/james/mailbox/events/KeyContract.java
index bd92d82..f50a66d 100644
--- a/mailbox/api/src/test/java/org/apache/james/mailbox/events/KeyContract.java
+++ b/mailbox/api/src/test/java/org/apache/james/mailbox/events/KeyContract.java
@@ -25,13 +25,17 @@ import static org.apache.james.mailbox.events.EventBusTestFixture.KEY_1;
 import static org.apache.james.mailbox.events.EventBusTestFixture.KEY_2;
 import static org.apache.james.mailbox.events.EventBusTestFixture.NO_KEYS;
 import static org.apache.james.mailbox.events.EventBusTestFixture.ONE_SECOND;
+import static org.apache.james.mailbox.events.EventBusTestFixture.WAIT_CONDITION;
 import static org.apache.james.mailbox.events.EventBusTestFixture.newListener;
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatCode;
 import static org.junit.jupiter.api.Assertions.assertTimeout;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.after;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -242,5 +246,77 @@ public interface KeyContract extends EventBusContract {
                     latch.countDown();
                 });
         }
+
+        @Test
+        default void failingRegisteredListenersShouldNotAbortRegisteredDelivery() {
+            EventBusTestFixture.MailboxListenerCountingSuccessfulExecution listener = spy(new EventBusTestFixture.MailboxListenerCountingSuccessfulExecution());
+            doThrow(new RuntimeException())
+                .doCallRealMethod()
+                .when(listener).event(any());
+            eventBus().register(listener, KEY_1);
+
+            eventBus().dispatch(EVENT, KEY_1).block();
+            eventBus().dispatch(EVENT, KEY_1).block();
+
+            WAIT_CONDITION
+                .until(() -> assertThat(listener.numberOfEventCalls()).isEqualTo(1));
+        }
+
+        @Test
+        default void allRegisteredListenersShouldBeExecutedWhenARegisteredListenerFails() {
+            MailboxListener listener = newListener();
+
+            MailboxListener failingListener = mock(MailboxListener.class);
+            when(listener.getExecutionMode()).thenReturn(MailboxListener.ExecutionMode.SYNCHRONOUS);
+            doThrow(new RuntimeException()).when(failingListener).event(any());
+
+            eventBus().register(failingListener, KEY_1);
+            eventBus().register(listener, KEY_1);
+
+            eventBus().dispatch(EVENT, ImmutableSet.of(KEY_1)).block();
+
+            verify(listener, timeout(ONE_SECOND).times(1)).event(any());
+        }
+    }
+
+    interface MultipleEventBusKeyContract extends MultipleEventBusContract {
+
+        @Test
+        default void crossEventBusRegistrationShouldBeAllowed() {
+            MailboxListener mailboxListener = newListener();
+
+            eventBus().register(mailboxListener, KEY_1);
+
+            eventBus2().dispatch(EVENT, KEY_1).block();
+
+            verify(mailboxListener, timeout(ONE_SECOND).times(1)).event(any());
+        }
+
+        @Test
+        default void unregisteredDistantListenersShouldNotBeNotified() {
+            MailboxListener mailboxListener = newListener();
+
+            eventBus().register(mailboxListener, KEY_1).unregister();
+
+            eventBus2().dispatch(EVENT, ImmutableSet.of(KEY_1)).block();
+
+            verify(mailboxListener, after(FIVE_HUNDRED_MS).never())
+                .event(any());
+        }
+
+        @Test
+        default void allRegisteredListenersShouldBeDispatched() {
+            MailboxListener mailboxListener1 = newListener();
+            MailboxListener mailboxListener2 = newListener();
+
+            eventBus().register(mailboxListener1, KEY_1);
+            eventBus2().register(mailboxListener2, KEY_1);
+
+            eventBus2().dispatch(EVENT, KEY_1).block();
+
+            verify(mailboxListener1, timeout(ONE_SECOND).times(1)).event(any());
+            verify(mailboxListener2, timeout(ONE_SECOND).times(1)).event(any());
+        }
+
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/68735a22/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/EventDispatcher.java
----------------------------------------------------------------------
diff --git a/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/EventDispatcher.java b/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/EventDispatcher.java
index b01fc53..77892b6 100644
--- a/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/EventDispatcher.java
+++ b/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/EventDispatcher.java
@@ -21,14 +21,15 @@ package org.apache.james.mailbox.events;
 
 import static org.apache.james.backend.rabbitmq.Constants.DIRECT_EXCHANGE;
 import static org.apache.james.backend.rabbitmq.Constants.DURABLE;
-import static org.apache.james.backend.rabbitmq.Constants.EMPTY_ROUTING_KEY;
 import static org.apache.james.mailbox.events.RabbitMQEventBus.MAILBOX_EVENT_EXCHANGE_NAME;
 
 import java.nio.charset.StandardCharsets;
+import java.util.Set;
 
 import org.apache.james.event.json.EventSerializer;
 import org.apache.james.mailbox.Event;
 
+import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 import reactor.core.publisher.MonoProcessor;
 import reactor.core.scheduler.Schedulers;
@@ -52,16 +53,29 @@ public class EventDispatcher {
             .block();
     }
 
-    Mono<Void> dispatch(Event event) {
-        Mono<OutboundMessage> outboundMessage = Mono.just(event)
+    Mono<Void> dispatch(Event event, Set<RegistrationKey> keys) {
+        Mono<byte[]> serializedEvent = Mono.just(event)
             .publishOn(Schedulers.parallel())
             .map(this::serializeEvent)
-            .map(payload -> new OutboundMessage(MAILBOX_EVENT_EXCHANGE_NAME, EMPTY_ROUTING_KEY, payload));
+            .cache();
 
-        return sender.send(outboundMessage)
+        return doDispatch(serializedEvent, keys)
             .subscribeWith(MonoProcessor.create());
     }
 
+    private Mono<Void> doDispatch(Mono<byte[]> serializedEvent, Set<RegistrationKey> keys) {
+        Flux<RoutingKeyConverter.RoutingKey> routingKeys = Flux.concat(
+            Mono.just(RoutingKeyConverter.RoutingKey.empty()),
+            Flux.fromIterable(keys)
+                .map(RoutingKeyConverter.RoutingKey::of));
+
+        Flux<OutboundMessage> outboundMessages = routingKeys
+            .flatMap(routingKey -> serializedEvent
+                .map(payload -> new OutboundMessage(MAILBOX_EVENT_EXCHANGE_NAME, routingKey.asString(), payload)));
+
+        return sender.send(outboundMessages);
+    }
+
     private byte[] serializeEvent(Event event) {
         return eventSerializer.toJson(event).getBytes(StandardCharsets.UTF_8);
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/68735a22/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/KeyRegistration.java
----------------------------------------------------------------------
diff --git a/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/KeyRegistration.java b/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/KeyRegistration.java
new file mode 100644
index 0000000..8dd002d
--- /dev/null
+++ b/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/KeyRegistration.java
@@ -0,0 +1,33 @@
+/****************************************************************
+ * 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.events;
+
+class KeyRegistration implements Registration {
+    private final Runnable unregister;
+
+    KeyRegistration(Runnable unregister) {
+        this.unregister = unregister;
+    }
+
+    @Override
+    public void unregister() {
+        unregister.run();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/68735a22/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/KeyRegistrationHandler.java
----------------------------------------------------------------------
diff --git a/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/KeyRegistrationHandler.java b/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/KeyRegistrationHandler.java
new file mode 100644
index 0000000..ff388df
--- /dev/null
+++ b/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/KeyRegistrationHandler.java
@@ -0,0 +1,124 @@
+/****************************************************************
+ * 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.events;
+
+import static org.apache.james.backend.rabbitmq.Constants.AUTO_DELETE;
+import static org.apache.james.backend.rabbitmq.Constants.DURABLE;
+import static org.apache.james.backend.rabbitmq.Constants.EXCLUSIVE;
+import static org.apache.james.backend.rabbitmq.Constants.NO_ARGUMENTS;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Optional;
+
+import org.apache.james.event.json.EventSerializer;
+import org.apache.james.mailbox.Event;
+import org.apache.james.mailbox.MailboxListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.rabbitmq.client.AMQP;
+import com.rabbitmq.client.Connection;
+import com.rabbitmq.client.Delivery;
+
+import reactor.core.Disposable;
+import reactor.core.publisher.Mono;
+import reactor.core.scheduler.Schedulers;
+import reactor.rabbitmq.QueueSpecification;
+import reactor.rabbitmq.RabbitFlux;
+import reactor.rabbitmq.Receiver;
+import reactor.rabbitmq.ReceiverOptions;
+import reactor.rabbitmq.Sender;
+
+public class KeyRegistrationHandler {
+    private static final Logger LOGGER = LoggerFactory.getLogger(KeyRegistrationHandler.class);
+
+    private final MailboxListenerRegistry mailboxListenerRegistry;
+    private final EventSerializer eventSerializer;
+    private final Sender sender;
+    private final RoutingKeyConverter routingKeyConverter;
+    private final Receiver receiver;
+    private final RegistrationQueueName registrationQueue;
+    private final RegistrationBinder registrationBinder;
+    private Optional<Disposable> receiverSubscriber;
+
+    public KeyRegistrationHandler(EventSerializer eventSerializer, Sender sender, Mono<Connection> connectionMono, RoutingKeyConverter routingKeyConverter) {
+        this.eventSerializer = eventSerializer;
+        this.sender = sender;
+        this.routingKeyConverter = routingKeyConverter;
+        this.mailboxListenerRegistry = new MailboxListenerRegistry();
+        this.receiver = RabbitFlux.createReceiver(new ReceiverOptions().connectionMono(connectionMono));
+        this.registrationQueue = new RegistrationQueueName();
+        this.registrationBinder = new RegistrationBinder(sender, registrationQueue);
+    }
+
+    void start() {
+        sender.declareQueue(QueueSpecification.queue()
+            .durable(DURABLE)
+            .exclusive(EXCLUSIVE)
+            .autoDelete(AUTO_DELETE)
+            .arguments(NO_ARGUMENTS))
+            .map(AMQP.Queue.DeclareOk::getQueue)
+            .doOnSuccess(registrationQueue::initialize)
+            .block();
+
+        receiverSubscriber = Optional.of(receiver.consumeAutoAck(registrationQueue.asString())
+            .subscribeOn(Schedulers.parallel())
+            .flatMap(this::handleDelivery)
+            .subscribe());
+    }
+
+    void stop() {
+        receiverSubscriber.filter(subscriber -> !subscriber.isDisposed())
+            .ifPresent(subscriber -> subscriber.dispose());
+        receiver.close();
+        mailboxListenerRegistry.clear();
+        sender.delete(QueueSpecification.queue(registrationQueue.asString())).block();
+    }
+
+    Registration register(MailboxListener listener, RegistrationKey key) {
+        Runnable bindIfEmpty = () -> registrationBinder.bind(key).block();
+        Runnable unbindIfEmpty = () -> registrationBinder.unbind(key).block();
+        Runnable unregister = () -> mailboxListenerRegistry.removeListener(key, listener, unbindIfEmpty);
+
+        KeyRegistration keyRegistration = new KeyRegistration(unregister);
+        mailboxListenerRegistry.addListener(key, listener, bindIfEmpty);
+        return keyRegistration;
+    }
+
+    private Mono<Void> handleDelivery(Delivery delivery) {
+        if (delivery.getBody() == null) {
+            return Mono.empty();
+        }
+        String routingKey = delivery.getEnvelope().getRoutingKey();
+        RegistrationKey registrationKey = routingKeyConverter.toRegistrationKey(routingKey);
+        Event event = toEvent(delivery);
+
+        return mailboxListenerRegistry.getLocalMailboxListeners(registrationKey)
+            .flatMap(listener -> Mono.fromRunnable(() -> listener.event(event))
+                .doOnError(e -> LOGGER.error("Exception happens when handling event of user {}", event.getUser().asString(), e))
+                .onErrorResume(e -> Mono.empty()))
+            .subscribeOn(Schedulers.elastic())
+            .then();
+    }
+
+    private Event toEvent(Delivery delivery) {
+        return eventSerializer.fromJson(new String(delivery.getBody(), StandardCharsets.UTF_8)).get();
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/68735a22/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/MailboxListenerRegistry.java
----------------------------------------------------------------------
diff --git a/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/MailboxListenerRegistry.java b/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/MailboxListenerRegistry.java
new file mode 100644
index 0000000..0d8f732
--- /dev/null
+++ b/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/MailboxListenerRegistry.java
@@ -0,0 +1,58 @@
+/****************************************************************
+ * 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.events;
+
+import org.apache.james.mailbox.MailboxListener;
+
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Multimaps;
+
+import reactor.core.publisher.Flux;
+
+class MailboxListenerRegistry {
+    private final Multimap<RegistrationKey, MailboxListener> listeners;
+
+    MailboxListenerRegistry() {
+        this.listeners = Multimaps.synchronizedMultimap(HashMultimap.create());
+    }
+
+    synchronized void addListener(RegistrationKey registrationKey, MailboxListener listener, Runnable runIfEmpty) {
+        if (listeners.get(registrationKey).isEmpty()) {
+            runIfEmpty.run();
+        }
+        listeners.put(registrationKey, listener);
+    }
+
+    synchronized void removeListener(RegistrationKey registrationKey, MailboxListener listener, Runnable runIfEmpty) {
+        boolean wasRemoved = listeners.remove(registrationKey, listener);
+        if (wasRemoved && listeners.get(registrationKey).isEmpty()) {
+            runIfEmpty.run();
+        }
+    }
+
+    synchronized void clear() {
+        listeners.clear();
+    }
+
+    Flux<MailboxListener> getLocalMailboxListeners(RegistrationKey registrationKey) {
+        return Flux.fromIterable(listeners.get(registrationKey));
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/68735a22/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/RabbitMQEventBus.java
----------------------------------------------------------------------
diff --git a/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/RabbitMQEventBus.java b/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/RabbitMQEventBus.java
index 87e8ab1..447b345 100644
--- a/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/RabbitMQEventBus.java
+++ b/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/RabbitMQEventBus.java
@@ -24,7 +24,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
 
 import javax.annotation.PreDestroy;
 
-import org.apache.commons.lang3.NotImplementedException;
 import org.apache.james.backend.rabbitmq.RabbitMQConnectionFactory;
 import org.apache.james.event.json.EventSerializer;
 import org.apache.james.mailbox.Event;
@@ -44,25 +43,29 @@ class RabbitMQEventBus implements EventBus {
     private final Mono<Connection> connectionMono;
     private final EventSerializer eventSerializer;
     private final AtomicBoolean isRunning;
+    private final RoutingKeyConverter routingKeyConverter;
 
     private GroupRegistrationHandler groupRegistrationHandler;
+    private KeyRegistrationHandler keyRegistrationHandler;
     private EventDispatcher eventDispatcher;
     private Sender sender;
 
-    RabbitMQEventBus(RabbitMQConnectionFactory rabbitMQConnectionFactory, EventSerializer eventSerializer) {
+    RabbitMQEventBus(RabbitMQConnectionFactory rabbitMQConnectionFactory, EventSerializer eventSerializer, RoutingKeyConverter routingKeyConverter) {
         this.connectionMono = Mono.fromSupplier(rabbitMQConnectionFactory::create).cache();
         this.eventSerializer = eventSerializer;
-        isRunning = new AtomicBoolean(false);
+        this.routingKeyConverter = routingKeyConverter;
+        this.isRunning = new AtomicBoolean(false);
     }
 
     public void start() {
         if (!isRunning.get()) {
             sender = RabbitFlux.createSender(new SenderOptions().connectionMono(connectionMono));
             groupRegistrationHandler = new GroupRegistrationHandler(eventSerializer, sender, connectionMono);
+            keyRegistrationHandler = new KeyRegistrationHandler(eventSerializer, sender, connectionMono, routingKeyConverter);
             eventDispatcher = new EventDispatcher(eventSerializer, sender);
 
             eventDispatcher.start();
-
+            keyRegistrationHandler.start();
             isRunning.set(true);
         }
     }
@@ -71,6 +74,7 @@ class RabbitMQEventBus implements EventBus {
     public void stop() {
         if (isRunning.get()) {
             groupRegistrationHandler.stop();
+            keyRegistrationHandler.stop();
             sender.close();
             isRunning.set(false);
         }
@@ -78,7 +82,7 @@ class RabbitMQEventBus implements EventBus {
 
     @Override
     public Registration register(MailboxListener listener, RegistrationKey key) {
-        throw new NotImplementedException("will implement latter");
+        return keyRegistrationHandler.register(listener, key);
     }
 
     @Override
@@ -89,7 +93,7 @@ class RabbitMQEventBus implements EventBus {
     @Override
     public Mono<Void> dispatch(Event event, Set<RegistrationKey> key) {
         if (!event.isNoop()) {
-            return eventDispatcher.dispatch(event);
+            return eventDispatcher.dispatch(event, key);
         }
         return Mono.empty();
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/68735a22/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/RegistrationBinder.java
----------------------------------------------------------------------
diff --git a/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/RegistrationBinder.java b/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/RegistrationBinder.java
new file mode 100644
index 0000000..f4405a6
--- /dev/null
+++ b/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/RegistrationBinder.java
@@ -0,0 +1,54 @@
+/****************************************************************
+ * 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.events;
+
+import static org.apache.james.mailbox.events.RabbitMQEventBus.MAILBOX_EVENT_EXCHANGE_NAME;
+
+import reactor.core.publisher.Mono;
+import reactor.rabbitmq.BindingSpecification;
+import reactor.rabbitmq.Sender;
+
+class RegistrationBinder {
+    private final Sender sender;
+    private final RegistrationQueueName registrationQueue;
+
+    RegistrationBinder(Sender sender, RegistrationQueueName registrationQueue) {
+        this.sender = sender;
+        this.registrationQueue = registrationQueue;
+    }
+
+    Mono<Void> bind(RegistrationKey key) {
+        return sender.bind(bindingSpecification(key))
+            .then();
+    }
+
+    Mono<Void> unbind(RegistrationKey key) {
+        return sender.unbind(bindingSpecification(key))
+            .then();
+    }
+
+    private BindingSpecification bindingSpecification(RegistrationKey key) {
+        RoutingKeyConverter.RoutingKey routingKey = RoutingKeyConverter.RoutingKey.of(key);
+        return BindingSpecification.binding()
+            .exchange(MAILBOX_EVENT_EXCHANGE_NAME)
+            .queue(registrationQueue.asString())
+            .routingKey(routingKey.asString());
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/68735a22/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/RegistrationQueueName.java
----------------------------------------------------------------------
diff --git a/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/RegistrationQueueName.java b/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/RegistrationQueueName.java
new file mode 100644
index 0000000..06fad8c
--- /dev/null
+++ b/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/RegistrationQueueName.java
@@ -0,0 +1,42 @@
+/****************************************************************
+ * 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.events;
+
+import java.util.Optional;
+
+import com.google.common.base.Preconditions;
+
+public class RegistrationQueueName {
+    private Optional<String> queueName;
+
+    RegistrationQueueName() {
+        this.queueName = Optional.empty();
+    }
+
+    void initialize(String queueName) {
+        Preconditions.checkNotNull(queueName);
+        Preconditions.checkState(!this.queueName.isPresent(), "'queueName' must be empty for initializing");
+        this.queueName = Optional.of(queueName);
+    }
+
+    String asString() {
+        return queueName.orElseThrow(() -> new IllegalStateException("'queueName' is not yet initialized"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/68735a22/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/MailboxListenerRegistryTest.java
----------------------------------------------------------------------
diff --git a/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/MailboxListenerRegistryTest.java b/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/MailboxListenerRegistryTest.java
new file mode 100644
index 0000000..e86dd6b
--- /dev/null
+++ b/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/MailboxListenerRegistryTest.java
@@ -0,0 +1,256 @@
+/****************************************************************
+ * 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.events;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+import java.time.Duration;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.james.mailbox.MailboxListener;
+import org.apache.james.mailbox.model.TestId;
+import org.apache.james.util.concurrency.ConcurrentTestRunner;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+class MailboxListenerRegistryTest {
+    private static final MailboxIdRegistrationKey KEY_1 = new MailboxIdRegistrationKey(TestId.of(42));
+
+    private MailboxListenerRegistry testee;
+
+    @BeforeEach
+    void setUp() {
+        testee = new MailboxListenerRegistry();
+    }
+
+    @Test
+    void getLocalMailboxListenersShouldReturnEmptyWhenNone() {
+        assertThat(testee.getLocalMailboxListeners(KEY_1).collectList().block())
+            .isEmpty();
+    }
+
+    @Test
+    void getLocalMailboxListenersShouldReturnPreviouslyAddedListener() {
+        MailboxListener listener = mock(MailboxListener.class);
+        testee.addListener(KEY_1, listener, () -> {
+        });
+
+        assertThat(testee.getLocalMailboxListeners(KEY_1).collectList().block())
+            .containsOnly(listener);
+    }
+
+    @Test
+    void getLocalMailboxListenersShouldReturnPreviouslyAddedListeners() {
+        MailboxListener listener1 = mock(MailboxListener.class);
+        MailboxListener listener2 = mock(MailboxListener.class);
+        testee.addListener(KEY_1, listener1, () -> {
+        });
+        testee.addListener(KEY_1, listener2, () -> {
+        });
+
+        assertThat(testee.getLocalMailboxListeners(KEY_1).collectList().block())
+            .containsOnly(listener1, listener2);
+    }
+
+    @Test
+    void getLocalMailboxListenersShouldNotReturnRemovedListeners() {
+        MailboxListener listener1 = mock(MailboxListener.class);
+        MailboxListener listener2 = mock(MailboxListener.class);
+        testee.addListener(KEY_1, listener1, () -> {
+        });
+        testee.addListener(KEY_1, listener2, () -> {
+        });
+
+        testee.removeListener(KEY_1, listener2, () -> {
+        });
+
+        assertThat(testee.getLocalMailboxListeners(KEY_1).collectList().block())
+            .containsOnly(listener1);
+    }
+
+    @Test
+    void addListenerShouldRunTaskWhenNoPreviouslyRegisteredListeners() {
+        MailboxListener listener = mock(MailboxListener.class);
+
+        AtomicBoolean atomicBoolean = new AtomicBoolean(false);
+        testee.addListener(KEY_1, listener, () -> atomicBoolean.set(true));
+
+        assertThat(atomicBoolean).isTrue();
+    }
+
+    @Test
+    void addListenerShouldNotRunTaskWhenPreviouslyRegisteredListeners() {
+        MailboxListener listener = mock(MailboxListener.class);
+
+        AtomicBoolean atomicBoolean = new AtomicBoolean(false);
+        testee.addListener(KEY_1, listener, () -> {
+        });
+        testee.addListener(KEY_1, listener, () -> atomicBoolean.set(true));
+
+        assertThat(atomicBoolean).isFalse();
+    }
+
+    @Test
+    void removeListenerShouldNotRunTaskWhenNoListener() {
+        MailboxListener listener = mock(MailboxListener.class);
+
+        AtomicBoolean atomicBoolean = new AtomicBoolean(false);
+        testee.removeListener(KEY_1, listener, () -> atomicBoolean.set(true));
+
+        assertThat(atomicBoolean).isFalse();
+    }
+
+    @Test
+    void removeListenerShouldNotRunTaskWhenSeveralListener() {
+        MailboxListener listener = mock(MailboxListener.class);
+        MailboxListener listener2 = mock(MailboxListener.class);
+
+        AtomicBoolean atomicBoolean = new AtomicBoolean(false);
+        testee.addListener(KEY_1, listener, () -> {
+        });
+        testee.addListener(KEY_1, listener2, () -> {
+        });
+        testee.removeListener(KEY_1, listener, () -> atomicBoolean.set(true));
+
+        assertThat(atomicBoolean).isFalse();
+    }
+
+    @Test
+    void removeListenerShouldRunTaskWhenOneListener() {
+        MailboxListener listener = mock(MailboxListener.class);
+
+        AtomicBoolean atomicBoolean = new AtomicBoolean(false);
+        testee.addListener(KEY_1, listener, () -> {
+        });
+        testee.removeListener(KEY_1, listener, () -> atomicBoolean.set(true));
+
+        assertThat(atomicBoolean).isTrue();
+    }
+
+    @Nested
+    class ConcurrentTest {
+        private final Duration ONE_SECOND = Duration.ofSeconds(1);
+
+        @Test
+        void getLocalMailboxListenersShouldReturnPreviousAddedListener() throws Exception {
+            MailboxListener listener = mock(MailboxListener.class);
+
+            ConcurrentTestRunner.builder()
+                .operation((threadNumber, operationNumber) -> testee.addListener(KEY_1, listener, () -> {
+                }))
+                .threadCount(10)
+                .operationCount(10)
+                .runSuccessfullyWithin(ONE_SECOND);
+
+            assertThat(testee.getLocalMailboxListeners(KEY_1).collectList().block())
+                .containsOnly(listener);
+        }
+
+        @Test
+        void getLocalMailboxListenersShouldReturnAllPreviousAddedListeners() throws Exception {
+            MailboxListener listener1 = mock(MailboxListener.class);
+            MailboxListener listener2 = mock(MailboxListener.class);
+            MailboxListener listener3 = mock(MailboxListener.class);
+
+            ConcurrentTestRunner.builder()
+                .operation((threadNumber, operationNumber) -> {
+                    if (threadNumber % 3 == 0) {
+                        testee.addListener(KEY_1, listener1, () -> {
+                        });
+                    } else if (threadNumber % 3 == 1) {
+                        testee.addListener(KEY_1, listener2, () -> {
+                        });
+                    } else if (threadNumber % 3 == 2) {
+                        testee.addListener(KEY_1, listener3, () -> {
+                        });
+                    }
+                })
+                .threadCount(6)
+                .operationCount(10)
+                .runSuccessfullyWithin(ONE_SECOND);
+
+            assertThat(testee.getLocalMailboxListeners(KEY_1).collectList().block())
+                .containsOnly(listener1, listener2, listener3);
+        }
+
+        @Test
+        void getLocalMailboxListenersShouldReturnEmptyWhenRemoveAddedListener() throws Exception {
+            MailboxListener listener1 = mock(MailboxListener.class);
+
+            testee.addListener(KEY_1, listener1, () -> {
+            });
+
+            ConcurrentTestRunner.builder()
+                .operation(((threadNumber, operationNumber) ->
+                    testee.removeListener(KEY_1, listener1, () -> {
+                    })))
+                .threadCount(10)
+                .operationCount(10)
+                .runSuccessfullyWithin(ONE_SECOND);
+
+            assertThat(testee.getLocalMailboxListeners(KEY_1).collectList().block())
+                .isEmpty();
+        }
+
+        @Test
+        void addListenerOnlyRunTaskOnceForEmptyRegistry() throws Exception {
+            MailboxListener listener1 = mock(MailboxListener.class);
+            MailboxListener listener2 = mock(MailboxListener.class);
+            MailboxListener listener3 = mock(MailboxListener.class);
+
+            AtomicInteger runIfEmptyCount = new AtomicInteger(0);
+
+            ConcurrentTestRunner.builder()
+                .operation((threadNumber, operationNumber) -> {
+                    if (threadNumber % 3 == 0) {
+                        testee.addListener(KEY_1, listener1, () -> runIfEmptyCount.incrementAndGet());
+                    } else if (threadNumber % 3 == 1) {
+                        testee.addListener(KEY_1, listener2, () -> runIfEmptyCount.incrementAndGet());
+                    } else if (threadNumber % 3 == 2) {
+                        testee.addListener(KEY_1, listener3, () -> runIfEmptyCount.incrementAndGet());
+                    }
+                })
+                .threadCount(6)
+                .operationCount(10)
+                .runSuccessfullyWithin(ONE_SECOND);
+
+            assertThat(runIfEmptyCount.get()).isEqualTo(1);
+        }
+
+        @Test
+        void removeListenerOnlyRunTaskOnceForEmptyRegistry() throws Exception {
+            MailboxListener listener1 = mock(MailboxListener.class);
+            AtomicInteger runIfEmptyCount = new AtomicInteger(0);
+
+            testee.addListener(KEY_1, listener1, () -> {});
+            ConcurrentTestRunner.builder()
+                .operation(((threadNumber, operationNumber) -> testee.removeListener(KEY_1, listener1, () -> runIfEmptyCount.incrementAndGet())))
+                .threadCount(10)
+                .operationCount(10)
+                .runSuccessfullyWithin(ONE_SECOND);
+
+            assertThat(runIfEmptyCount.get()).isEqualTo(1);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/68735a22/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RabbitMQEventBusTest.java
----------------------------------------------------------------------
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 8524e38..0daf7f0 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
@@ -53,6 +53,7 @@ import org.apache.james.mailbox.model.TestMessageId;
 import org.apache.james.util.concurrency.ConcurrentTestRunner;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
@@ -70,7 +71,8 @@ import reactor.rabbitmq.Sender;
 import reactor.rabbitmq.SenderOptions;
 
 class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract, GroupContract.MultipleEventBusGroupContract,
-    EventBusConcurrentTestContract.SingleEventBusConcurrentContract, EventBusConcurrentTestContract.MultiEventBusConcurrentContract {
+    EventBusConcurrentTestContract.SingleEventBusConcurrentContract, EventBusConcurrentTestContract.MultiEventBusConcurrentContract,
+    KeyContract.SingleEventBusKeyContract, KeyContract.MultipleEventBusKeyContract {
 
     @RegisterExtension
     static RabbitMQExtension rabbitMQExtension = new RabbitMQExtension();
@@ -80,6 +82,7 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
     private Sender sender;
     private RabbitMQConnectionFactory connectionFactory;
     private EventSerializer eventSerializer;
+    private RoutingKeyConverter routingKeyConverter;
 
     @BeforeEach
     void setUp() {
@@ -88,9 +91,10 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
 
         TestId.Factory mailboxIdFactory = new TestId.Factory();
         eventSerializer = new EventSerializer(mailboxIdFactory, new TestMessageId.Factory());
+        routingKeyConverter = RoutingKeyConverter.forFactories(new MailboxIdRegistrationKey.Factory(mailboxIdFactory));
 
-        eventBus = new RabbitMQEventBus(connectionFactory, eventSerializer);
-        eventBus2 = new RabbitMQEventBus(connectionFactory, eventSerializer);
+        eventBus = new RabbitMQEventBus(connectionFactory, eventSerializer, routingKeyConverter);
+        eventBus2 = new RabbitMQEventBus(connectionFactory, eventSerializer, routingKeyConverter);
         eventBus.start();
         eventBus2.start();
         sender = RabbitFlux.createSender(new SenderOptions().connectionMono(connectionMono));
@@ -117,6 +121,13 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
         return eventBus2;
     }
 
+    @Override
+    @Test
+    @Disabled("This test is failing by design as the different registration keys are handled by distinct messages")
+    public void dispatchShouldCallListenerOnceWhenSeveralKeysMatching() {
+
+    }
+
     @Nested
     class PublishingTest {
         private static final String MAILBOX_WORK_QUEUE_NAME = MAILBOX_EVENT + "-workQueue";
@@ -269,7 +280,7 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
 
             @BeforeEach
             void setUp() {
-                eventBus3 = new RabbitMQEventBus(connectionFactory, eventSerializer);
+                eventBus3 = new RabbitMQEventBus(connectionFactory, eventSerializer, routingKeyConverter);
                 eventBus3.start();
             }
 
@@ -368,4 +379,6 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
         }
 
     }
+
+
 }
\ 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


[06/17] james-project git commit: MAILBOX-371 Fix-up for LifeCycleTest more stable

Posted by bt...@apache.org.
MAILBOX-371 Fix-up for LifeCycleTest more stable


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

Branch: refs/heads/master
Commit: 5b9b106572488b8ce4f2173c9b6fe0b08b451fb6
Parents: af95d7b
Author: datph <dp...@linagora.com>
Authored: Mon Jan 14 15:24:35 2019 +0700
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Wed Jan 16 13:47:08 2019 +0700

----------------------------------------------------------------------
 .../mailbox/events/RabbitMQEventBusTest.java    | 25 ++++++++++----------
 1 file changed, 12 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/5b9b1065/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RabbitMQEventBusTest.java
----------------------------------------------------------------------
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 52a6e50..dbb125a 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
@@ -237,6 +237,11 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
 
     @Nested
     class LifeCycleTest {
+        private final Duration TEN_SECONDS = Duration.ofSeconds(10);
+
+        private static final int THREAD_COUNT = 10;
+        private static final int OPERATION_COUNT = 100;
+        private static final int MAX_EVENT_DISPATCHED_COUNT = THREAD_COUNT * OPERATION_COUNT;
 
         private RabbitMQManagementAPI rabbitManagementAPI;
 
@@ -298,13 +303,10 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
                 MailboxListenerCountingSuccessfulExecution listener = new MailboxListenerCountingSuccessfulExecution();
                 eventBus.register(listener, GROUP_A);
 
-                int threadCount = 10;
-                int operationCount = 1000;
-                int maxEventsDispatched = threadCount * operationCount;
                 ConcurrentTestRunner.builder()
                     .operation((threadNumber, step) -> eventBus.dispatch(EVENT, KEY_1))
-                    .threadCount(10)
-                    .operationCount(1000)
+                    .threadCount(THREAD_COUNT)
+                    .operationCount(OPERATION_COUNT)
                     .runSuccessfullyWithin(Duration.ofMinutes(1));
 
                 eventBus.stop();
@@ -313,7 +315,7 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
                 TimeUnit.SECONDS.sleep(1);
                 assertThat(listener.numberOfEventCalls())
                     .isEqualTo(callsAfterStop)
-                    .isLessThan(maxEventsDispatched);
+                    .isLessThan(MAX_EVENT_DISPATCHED_COUNT);
             }
         }
 
@@ -389,14 +391,11 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
                 eventBus.register(listener, GROUP_A);
                 eventBus2.register(listener, GROUP_A);
 
-                int threadCount = 10;
-                int operationCount = 1000;
-                int maxEventsDispatched = threadCount * operationCount;
                 ConcurrentTestRunner.builder()
                     .operation((threadNumber, step) -> eventBus.dispatch(EVENT, KEY_1))
-                    .threadCount(10)
-                    .operationCount(1000)
-                    .runSuccessfullyWithin(Duration.ofSeconds(5));
+                    .threadCount(THREAD_COUNT)
+                    .operationCount(OPERATION_COUNT)
+                    .runSuccessfullyWithin(TEN_SECONDS);
 
                 eventBus.stop();
                 eventBus2.stop();
@@ -405,7 +404,7 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
                 TimeUnit.SECONDS.sleep(1);
                 assertThat(listener.numberOfEventCalls())
                     .isEqualTo(callsAfterStop)
-                    .isLessThan(maxEventsDispatched);
+                    .isLessThan(MAX_EVENT_DISPATCHED_COUNT);
             }
         }
 


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


[16/17] james-project git commit: JAMES-2637 add tests for getSourcesForType

Posted by bt...@apache.org.
JAMES-2637 add tests for getSourcesForType


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

Branch: refs/heads/master
Commit: 2bbdb47d67230619970dd582e8cce24753732147
Parents: c826452
Author: Rene Cordier <rc...@linagora.com>
Authored: Tue Jan 15 15:21:00 2019 +0700
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Wed Jan 16 13:48:57 2019 +0700

----------------------------------------------------------------------
 .../lib/AbstractRecipientRewriteTableTest.java  | 43 ++++++++++++++++++++
 1 file changed, 43 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/2bbdb47d/server/data/data-library/src/test/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTableTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/test/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTableTest.java b/server/data/data-library/src/test/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTableTest.java
index 862a15a..3ab8c16 100644
--- a/server/data/data-library/src/test/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTableTest.java
+++ b/server/data/data-library/src/test/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTableTest.java
@@ -445,4 +445,47 @@ public abstract class AbstractRecipientRewriteTableTest {
 
         assertThat(virtualUserTable.listSources(groupMapping)).isEmpty();
     }
+
+    @Test
+    public void getSourcesForTypeShouldReturnEmptyWhenNoMapping() throws Exception {
+        assertThat(virtualUserTable.getSourcesForType(Mapping.Type.Alias)).isEmpty();
+    }
+
+    @Test
+    public void getSourcesForTypeShouldReturnEmptyWhenNoMatchingMapping() throws Exception {
+        virtualUserTable.addForwardMapping(SOURCE, ADDRESS);
+
+        assertThat(virtualUserTable.getSourcesForType(Mapping.Type.Alias)).isEmpty();
+    }
+
+    @Test
+    public void getSourcesForTypeShouldReturnMatchingMapping() throws Exception {
+        virtualUserTable.addAliasMapping(SOURCE, ADDRESS);
+
+        assertThat(virtualUserTable.getSourcesForType(Mapping.Type.Alias)).containsOnly(SOURCE);
+    }
+
+    @Test
+    public void getSourcesForTypeShouldNotReturnDuplicatedSources() throws Exception {
+        virtualUserTable.addAliasMapping(SOURCE, ADDRESS);
+        virtualUserTable.addAliasMapping(SOURCE, ADDRESS_2);
+
+        assertThat(virtualUserTable.getSourcesForType(Mapping.Type.Alias)).containsExactly(SOURCE);
+    }
+
+    @Test
+    public void getSourcesForTypeShouldReturnSortedList() throws Exception {
+        MappingSource source1 = MappingSource.fromUser("alice", Domain.LOCALHOST);
+        MappingSource source2 = MappingSource.fromUser("bob", Domain.LOCALHOST);
+        MappingSource source3 = MappingSource.fromUser("cedric", Domain.LOCALHOST);
+
+        virtualUserTable.addAliasMapping(source1, ADDRESS);
+        virtualUserTable.addAliasMapping(source3, ADDRESS);
+        virtualUserTable.addAliasMapping(source2, ADDRESS);
+
+        assertThat(virtualUserTable.getSourcesForType(Mapping.Type.Alias))
+            .containsExactly(source1, source2, source3);
+    }
+
+
 }


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


[04/17] james-project git commit: MAILBOX-371 Wrapping RabbitMQExtension to avoid start and stop several rabbit mq docker

Posted by bt...@apache.org.
MAILBOX-371 Wrapping RabbitMQExtension to avoid start and stop several rabbit mq docker


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

Branch: refs/heads/master
Commit: 9f3b7ec0f391ac36deb2b4fc130eca22fc5225a3
Parents: 7ce35a3
Author: datph <dp...@linagora.com>
Authored: Mon Jan 14 11:51:12 2019 +0700
Committer: datph <dp...@linagora.com>
Committed: Wed Jan 16 05:38:45 2019 +0700

----------------------------------------------------------------------
 .../mailbox/events/RabbitMQEventBusTest.java    | 47 +++++++++++++++++---
 1 file changed, 41 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/9f3b7ec0/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RabbitMQEventBusTest.java
----------------------------------------------------------------------
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 efa8380..aa4c5c6 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
@@ -51,11 +51,16 @@ import org.apache.james.mailbox.MailboxListener;
 import org.apache.james.mailbox.model.TestId;
 import org.apache.james.mailbox.model.TestMessageId;
 import org.apache.james.util.concurrency.ConcurrentTestRunner;
+import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.AfterEachCallback;
+import org.junit.jupiter.api.extension.BeforeEachCallback;
+import org.junit.jupiter.api.extension.ExtensionContext;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
 import com.rabbitmq.client.Connection;
@@ -74,8 +79,40 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
     EventBusConcurrentTestContract.SingleEventBusConcurrentContract, EventBusConcurrentTestContract.MultiEventBusConcurrentContract,
     KeyContract.SingleEventBusKeyContract, KeyContract.MultipleEventBusKeyContract {
 
+    static class RabbitMQEventExtension implements BeforeEachCallback, AfterEachCallback {
+        static final RabbitMQExtension rabbitMQExtension = new RabbitMQExtension();
+
+        void startRabbit() {
+            rabbitMQExtension.beforeAll(null);
+        }
+
+        void stopRabbit() {
+            rabbitMQExtension.afterAll(null);
+        }
+
+        @Override
+        public void beforeEach(ExtensionContext extensionContext) throws Exception {
+            rabbitMQExtension.beforeEach(extensionContext);
+        }
+
+        @Override
+        public void afterEach(ExtensionContext extensionContext) throws Exception {
+            rabbitMQExtension.afterEach(extensionContext);
+        }
+    }
+
+    @BeforeAll
+    static void beforeAll() {
+        testExtension.startRabbit();
+    }
+
+    @AfterAll
+    static void afterAll() {
+        testExtension.stopRabbit();
+    }
+
     @RegisterExtension
-    static RabbitMQExtension rabbitMQExtension = new RabbitMQExtension();
+    static RabbitMQEventExtension testExtension = new RabbitMQEventExtension();
 
     private RabbitMQEventBus eventBus;
     private RabbitMQEventBus eventBus2;
@@ -86,7 +123,7 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
 
     @BeforeEach
     void setUp() {
-        connectionFactory = rabbitMQExtension.getConnectionFactory();
+        connectionFactory = RabbitMQEventExtension.rabbitMQExtension.getConnectionFactory();
         Mono<Connection> connectionMono = Mono.fromSupplier(connectionFactory::create).cache();
 
         TestId.Factory mailboxIdFactory = new TestId.Factory();
@@ -170,7 +207,7 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
         }
 
         private Event dequeueEvent() {
-            RabbitMQConnectionFactory connectionFactory = rabbitMQExtension.getConnectionFactory();
+            RabbitMQConnectionFactory connectionFactory = RabbitMQEventExtension.rabbitMQExtension.getConnectionFactory();
             Receiver receiver = RabbitFlux.createReceiver(new ReceiverOptions().connectionMono(Mono.just(connectionFactory.create())));
 
             byte[] eventInBytes = receiver.consumeAutoAck(MAILBOX_WORK_QUEUE_NAME)
@@ -189,7 +226,7 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
 
         @BeforeEach
         void setUp() throws Exception {
-            rabbitManagementAPI = rabbitMQExtension.managementAPI();
+            rabbitManagementAPI = RabbitMQEventExtension.rabbitMQExtension.managementAPI();
         }
 
         @Nested
@@ -370,6 +407,4 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
         }
 
     }
-
-
 }
\ 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


[09/17] james-project git commit: JAMES-2637 Strong typing for AliasSourcesResponse

Posted by bt...@apache.org.
JAMES-2637 Strong typing for AliasSourcesResponse


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

Branch: refs/heads/master
Commit: 03420dab14aedf1cca60d0dfc722401afecfed57
Parents: 92f44f2
Author: Rene Cordier <rc...@linagora.com>
Authored: Tue Jan 15 14:57:40 2019 +0700
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Wed Jan 16 13:48:56 2019 +0700

----------------------------------------------------------------------
 .../org/apache/james/webadmin/dto/AliasSourcesResponse.java  | 8 +++++---
 .../java/org/apache/james/webadmin/routes/AliasRoutes.java   | 3 +--
 .../org/apache/james/webadmin/routes/AliasRoutesTest.java    | 4 +++-
 3 files changed, 9 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/03420dab/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/AliasSourcesResponse.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/AliasSourcesResponse.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/AliasSourcesResponse.java
index a57988b..09e6515 100644
--- a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/AliasSourcesResponse.java
+++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/AliasSourcesResponse.java
@@ -19,14 +19,16 @@
 
 package org.apache.james.webadmin.dto;
 
+import org.apache.james.rrt.lib.MappingSource;
+
 public class AliasSourcesResponse {
-    private final String source;
+    private final MappingSource source;
 
-    public AliasSourcesResponse(String source) {
+    public AliasSourcesResponse(MappingSource source) {
         this.source = source;
     }
 
-    public String getSource() {
+    public MappingSource getSource() {
         return source;
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/03420dab/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AliasRoutes.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AliasRoutes.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AliasRoutes.java
index f039559..e88febf 100644
--- a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AliasRoutes.java
+++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AliasRoutes.java
@@ -227,8 +227,7 @@ public class AliasRoutes implements Routes {
             .entrySet().stream()
             .filter(e -> e.getValue().contains(Mapping.alias(baseAddress.asString())))
             .map(Map.Entry::getKey)
-            .map(MappingSource::asMailAddressString)
-            .sorted()
+            .sorted(Comparator.comparing(MappingSource::asMailAddressString))
             .map(AliasSourcesResponse::new)
             .collect(Guavate.toImmutableSet());
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/03420dab/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/AliasRoutesTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/AliasRoutesTest.java b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/AliasRoutesTest.java
index af6e4e1..3142b8d 100644
--- a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/AliasRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/AliasRoutesTest.java
@@ -37,6 +37,7 @@ import org.apache.james.user.api.UsersRepository;
 import org.apache.james.user.memory.MemoryUsersRepository;
 import org.apache.james.webadmin.WebAdminServer;
 import org.apache.james.webadmin.WebAdminUtils;
+import org.apache.james.webadmin.dto.MappingSourceModule;
 import org.apache.james.webadmin.utils.JsonTransformer;
 import org.eclipse.jetty.http.HttpStatus;
 import org.junit.jupiter.api.AfterEach;
@@ -113,6 +114,7 @@ class AliasRoutesTest {
                 .autoDetect(false)
                 .autoDetectIp(false));
             domainList.addDomain(DOMAIN);
+            MappingSourceModule module = new MappingSourceModule();
 
             usersRepository = MemoryUsersRepository.withVirtualHosting();
             usersRepository.setDomainList(domainList);
@@ -122,7 +124,7 @@ class AliasRoutesTest {
             usersRepository.addUser(BOB_WITH_SLASH, BOB_WITH_SLASH_PASSWORD);
             usersRepository.addUser(ALICE, ALICE_PASSWORD);
 
-            createServer(new AliasRoutes(memoryRecipientRewriteTable, usersRepository, new JsonTransformer()));
+            createServer(new AliasRoutes(memoryRecipientRewriteTable, usersRepository, new JsonTransformer(module)));
         }
 
         @Test


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


[08/17] james-project git commit: JAMES-2637 refactoring forward and group routes

Posted by bt...@apache.org.
JAMES-2637 refactoring forward and group routes


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

Branch: refs/heads/master
Commit: 331a888c71674cc7f77a3a4cd836cd5561b742d2
Parents: b312b87
Author: Rene Cordier <rc...@linagora.com>
Authored: Thu Jan 10 17:34:40 2019 +0700
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Wed Jan 16 13:48:56 2019 +0700

----------------------------------------------------------------------
 .../james/modules/server/DataRoutesModules.java |  5 ++
 .../james/rrt/api/RecipientRewriteTable.java    | 12 +++-
 .../org/apache/james/rrt/lib/MappingSource.java | 19 ++++++-
 .../james/webadmin/dto/MappingSourceModule.java | 60 ++++++++++++++++++++
 .../james/webadmin/routes/ForwardRoutes.java    | 17 +-----
 .../james/webadmin/routes/GroupsRoutes.java     | 15 +----
 .../webadmin/routes/ForwardRoutesTest.java      |  8 ++-
 .../james/webadmin/routes/GroupsRoutesTest.java |  8 ++-
 8 files changed, 108 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/331a888c/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DataRoutesModules.java
----------------------------------------------------------------------
diff --git a/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DataRoutesModules.java b/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DataRoutesModules.java
index a2726af..f6400ea 100644
--- a/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DataRoutesModules.java
+++ b/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DataRoutesModules.java
@@ -20,12 +20,14 @@
 package org.apache.james.modules.server;
 
 import org.apache.james.webadmin.Routes;
+import org.apache.james.webadmin.dto.MappingSourceModule;
 import org.apache.james.webadmin.routes.AliasRoutes;
 import org.apache.james.webadmin.routes.DomainMappingsRoutes;
 import org.apache.james.webadmin.routes.DomainsRoutes;
 import org.apache.james.webadmin.routes.ForwardRoutes;
 import org.apache.james.webadmin.routes.GroupsRoutes;
 import org.apache.james.webadmin.routes.UserRoutes;
+import org.apache.james.webadmin.utils.JsonTransformerModule;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.multibindings.Multibinder;
@@ -41,5 +43,8 @@ public class DataRoutesModules extends AbstractModule {
         routesMultibinder.addBinding().to(ForwardRoutes.class);
         routesMultibinder.addBinding().to(GroupsRoutes.class);
         routesMultibinder.addBinding().to(UserRoutes.class);
+
+        Multibinder<JsonTransformerModule> jsonTransformerModuleMultibinder = Multibinder.newSetBinder(binder(), JsonTransformerModule.class);
+        jsonTransformerModuleMultibinder.addBinding().to(MappingSourceModule.class);
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/331a888c/server/data/data-api/src/main/java/org/apache/james/rrt/api/RecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/api/RecipientRewriteTable.java b/server/data/data-api/src/main/java/org/apache/james/rrt/api/RecipientRewriteTable.java
index 4970f1b..2c53f3a 100644
--- a/server/data/data-api/src/main/java/org/apache/james/rrt/api/RecipientRewriteTable.java
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/api/RecipientRewriteTable.java
@@ -115,9 +115,19 @@ public interface RecipientRewriteTable {
         Preconditions.checkArgument(listSourcesSupportedType.contains(mapping.getType()),
             String.format("Not supported mapping of type %s", mapping.getType()));
 
-        return getAllMappings().entrySet().stream()
+        return getAllMappings()
+            .entrySet().stream()
             .filter(entry -> entry.getValue().contains(mapping))
             .map(Map.Entry::getKey)
             .collect(Guavate.toImmutableList());
     }
+
+    default List<MappingSource> getSourcesForType(Mapping.Type type) throws RecipientRewriteTableException {
+        return getAllMappings()
+            .entrySet().stream()
+            .filter(e -> e.getValue().contains(type))
+            .map(Map.Entry::getKey)
+            .sorted()
+            .collect(Guavate.toImmutableList());
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/331a888c/server/data/data-api/src/main/java/org/apache/james/rrt/lib/MappingSource.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/MappingSource.java b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/MappingSource.java
index 7bd6298..68ad8b4 100644
--- a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/MappingSource.java
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/MappingSource.java
@@ -32,7 +32,7 @@ import org.apache.james.util.OptionalUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class MappingSource implements Serializable {
+public class MappingSource implements Serializable, Comparable<MappingSource> {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(MappingSource.class);
     private static final String WILDCARD = "*";
@@ -145,4 +145,21 @@ public class MappingSource implements Serializable {
     public final int hashCode() {
         return Objects.hash(domain, user, wildcard);
     }
+
+    @Override
+    public int compareTo(MappingSource mappingSource) {
+        final int result;
+        final MailAddress mailAddress1 = this.asMailAddress().get();
+        final MailAddress mailAddress2 = mappingSource.asMailAddress().get();
+
+        if (mailAddress1 == null) {
+            result = mailAddress2 == null ? 0 : 1;
+        } else if (mailAddress2 == null) {
+            result = -1;
+        } else {
+            result = mailAddress1.asString().compareTo(mailAddress2.asString());
+        }
+
+        return result;
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/331a888c/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/MappingSourceModule.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/MappingSourceModule.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/MappingSourceModule.java
new file mode 100644
index 0000000..424a04e
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/MappingSourceModule.java
@@ -0,0 +1,60 @@
+/****************************************************************
+ * 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.webadmin.dto;
+
+import java.io.IOException;
+import java.util.Optional;
+
+import org.apache.james.core.MailAddress;
+import org.apache.james.rrt.lib.MappingSource;
+import org.apache.james.webadmin.utils.JsonTransformerModule;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.Module;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+public class MappingSourceModule implements JsonTransformerModule {
+
+    private final SimpleModule simpleModule;
+
+    public MappingSourceModule() {
+        simpleModule = new SimpleModule()
+            .addSerializer(MappingSource.class, new JsonSerializer<MappingSource>() {
+                @Override
+                public void serialize(MappingSource t, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
+                    jsonGenerator.writeString(serialize(t.asMailAddress()));
+                }
+
+                private String serialize(Optional<MailAddress> mailAddress) {
+                    if (mailAddress.isPresent()) {
+                        return mailAddress.get().asString();
+                    }
+                    return "";
+                }
+            });
+    }
+
+    @Override
+    public Module asJacksonModule() {
+        return simpleModule;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/331a888c/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/ForwardRoutes.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/ForwardRoutes.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/ForwardRoutes.java
index d69a568..5484f58 100644
--- a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/ForwardRoutes.java
+++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/ForwardRoutes.java
@@ -23,9 +23,6 @@ import static org.apache.james.webadmin.Constants.SEPARATOR;
 import static spark.Spark.halt;
 
 import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
 
 import javax.inject.Inject;
 import javax.ws.rs.DELETE;
@@ -44,7 +41,6 @@ import org.apache.james.rrt.lib.MappingSource;
 import org.apache.james.rrt.lib.Mappings;
 import org.apache.james.user.api.UsersRepository;
 import org.apache.james.user.api.UsersRepositoryException;
-import org.apache.james.util.OptionalUtils;
 import org.apache.james.webadmin.Constants;
 import org.apache.james.webadmin.Routes;
 import org.apache.james.webadmin.dto.ForwardDestinationResponse;
@@ -56,7 +52,6 @@ import org.eclipse.jetty.http.HttpStatus;
 import com.github.steveash.guavate.Guavate;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSortedSet;
 
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
@@ -128,16 +123,8 @@ public class ForwardRoutes implements Routes {
         @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500,
             message = "Internal server error - Something went bad on the server side.")
     })
-    public Set<String> listForwards(Request request, Response response) throws RecipientRewriteTableException {
-        return Optional.ofNullable(recipientRewriteTable.getAllMappings())
-            .map(mappings ->
-                mappings.entrySet().stream()
-                    .filter(e -> e.getValue().contains(Mapping.Type.Forward))
-                    .map(Map.Entry::getKey)
-                    .flatMap(source -> OptionalUtils.toStream(source.asMailAddress()))
-                    .map(MailAddress::asString)
-                    .collect(Guavate.toImmutableSortedSet()))
-            .orElse(ImmutableSortedSet.of());
+    public List<MappingSource> listForwards(Request request, Response response) throws RecipientRewriteTableException {
+        return recipientRewriteTable.getSourcesForType(Mapping.Type.Forward);
     }
 
     @PUT

http://git-wip-us.apache.org/repos/asf/james-project/blob/331a888c/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/GroupsRoutes.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/GroupsRoutes.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/GroupsRoutes.java
index 3ce454e..f191b31 100644
--- a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/GroupsRoutes.java
+++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/GroupsRoutes.java
@@ -23,9 +23,6 @@ import static org.apache.james.webadmin.Constants.SEPARATOR;
 import static spark.Spark.halt;
 
 import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
 
 import javax.inject.Inject;
 import javax.ws.rs.DELETE;
@@ -123,16 +120,8 @@ public class GroupsRoutes implements Routes {
         @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500,
             message = "Internal server error - Something went bad on the server side.")
     })
-    public Set<String> listGroups(Request request, Response response) throws RecipientRewriteTableException {
-        return Optional.ofNullable(recipientRewriteTable.getAllMappings())
-            .map(mappings ->
-                mappings.entrySet().stream()
-                    .filter(e -> e.getValue().contains(Mapping.Type.Group))
-                    .map(Map.Entry::getKey)
-                    .flatMap(source -> OptionalUtils.toStream(source.asMailAddress()))
-                    .map(MailAddress::asString)
-                    .collect(Guavate.toImmutableSortedSet()))
-            .orElse(ImmutableSortedSet.of());
+    public List<MappingSource> listGroups(Request request, Response response) throws RecipientRewriteTableException {
+        return recipientRewriteTable.getSourcesForType(Mapping.Type.Group);
     }
 
     @PUT

http://git-wip-us.apache.org/repos/asf/james-project/blob/331a888c/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/ForwardRoutesTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/ForwardRoutesTest.java b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/ForwardRoutesTest.java
index 288b050..f254860 100644
--- a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/ForwardRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/ForwardRoutesTest.java
@@ -52,6 +52,7 @@ import org.apache.james.user.api.UsersRepository;
 import org.apache.james.user.memory.MemoryUsersRepository;
 import org.apache.james.webadmin.WebAdminServer;
 import org.apache.james.webadmin.WebAdminUtils;
+import org.apache.james.webadmin.dto.MappingSourceModule;
 import org.apache.james.webadmin.utils.JsonTransformer;
 import org.eclipse.jetty.http.HttpStatus;
 import org.junit.jupiter.api.AfterEach;
@@ -113,6 +114,7 @@ class ForwardRoutesTest {
                 .autoDetect(false)
                 .autoDetectIp(false));
             domainList.addDomain(DOMAIN);
+            MappingSourceModule mappingSourceModule = new MappingSourceModule();
 
             usersRepository = MemoryUsersRepository.withVirtualHosting();
             usersRepository.setDomainList(domainList);
@@ -123,7 +125,7 @@ class ForwardRoutesTest {
             usersRepository.addUser(ALICE_WITH_SLASH, ALICE_SLASH_PASSWORD);
             usersRepository.addUser(CEDRIC, CEDRIC_PASSWORD);
 
-            createServer(new ForwardRoutes(memoryRecipientRewriteTable, usersRepository, new JsonTransformer()));
+            createServer(new ForwardRoutes(memoryRecipientRewriteTable, usersRepository, new JsonTransformer(mappingSourceModule)));
         }
 
         @Test
@@ -617,7 +619,7 @@ class ForwardRoutesTest {
         void getAllShouldReturnErrorWhenRecipientRewriteTableExceptionIsThrown() throws Exception {
             doThrow(RecipientRewriteTableException.class)
                 .when(memoryRecipientRewriteTable)
-                .getAllMappings();
+                .getSourcesForType(any());
 
             when()
                 .get()
@@ -629,7 +631,7 @@ class ForwardRoutesTest {
         void getAllShouldReturnErrorWhenRuntimeExceptionIsThrown() throws Exception {
             doThrow(RuntimeException.class)
                 .when(memoryRecipientRewriteTable)
-                .getAllMappings();
+                .getSourcesForType(any());
 
             when()
                 .get()

http://git-wip-us.apache.org/repos/asf/james-project/blob/331a888c/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/GroupsRoutesTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/GroupsRoutesTest.java b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/GroupsRoutesTest.java
index 1edf80d..713a8ff 100644
--- a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/GroupsRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/GroupsRoutesTest.java
@@ -50,6 +50,7 @@ import org.apache.james.user.api.UsersRepositoryException;
 import org.apache.james.user.memory.MemoryUsersRepository;
 import org.apache.james.webadmin.WebAdminServer;
 import org.apache.james.webadmin.WebAdminUtils;
+import org.apache.james.webadmin.dto.MappingSourceModule;
 import org.apache.james.webadmin.utils.JsonTransformer;
 import org.eclipse.jetty.http.HttpStatus;
 import org.junit.jupiter.api.AfterEach;
@@ -109,7 +110,8 @@ class GroupsRoutesTest {
             domainList.addDomain(DOMAIN);
             usersRepository = MemoryUsersRepository.withVirtualHosting();
             usersRepository.setDomainList(domainList);
-            createServer(new GroupsRoutes(memoryRecipientRewriteTable, usersRepository, domainList, new JsonTransformer()));
+            MappingSourceModule mappingSourceModule = new MappingSourceModule();
+            createServer(new GroupsRoutes(memoryRecipientRewriteTable, usersRepository, domainList, new JsonTransformer(mappingSourceModule)));
         }
 
         @Test
@@ -622,7 +624,7 @@ class GroupsRoutesTest {
         void getAllShouldReturnErrorWhenRecipientRewriteTableExceptionIsThrown() throws Exception {
             doThrow(RecipientRewriteTableException.class)
                 .when(memoryRecipientRewriteTable)
-                .getAllMappings();
+                .getSourcesForType(any());
 
             when()
                 .get()
@@ -634,7 +636,7 @@ class GroupsRoutesTest {
         void getAllShouldReturnErrorWhenRuntimeExceptionIsThrown() throws Exception {
             doThrow(RuntimeException.class)
                 .when(memoryRecipientRewriteTable)
-                .getAllMappings();
+                .getSourcesForType(any());
 
             when()
                 .get()


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


[02/17] james-project git commit: MAILBOX-371 Remove unnecessary test for lifecycle

Posted by bt...@apache.org.
MAILBOX-371 Remove unnecessary test for lifecycle

This test is in SingleLifeCycleTest, There is another equivalent test
with multiple event bus. Remove this because it is impossible to passed
when RabbitMQEventBusTest also implements MultipleLifeCycleTest, then in
setup phrase, two eventbus are up, that means, stopping one eventbus
doesn't make queue registration for key deleted. (Because there is another
eventbus is consuming this queue!)


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

Branch: refs/heads/master
Commit: 7ce35a3784b7722392e6a12c4e021a08bfb9cfe6
Parents: 68735a2
Author: datph <dp...@linagora.com>
Authored: Mon Jan 14 11:02:44 2019 +0700
Committer: datph <dp...@linagora.com>
Committed: Wed Jan 16 05:38:45 2019 +0700

----------------------------------------------------------------------
 .../apache/james/mailbox/events/RabbitMQEventBusTest.java   | 9 ---------
 1 file changed, 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/7ce35a37/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RabbitMQEventBusTest.java
----------------------------------------------------------------------
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 0daf7f0..efa8380 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
@@ -225,15 +225,6 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
             }
 
             @Test
-            void stopShouldDeleteKeyRegistrationWorkQueue() {
-                eventBus.start();
-                eventBus.stop();
-
-                assertThat(rabbitManagementAPI.listQueues())
-                    .isEmpty();
-            }
-
-            @Test
             void eventBusShouldNotThrowWhenContinuouslyStartAndStop() {
                 assertThatCode(() -> {
                     eventBus.start();


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


[14/17] james-project git commit: JAMES-2637 add getMappingsForType method with tests

Posted by bt...@apache.org.
JAMES-2637 add getMappingsForType method with tests


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

Branch: refs/heads/master
Commit: 03ee195d1b5272f365cc9462712a2f5a15fb87d3
Parents: 2bbdb47
Author: Rene Cordier <rc...@linagora.com>
Authored: Tue Jan 15 15:42:26 2019 +0700
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Wed Jan 16 13:48:57 2019 +0700

----------------------------------------------------------------------
 .../james/rrt/api/RecipientRewriteTable.java    | 13 ++++++
 .../lib/AbstractRecipientRewriteTableTest.java  | 45 ++++++++++++++++++++
 .../james/webadmin/routes/AliasRoutes.java      |  8 +---
 .../james/webadmin/routes/AliasRoutesTest.java  |  4 +-
 4 files changed, 61 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/03ee195d/server/data/data-api/src/main/java/org/apache/james/rrt/api/RecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/api/RecipientRewriteTable.java b/server/data/data-api/src/main/java/org/apache/james/rrt/api/RecipientRewriteTable.java
index 378c10e..3a15f72 100644
--- a/server/data/data-api/src/main/java/org/apache/james/rrt/api/RecipientRewriteTable.java
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/api/RecipientRewriteTable.java
@@ -22,14 +22,17 @@ import java.util.Comparator;
 import java.util.EnumSet;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Stream;
 
 import org.apache.james.core.Domain;
 import org.apache.james.rrt.lib.Mapping;
 import org.apache.james.rrt.lib.MappingSource;
 import org.apache.james.rrt.lib.Mappings;
+import org.apache.james.rrt.lib.MappingsImpl;
 
 import com.github.steveash.guavate.Guavate;
 import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
 
 /**
  * Interface which should be implemented of classes which map recipients.
@@ -131,4 +134,14 @@ public interface RecipientRewriteTable {
             .sorted(Comparator.comparing(MappingSource::asMailAddressString))
             .collect(Guavate.toImmutableList());
     }
+
+    default Stream<Mapping> getMappingsForType(Mapping.Type type) throws RecipientRewriteTableException {
+        return ImmutableSet.copyOf(getAllMappings()
+            .values().stream()
+            .map(mappings -> mappings.select(type))
+            .reduce(Mappings::union)
+            .orElse(MappingsImpl.empty()))
+            .stream();
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/03ee195d/server/data/data-library/src/test/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTableTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/test/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTableTest.java b/server/data/data-library/src/test/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTableTest.java
index 3ab8c16..f5e26af 100644
--- a/server/data/data-library/src/test/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTableTest.java
+++ b/server/data/data-library/src/test/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTableTest.java
@@ -487,5 +487,50 @@ public abstract class AbstractRecipientRewriteTableTest {
             .containsExactly(source1, source2, source3);
     }
 
+    @Test
+    public void getMappingsForTypeShouldReturnEmptyWhenNoMapping() throws Exception {
+        assertThat(virtualUserTable.getMappingsForType(Mapping.Type.Alias)).isEmpty();
+    }
+
+    @Test
+    public void getMappingsForTypeShouldReturnEmptyWhenNoMatchingMapping() throws Exception {
+        virtualUserTable.addForwardMapping(SOURCE, ADDRESS);
+
+        assertThat(virtualUserTable.getMappingsForType(Mapping.Type.Alias)).isEmpty();
+    }
+
+    @Test
+    public void getMappingsForTypeShouldReturnMatchingMapping() throws Exception {
+        virtualUserTable.addAliasMapping(SOURCE, ADDRESS);
+
+        assertThat(virtualUserTable.getMappingsForType(Mapping.Type.Alias)).containsOnly(Mapping.alias(ADDRESS));
+    }
+
+    @Test
+    public void getMappingsForTypeShouldNotReturnDuplicatedDestinations() throws Exception {
+        MappingSource source2 = MappingSource.fromUser("bob", Domain.LOCALHOST);
+
+        virtualUserTable.addAliasMapping(SOURCE, ADDRESS);
+        virtualUserTable.addAliasMapping(source2, ADDRESS);
+
+        assertThat(virtualUserTable.getMappingsForType(Mapping.Type.Alias)).containsExactly(Mapping.alias(ADDRESS));
+    }
+
+    @Test
+    public void getMappingsForTypeShouldReturnSortedList() throws Exception {
+        String address1 = "alice@domain.com";
+        String address2 = "bob@domain.com";
+        String address3 = "cedric@domain.com";
+        Mapping mapping1 = Mapping.alias(address1);
+        Mapping mapping2 = Mapping.alias(address2);
+        Mapping mapping3 = Mapping.alias(address3);
+
+        virtualUserTable.addAliasMapping(SOURCE, address1);
+        virtualUserTable.addAliasMapping(SOURCE, address3);
+        virtualUserTable.addAliasMapping(SOURCE, address2);
+
+        assertThat(virtualUserTable.getMappingsForType(Mapping.Type.Alias))
+            .containsExactly(mapping1, mapping2, mapping3);
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/03ee195d/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AliasRoutes.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AliasRoutes.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AliasRoutes.java
index ceb29af..475a428 100644
--- a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AliasRoutes.java
+++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AliasRoutes.java
@@ -24,7 +24,6 @@ import static spark.Spark.halt;
 
 import java.util.Comparator;
 import java.util.List;
-import java.util.Map;
 
 import javax.inject.Inject;
 import javax.ws.rs.DELETE;
@@ -41,7 +40,6 @@ import org.apache.james.rrt.api.RecipientRewriteTableException;
 import org.apache.james.rrt.api.SameSourceAndDestinationException;
 import org.apache.james.rrt.lib.Mapping;
 import org.apache.james.rrt.lib.MappingSource;
-import org.apache.james.rrt.lib.Mappings;
 import org.apache.james.user.api.UsersRepository;
 import org.apache.james.user.api.UsersRepositoryException;
 import org.apache.james.util.OptionalUtils;
@@ -117,11 +115,7 @@ public class AliasRoutes implements Routes {
             message = "Internal server error - Something went bad on the server side.")
     })
     public ImmutableSet<String> listAddressesWithAliases(Request request, Response response) throws RecipientRewriteTableException {
-        return recipientRewriteTable.getAllMappings()
-            .entrySet().stream()
-            .filter(e -> e.getValue().contains(Mapping.Type.Alias))
-            .map(Map.Entry::getValue)
-            .flatMap(Mappings::asStream)
+        return recipientRewriteTable.getMappingsForType(Mapping.Type.Alias)
             .flatMap(mapping -> OptionalUtils.toStream(mapping.asMailAddress()))
             .map(MailAddress::asString)
             .collect(Guavate.toImmutableSortedSet());

http://git-wip-us.apache.org/repos/asf/james-project/blob/03ee195d/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/AliasRoutesTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/AliasRoutesTest.java b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/AliasRoutesTest.java
index 5835e49..52717f3 100644
--- a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/AliasRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/AliasRoutesTest.java
@@ -562,7 +562,7 @@ class AliasRoutesTest {
         void getAllShouldReturnErrorWhenRecipientRewriteTableExceptionIsThrown() throws Exception {
             doThrow(RecipientRewriteTableException.class)
                 .when(memoryRecipientRewriteTable)
-                .getAllMappings();
+                .getMappingsForType(any());
 
             when()
                 .get()
@@ -574,7 +574,7 @@ class AliasRoutesTest {
         void getAllShouldReturnErrorWhenRuntimeExceptionIsThrown() throws Exception {
             doThrow(RuntimeException.class)
                 .when(memoryRecipientRewriteTable)
-                .getAllMappings();
+                .getMappingsForType(any());
 
             when()
                 .get()


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