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

[01/27] james-project git commit: JAMES-2366 rename checkMapping to make it clear it checks entry doesn't already exist

Repository: james-project
Updated Branches:
  refs/heads/master ff231f907 -> 776fc33ac


JAMES-2366 rename checkMapping to make it clear it checks entry doesn't already exist


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

Branch: refs/heads/master
Commit: bfec1afecd1b27db9862bd51e953ad4bc3184e54
Parents: 565c6a2
Author: Matthieu Baechler <ma...@apache.org>
Authored: Wed Apr 18 16:42:15 2018 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:45:26 2018 +0200

----------------------------------------------------------------------
 .../james/rrt/lib/AbstractRecipientRewriteTable.java    | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/bfec1afe/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
index d028eca..5f7d9d7 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
@@ -182,7 +182,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
         }
 
         Mapping mapping = Mapping.regex(regex);
-        checkMapping(user, domain, mapping);
+        checkDuplicateMapping(user, domain, mapping);
         LOGGER.info("Add regex mapping => {} for user: {} domain: {}", regex, user, domain.name());
         addMapping(user, domain, mapping);
 
@@ -200,7 +200,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
             .appendDomainFromThrowingSupplierIfNone(this::defaultDomain);
 
         checkHasValidAddress(mapping);
-        checkMapping(user, domain, mapping);
+        checkDuplicateMapping(user, domain, mapping);
 
         LOGGER.info("Add address mapping => {} for user: {} domain: {}", mapping, user, domain.name());
         addMapping(user, domain, mapping);
@@ -233,7 +233,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
     public void addErrorMapping(String user, Domain domain, String error) throws RecipientRewriteTableException {
         Mapping mapping = Mapping.error(error);
 
-        checkMapping(user, domain, mapping);
+        checkDuplicateMapping(user, domain, mapping);
         LOGGER.info("Add error mapping => {} for user: {} domain: {}", error, user, domain.name());
         addMapping(user, domain, mapping);
 
@@ -263,7 +263,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
             .appendDomainFromThrowingSupplierIfNone(this::defaultDomain);
 
         checkHasValidAddress(mapping);
-        checkMapping(user, domain, mapping);
+        checkDuplicateMapping(user, domain, mapping);
 
         LOGGER.info("Add forward mapping => {} for user: {} domain: {}", mapping, user, domain.name());
         addMapping(user, domain, mapping);
@@ -284,7 +284,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
             .appendDomainFromThrowingSupplierIfNone(this::defaultDomain);
 
         checkHasValidAddress(mapping);
-        checkMapping(user, domain, mapping);
+        checkDuplicateMapping(user, domain, mapping);
 
         LOGGER.info("Add forward mapping => {} for user: {} domain: {}", mapping, user, domain.name());
         addMapping(user, domain, mapping);
@@ -313,7 +313,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
      */
     protected abstract Mappings mapAddress(String user, Domain domain) throws RecipientRewriteTableException;
 
-    private void checkMapping(String user, Domain domain, Mapping mapping) throws RecipientRewriteTableException {
+    private void checkDuplicateMapping(String user, Domain domain, Mapping mapping) throws RecipientRewriteTableException {
         Mappings mappings = getUserDomainMappings(user, domain);
         if (mappings != null && mappings.contains(mapping)) {
             throw new RecipientRewriteTableException("Mapping " + mapping + " for user " + user + " domain " + domain + " already exist!");


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


[04/27] james-project git commit: JAMES-2366 Avoid String parsing for default domain appending

Posted by ma...@apache.org.
JAMES-2366 Avoid String parsing for default domain appending


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

Branch: refs/heads/master
Commit: a71d033fa4b9aff6aa7563e4fae2482705c8421a
Parents: a64ee17
Author: benwa <bt...@linagora.com>
Authored: Wed Apr 18 09:17:31 2018 +0700
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:45:26 2018 +0200

----------------------------------------------------------------------
 .../main/java/org/apache/james/core/User.java   | 22 +++++++++++++++-----
 .../java/org/apache/james/core/UserTest.java    | 16 +++++++++++++-
 .../rrt/lib/AbstractRecipientRewriteTable.java  | 16 +++++---------
 3 files changed, 37 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/a71d033f/core/src/main/java/org/apache/james/core/User.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/james/core/User.java b/core/src/main/java/org/apache/james/core/User.java
index 40f5069..8b5421e 100644
--- a/core/src/main/java/org/apache/james/core/User.java
+++ b/core/src/main/java/org/apache/james/core/User.java
@@ -47,8 +47,13 @@ public class User {
     public static User fromLocalPartWithDomain(String localPart, String domain) {
         Preconditions.checkNotNull(domain);
 
-        return from(localPart,
-            Optional.of(domain));
+        return fromLocalPartWithDomain(localPart, Domain.of(domain));
+    }
+
+    public static User fromLocalPartWithDomain(String localPart, Domain domain) {
+        Preconditions.checkNotNull(domain);
+
+        return new User(localPart, Optional.of(domain));
     }
 
     public static User fromLocalPartWithoutDomain(String localPart) {
@@ -57,19 +62,19 @@ public class User {
     }
 
     public static User from(String localPart, Optional<String> domain) {
-       return new User(localPart, domain);
+       return new User(localPart, domain.map(Domain::of));
     }
 
     private final String localPart;
     private final Optional<Domain> domainPart;
 
-    private User(String localPart, Optional<String> domainPart) {
+    private User(String localPart, Optional<Domain> domainPart) {
         Preconditions.checkNotNull(localPart);
         Preconditions.checkArgument(!localPart.isEmpty(), "username should not be empty");
         Preconditions.checkArgument(!localPart.contains("@"), "username can not contain domain delimiter");
 
         this.localPart = localPart;
-        this.domainPart = domainPart.map(Domain::of);
+        this.domainPart = domainPart;
     }
 
     public String getLocalPart() {
@@ -84,6 +89,13 @@ public class User {
         return domainPart.isPresent();
     }
 
+    public User withDefaultDomain(Domain defaultDomain) {
+        if (hasDomainPart()) {
+            return this;
+        }
+        return new User(localPart, Optional.of(defaultDomain));
+    }
+
     public String asString() {
         return domainPart.map(domain -> localPart + "@" + domain.asString())
             .orElse(localPart);

http://git-wip-us.apache.org/repos/asf/james-project/blob/a71d033f/core/src/test/java/org/apache/james/core/UserTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/james/core/UserTest.java b/core/src/test/java/org/apache/james/core/UserTest.java
index bc97eba..cd4e60a 100644
--- a/core/src/test/java/org/apache/james/core/UserTest.java
+++ b/core/src/test/java/org/apache/james/core/UserTest.java
@@ -78,7 +78,8 @@ public class UserTest {
 
     @Test
     public void fromLocalPartWithDomainStringVersionShouldThrowOnNullDomainPart() {
-        assertThatThrownBy(() -> User.fromLocalPartWithDomain("local", null))
+        String domain = null;
+        assertThatThrownBy(() -> User.fromLocalPartWithDomain("local", domain))
             .isInstanceOf(NullPointerException.class);
     }
 
@@ -178,4 +179,17 @@ public class UserTest {
             .isTrue();
     }
 
+    @Test
+    public void withDefaultDomainShouldAppendDefaultDomainWhenNone() {
+        assertThat(User.fromUsername("user")
+            .withDefaultDomain(Domain.LOCALHOST))
+            .isEqualTo(User.fromLocalPartWithDomain("user", Domain.LOCALHOST));
+    }
+
+    @Test
+    public void withDefaultDomainShouldNotAppendDefaultDomainWhenDomainIsPresent() {
+        assertThat(User.fromUsername("user@domain")
+            .withDefaultDomain(Domain.LOCALHOST))
+            .isEqualTo(User.fromUsername("user@domain"));
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/a71d033f/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
index ce9701c..23c60c2 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
@@ -31,6 +31,7 @@ import org.apache.commons.configuration.ConfigurationException;
 import org.apache.commons.configuration.HierarchicalConfiguration;
 import org.apache.james.core.Domain;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.User;
 import org.apache.james.domainlist.api.DomainList;
 import org.apache.james.domainlist.api.DomainListException;
 import org.apache.james.lifecycle.api.Configurable;
@@ -139,18 +140,11 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
             return Stream.of(toMapping(addressWithMappingApplied, target.getType()));
         }
 
-        String userName;
-        Domain targetDomain;
-        String[] args = addressWithMappingApplied.split("@");
+        User coreUser = User.fromUsername(addressWithMappingApplied)
+            .withDefaultDomain(domain);
 
-        if (args.length > 1) {
-            userName = args[0];
-            targetDomain = Domain.of(args[1]);
-        } else {
-            // TODO Is that the right todo here?
-            userName = addressWithMappingApplied;
-            targetDomain = domain;
-        }
+        String userName = coreUser.getLocalPart();
+        Domain targetDomain = coreUser.getDomainPart().get();
 
         // Check if the returned mapping is the same as the
         // input. If so return null to avoid loops


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


[13/27] james-project git commit: JAMES-2366 Behaviour upon identity should be specified in Mapping::Type

Posted by ma...@apache.org.
JAMES-2366 Behaviour upon identity should be specified in Mapping::Type


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

Branch: refs/heads/master
Commit: f08343ddef434e5fdd2549d69fca4cb828f1e68c
Parents: 8947eee
Author: benwa <bt...@linagora.com>
Authored: Wed Apr 18 09:58:33 2018 +0700
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:45:26 2018 +0200

----------------------------------------------------------------------
 .../java/org/apache/james/rrt/lib/Mapping.java  | 38 ++++++++++++++++----
 .../rrt/lib/SkipMappingProcessingException.java | 24 +++++++++++++
 .../rrt/lib/AbstractRecipientRewriteTable.java  | 25 ++++++-------
 3 files changed, 66 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/f08343dd/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
index 3a7757a..c494d8b 100644
--- a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
@@ -22,7 +22,9 @@ package org.apache.james.rrt.lib;
 
 import java.util.Optional;
 import java.util.function.Supplier;
+import java.util.stream.Stream;
 
+import org.apache.commons.lang3.NotImplementedException;
 import org.apache.james.core.Domain;
 import org.apache.james.core.MailAddress;
 import org.apache.james.rrt.api.RecipientRewriteTableException;
@@ -53,17 +55,19 @@ public interface Mapping {
     Optional<MailAddress> asMailAddress();
 
     enum Type {
-        Regex("regex:"),
-        Domain("domain:"),
-        Error("error:"),
-        Forward("forward:"),
-        Group("group:"),
-        Address("");
+        Regex("regex:", IdentityMappingBehaviour.Throw),
+        Domain("domain:", IdentityMappingBehaviour.Throw),
+        Error("error:", IdentityMappingBehaviour.Throw),
+        Forward("forward:", IdentityMappingBehaviour.ReturnIdentity),
+        Group("group:", IdentityMappingBehaviour.Throw),
+        Address("", IdentityMappingBehaviour.Throw);
 
         private final String asPrefix;
+        private final IdentityMappingBehaviour identityMappingBehaviour;
 
-        Type(String asPrefix) {
+        Type(String asPrefix, IdentityMappingBehaviour identityMappingBehaviour) {
             this.asPrefix = asPrefix;
+            this.identityMappingBehaviour = identityMappingBehaviour;
         }
 
         public String asPrefix() {
@@ -82,6 +86,26 @@ public interface Mapping {
                 || mapping.startsWith(Forward.asPrefix())
                 || mapping.startsWith(Group.asPrefix());
         }
+
+        public IdentityMappingBehaviour getIdentityMappingBehaviour() {
+            return identityMappingBehaviour;
+        }
+    }
+
+    enum IdentityMappingBehaviour {
+        Throw,
+        ReturnIdentity;
+
+        public Stream<Mapping> handleIdentity(Stream<Mapping> mapping) {
+            switch (this) {
+                case Throw:
+                    throw new SkipMappingProcessingException();
+                case ReturnIdentity:
+                    return mapping;
+                default:
+                    throw new NotImplementedException("Unknown IdentityMappingBehaviour : " + this);
+            }
+        }
     }
 
     Type getType();

http://git-wip-us.apache.org/repos/asf/james-project/blob/f08343dd/server/data/data-api/src/main/java/org/apache/james/rrt/lib/SkipMappingProcessingException.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/SkipMappingProcessingException.java b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/SkipMappingProcessingException.java
new file mode 100644
index 0000000..00a62e1
--- /dev/null
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/SkipMappingProcessingException.java
@@ -0,0 +1,24 @@
+/****************************************************************
+ * 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;
+
+public class SkipMappingProcessingException extends RuntimeException {
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/f08343dd/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
index f5da229..1632414 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
@@ -118,20 +118,16 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
             return MappingsImpl.fromMappings(
                 targetMappings.asStream()
                     .flatMap(Throwing.<Mapping, Stream<Mapping>>function(target -> convertAndRecurseMapping(user, target, mappingLimit)).sneakyThrow()));
-        } catch (EmptyMappingException e) {
+        } catch (SkipMappingProcessingException e) {
             return MappingsImpl.empty();
         }
     }
 
-    private static class EmptyMappingException extends RuntimeException {
-
-    }
-
-    private Stream<Mapping> convertAndRecurseMapping(User user, Mapping associatedMapping, int remainingLoops) throws ErrorMappingException, RecipientRewriteTableException, EmptyMappingException, AddressException {
+    private Stream<Mapping> convertAndRecurseMapping(User user, Mapping associatedMapping, int remainingLoops) throws ErrorMappingException, RecipientRewriteTableException, SkipMappingProcessingException, AddressException {
 
         Function<String, Stream<Mapping>> convertAndRecurseMapping =
             Throwing
-                .function((String stringMapping) -> convertAndRecurseMapping(associatedMapping.getType(), user, remainingLoops, stringMapping))
+                .function((String stringMapping) -> convertAndRecurseMapping(associatedMapping.getType(), user, stringMapping, remainingLoops))
                 .sneakyThrow();
 
         return associatedMapping.apply(user.asMailAddress())
@@ -139,7 +135,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
             .orElse(Stream.empty());
     }
 
-    private Stream<Mapping> convertAndRecurseMapping(Type mappingType, User originalUser, int remainingLoops, String addressWithMappingApplied) throws ErrorMappingException, RecipientRewriteTableException {
+    private Stream<Mapping> convertAndRecurseMapping(Type mappingType, User originalUser, String addressWithMappingApplied, int remainingLoops) throws ErrorMappingException, RecipientRewriteTableException {
         LOGGER.debug("Valid virtual user mapping {} to {}", originalUser, addressWithMappingApplied);
 
         Stream<Mapping> nonRecursiveResult = Stream.of(toMapping(addressWithMappingApplied, mappingType));
@@ -150,15 +146,16 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
         User targetUser = User.fromUsername(addressWithMappingApplied)
             .withDefaultDomain(originalUser.getDomainPart().get());
 
-        // Check if the returned mapping is the same as the
-        // input. If so return null to avoid loops
+        // Check if the returned mapping is the same as the input. If so we need to handle identity to avoid loops.
         if (originalUser.equals(targetUser)) {
-            if (mappingType.equals(Type.Forward)) {
-                return nonRecursiveResult;
-            }
-            throw new EmptyMappingException();
+            return mappingType.getIdentityMappingBehaviour()
+                .handleIdentity(nonRecursiveResult);
+        } else {
+            return recurseMapping(nonRecursiveResult, targetUser, remainingLoops);
         }
+    }
 
+    private Stream<Mapping> recurseMapping(Stream<Mapping> nonRecursiveResult, User targetUser, int remainingLoops) throws ErrorMappingException, RecipientRewriteTableException {
         Mappings childMappings = getMappings(targetUser, remainingLoops - 1);
 
         if (childMappings.isEmpty()) {


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


[15/27] james-project git commit: JAMES-2366 WebAdmin Group API should rely on RRT group

Posted by ma...@apache.org.
JAMES-2366 WebAdmin Group API should rely on RRT group


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

Branch: refs/heads/master
Commit: 6368cb0604200421cd39c64f6164ae129ccae777
Parents: 7208b3ce
Author: benwa <bt...@linagora.com>
Authored: Fri Apr 6 11:34:52 2018 +0700
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:45:26 2018 +0200

----------------------------------------------------------------------
 .../james/cli/probe/impl/JmxDataProbe.java      | 31 +++++++++++++++++---
 .../org/apache/james/utils/DataProbeImpl.java   | 10 +++++++
 .../java/org/apache/james/probe/DataProbe.java  |  4 +++
 .../RecipientRewriteTableManagementMBean.java   | 24 +++++++++++++++
 .../lib/RecipientRewriteTableManagement.java    | 17 +++++++++++
 .../WebAdminServerIntegrationTest.java          |  4 +--
 .../james/webadmin/routes/GroupsRoutes.java     |  8 ++---
 .../james/webadmin/routes/GroupsRoutesTest.java | 12 ++++----
 8 files changed, 94 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/6368cb06/server/container/cli/src/main/java/org/apache/james/cli/probe/impl/JmxDataProbe.java
----------------------------------------------------------------------
diff --git a/server/container/cli/src/main/java/org/apache/james/cli/probe/impl/JmxDataProbe.java b/server/container/cli/src/main/java/org/apache/james/cli/probe/impl/JmxDataProbe.java
index 4e24f18..9cc3b60 100644
--- a/server/container/cli/src/main/java/org/apache/james/cli/probe/impl/JmxDataProbe.java
+++ b/server/container/cli/src/main/java/org/apache/james/cli/probe/impl/JmxDataProbe.java
@@ -26,6 +26,7 @@ import java.util.Map;
 
 import javax.management.MalformedObjectNameException;
 
+import org.apache.james.core.Domain;
 import org.apache.james.domainlist.api.DomainListManagementMBean;
 import org.apache.james.probe.DataProbe;
 import org.apache.james.rrt.api.RecipientRewriteTableManagementMBean;
@@ -246,8 +247,8 @@ public class JmxDataProbe implements DataProbe, JmxProbe {
                     .addContext(MDCBuilder.ACTION, "addForwardMapping")
                     .build()) {
            virtualUserTableProxy.addForwardMapping(user, domain, address);
-       }
-   }
+        }
+    }
 
     @Override
     public void removeForwardMapping(String user, String domain, String address) throws Exception {
@@ -257,6 +258,28 @@ public class JmxDataProbe implements DataProbe, JmxProbe {
                     .addContext(MDCBuilder.ACTION, "removeForwardMapping")
                     .build()) {
            virtualUserTableProxy.removeForwardMapping(user, domain, address);
-       }
-   }
+        }
+    }
+
+    @Override
+    public void addGroupMapping(String toUser, String toDomain, String fromAddress) throws Exception {
+        try (Closeable closeable =
+                 MDCBuilder.create()
+                     .addContext(MDCBuilder.PROTOCOL, JMX)
+                     .addContext(MDCBuilder.ACTION, "removeForwardMapping")
+                     .build()) {
+            virtualUserTableProxy.addGroupMapping(toUser, toDomain, fromAddress);
+        }
+    }
+
+    @Override
+    public void removeGroupMapping(String toUser, String toDomain, String fromAddress) throws Exception {
+        try (Closeable closeable =
+                 MDCBuilder.create()
+                     .addContext(MDCBuilder.PROTOCOL, JMX)
+                     .addContext(MDCBuilder.ACTION, "removeForwardMapping")
+                     .build()) {
+            virtualUserTableProxy.removeGroupMapping(toUser, toDomain, fromAddress);
+        }
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/6368cb06/server/container/guice/guice-common/src/main/java/org/apache/james/utils/DataProbeImpl.java
----------------------------------------------------------------------
diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/DataProbeImpl.java b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/DataProbeImpl.java
index 1e70007..592f3a8 100644
--- a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/DataProbeImpl.java
+++ b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/DataProbeImpl.java
@@ -143,4 +143,14 @@ public class DataProbeImpl implements GuiceProbe, DataProbe {
     public void removeForwardMapping(String user, String domain, String address) throws Exception {
         recipientRewriteTable.removeForwardMapping(user, Domain.of(domain), address);
     }
+
+    @Override
+    public void addGroupMapping(String toUser, String toDomain, String fromAddress) throws Exception {
+        recipientRewriteTable.addGroupMapping(toUser, Domain.of(toDomain), fromAddress);
+    }
+
+    @Override
+    public void removeGroupMapping(String toUser, String toDomain, String fromAddress) throws Exception {
+        recipientRewriteTable.removeGroupMapping(toUser, Domain.of(toDomain), fromAddress);
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/6368cb06/server/data/data-api/src/main/java/org/apache/james/probe/DataProbe.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/probe/DataProbe.java b/server/data/data-api/src/main/java/org/apache/james/probe/DataProbe.java
index 2dc6f8c..c545d27 100644
--- a/server/data/data-api/src/main/java/org/apache/james/probe/DataProbe.java
+++ b/server/data/data-api/src/main/java/org/apache/james/probe/DataProbe.java
@@ -61,4 +61,8 @@ public interface DataProbe {
     void addForwardMapping(String toUser, String toDomain, String fromAddress) throws Exception;
 
     void removeForwardMapping(String toUser, String toDomain, String fromAddress) throws Exception;
+
+    void addGroupMapping(String toUser, String toDomain, String fromAddress) throws Exception;
+
+    void removeGroupMapping(String toUser, String toDomain, String fromAddress) throws Exception;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/6368cb06/server/data/data-api/src/main/java/org/apache/james/rrt/api/RecipientRewriteTableManagementMBean.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/api/RecipientRewriteTableManagementMBean.java b/server/data/data-api/src/main/java/org/apache/james/rrt/api/RecipientRewriteTableManagementMBean.java
index dec0e4d..75e4dee 100644
--- a/server/data/data-api/src/main/java/org/apache/james/rrt/api/RecipientRewriteTableManagementMBean.java
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/api/RecipientRewriteTableManagementMBean.java
@@ -211,4 +211,28 @@ public interface RecipientRewriteTableManagementMBean {
      * @throws Exception If an error occurred
      */
     void removeForwardMapping(String toUser, String toDomain, String fromAddress) throws Exception;
+
+    /***
+     * Add group mapping
+     *
+     * @param toUser
+     *            the username part of the mail address destination defined for this group.
+     * @param toDomain
+     *            the domain part of the mail address destination defined for this group.
+     * @param fromAddress The base address of the group. Mails for this address will be sent to the added group destination.
+     * @throws Exception If an error occurred
+     */
+    void addGroupMapping(String user, String domain, String address) throws Exception;
+
+    /**
+     * Remove group mapping
+     *
+     * @param toUser
+     *            the username part of the mail address destination defined for this group.
+     * @param toDomain
+     *            the domain part of the mail address destination defined for this group.
+     * @param fromAddress The base address of the forward. Mails for this address will no more sent to the removed group destination.
+     * @throws Exception If an error occurred
+     */
+    void removeGroupMapping(String toUser, String toDomain, String fromAddress) throws Exception;
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/6368cb06/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableManagement.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableManagement.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableManagement.java
index 13c5108..3da96e3 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableManagement.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableManagement.java
@@ -114,4 +114,21 @@ public class RecipientRewriteTableManagement extends StandardMBean implements Re
         rrt.removeForwardMapping(user, Domain.of(domain), address);
     }
 
+    @Override
+    public void addGroupMapping(String toUser, String toDomain, String fromAddress) {
+        try {
+            rrt.addGroupMapping(toUser, Domain.of(toDomain), fromAddress);
+        } catch (RecipientRewriteTableException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public void removeGroupMapping(String toUser, String toDomain, String fromAddress) {
+        try {
+            rrt.removeForwardMapping(toUser, Domain.of(toDomain), fromAddress);
+        } catch (RecipientRewriteTableException e) {
+            throw new RuntimeException(e);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/6368cb06/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/WebAdminServerIntegrationTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/WebAdminServerIntegrationTest.java b/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/WebAdminServerIntegrationTest.java
index d882331..18181b3 100644
--- a/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/WebAdminServerIntegrationTest.java
+++ b/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/WebAdminServerIntegrationTest.java
@@ -281,8 +281,8 @@ public class WebAdminServerIntegrationTest {
 
     @Test
     public void addressGroupsEndpointShouldHandleRequests() throws Exception {
-        dataProbe.addAddressMapping("group", "domain.com", "user1@domain.com");
-        dataProbe.addAddressMapping("group", "domain.com", "user2@domain.com");
+        dataProbe.addGroupMapping("group", "domain.com", "user1@domain.com");
+        dataProbe.addGroupMapping("group", "domain.com", "user2@domain.com");
 
         List<String> members = when()
             .get("/address/groups/group@domain.com")

http://git-wip-us.apache.org/repos/asf/james-project/blob/6368cb06/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 29ec2f8..1f5cd39 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
@@ -127,7 +127,7 @@ public class GroupsRoutes implements Routes {
         return Optional.ofNullable(recipientRewriteTable.getAllMappings())
             .map(mappings ->
                 mappings.entrySet().stream()
-                    .filter(e -> e.getValue().contains(Mapping.Type.Address))
+                    .filter(e -> e.getValue().contains(Mapping.Type.Group))
                     .map(Map.Entry::getKey)
                     .collect(Guavate.toImmutableSortedSet()))
             .orElse(ImmutableSortedSet.of());
@@ -159,7 +159,7 @@ public class GroupsRoutes implements Routes {
         ensureRegisteredDomain(domain);
         ensureNotShadowingAnotherAddress(groupAddress);
         MailAddress userAddress = parseMailAddress(request.params(USER_ADDRESS));
-        recipientRewriteTable.addAddressMapping(groupAddress.getLocalPart(), domain, userAddress.asString());
+        recipientRewriteTable.addGroupMapping(groupAddress.getLocalPart(), domain, userAddress.asString());
         return halt(HttpStatus.CREATED_201);
     }
 
@@ -201,7 +201,7 @@ public class GroupsRoutes implements Routes {
     public HaltException removeFromGroup(Request request, Response response) throws JsonExtractException, AddressException, RecipientRewriteTableException {
         MailAddress groupAddress = parseMailAddress(request.params(GROUP_ADDRESS));
         MailAddress userAddress = parseMailAddress(request.params(USER_ADDRESS));
-        recipientRewriteTable.removeAddressMapping(
+        recipientRewriteTable.removeGroupMapping(
             groupAddress.getLocalPart(),
             groupAddress.getDomain(),
             userAddress.asString());
@@ -227,7 +227,7 @@ public class GroupsRoutes implements Routes {
 
         ensureNonEmptyMappings(mappings);
 
-        return mappings.select(Mapping.Type.Address)
+        return mappings.select(Mapping.Type.Group)
                 .asStream()
                 .map(Mapping::asMailAddress)
                 .flatMap(OptionalUtils::toStream)

http://git-wip-us.apache.org/repos/asf/james-project/blob/6368cb06/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 e412b44..1dd9c6c 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
@@ -527,7 +527,7 @@ class GroupsRoutesTest {
         void putShouldReturnErrorWhenRecipientRewriteTableExceptionIsThrown() throws Exception {
             doThrow(RecipientRewriteTableException.class)
                 .when(memoryRecipientRewriteTable)
-                .addAddressMapping(anyString(), any(), anyString());
+                .addGroupMapping(anyString(), any(), anyString());
 
             when()
                 .put(GROUP1 + SEPARATOR + GROUP2)
@@ -540,7 +540,7 @@ class GroupsRoutesTest {
         void putShouldReturnErrorWhenErrorMappingExceptionIsThrown() throws Exception {
             doThrow(RecipientRewriteTable.ErrorMappingException.class)
                 .when(memoryRecipientRewriteTable)
-                .addAddressMapping(anyString(), any(), anyString());
+                .addGroupMapping(anyString(), any(), anyString());
 
             when()
                 .put(GROUP1 + SEPARATOR + GROUP2)
@@ -553,7 +553,7 @@ class GroupsRoutesTest {
         void putShouldReturnErrorWhenRuntimeExceptionIsThrown() throws Exception {
             doThrow(RuntimeException.class)
                 .when(memoryRecipientRewriteTable)
-                .addAddressMapping(anyString(), any(), anyString());
+                .addGroupMapping(anyString(), any(), anyString());
 
             when()
                 .put(GROUP1 + SEPARATOR + GROUP2)
@@ -605,7 +605,7 @@ class GroupsRoutesTest {
         void deleteShouldReturnErrorWhenRecipientRewriteTableExceptionIsThrown() throws Exception {
             doThrow(RecipientRewriteTableException.class)
                 .when(memoryRecipientRewriteTable)
-                .removeAddressMapping(anyString(), any(), anyString());
+                .removeGroupMapping(anyString(), any(), anyString());
 
             when()
                 .delete(GROUP1 + SEPARATOR + GROUP2)
@@ -618,7 +618,7 @@ class GroupsRoutesTest {
         void deleteShouldReturnErrorWhenErrorMappingExceptionIsThrown() throws Exception {
             doThrow(RecipientRewriteTable.ErrorMappingException.class)
                 .when(memoryRecipientRewriteTable)
-                .removeAddressMapping(anyString(), any(), anyString());
+                .removeGroupMapping(anyString(), any(), anyString());
 
             when()
                 .delete(GROUP1 + SEPARATOR + GROUP2)
@@ -631,7 +631,7 @@ class GroupsRoutesTest {
         void deleteShouldReturnErrorWhenRuntimeExceptionIsThrown() throws Exception {
             doThrow(RuntimeException.class)
                 .when(memoryRecipientRewriteTable)
-                .removeAddressMapping(anyString(), any(), anyString());
+                .removeGroupMapping(anyString(), any(), anyString());
 
             when()
                 .delete(GROUP1 + SEPARATOR + GROUP2)


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


[05/27] james-project git commit: JAMES-2366 Adding a group mapping type

Posted by ma...@apache.org.
JAMES-2366 Adding a group mapping type


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

Branch: refs/heads/master
Commit: 43a6882f0cbc2a40a5e366b57cc25bee844124e8
Parents: ff231f9
Author: benwa <bt...@linagora.com>
Authored: Fri Apr 6 09:29:35 2018 +0700
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:45:26 2018 +0200

----------------------------------------------------------------------
 .../java/org/apache/james/rrt/lib/Mapping.java  | 15 ++++++++++-----
 .../rrt/lib/AbstractRecipientRewriteTable.java  | 20 +++++++++++++++++---
 .../org/apache/james/rrt/lib/MappingImpl.java   |  7 +++++--
 .../apache/james/rrt/lib/MappingImplTest.java   | 12 +++++++++++-
 .../apache/james/rrt/lib/MappingsImplTest.java  | 15 +++++++++++++++
 5 files changed, 58 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/43a6882f/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
index 1c7d3a6..39be80d 100644
--- a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
@@ -44,17 +44,21 @@ public interface Mapping {
         if (input.startsWith(Type.Forward.asPrefix())) {
             return Type.Forward;
         }
+        if (input.startsWith(Type.Group.asPrefix())) {
+            return Type.Group;
+        }
         return Type.Address;
     }
 
     Optional<MailAddress> asMailAddress();
 
     enum Type {
-        Regex("regex:", 3),
+        Regex("regex:", 4),
         Domain("domain:", 1),
-        Error("error:", 3),
-        Forward("forward:", 2),
-        Address("", 3);
+        Error("error:", 4),
+        Forward("forward:", 3),
+        Group("group:", 2),
+        Address("", 4);
 
         private final String asPrefix;
         private final int order;
@@ -77,7 +81,8 @@ public interface Mapping {
             return mapping.startsWith(Regex.asPrefix())
                 || mapping.startsWith(Domain.asPrefix())
                 || mapping.startsWith(Error.asPrefix())
-                || mapping.startsWith(Forward.asPrefix());
+                || mapping.startsWith(Forward.asPrefix())
+                || mapping.startsWith(Group.asPrefix());
         }
 
         public int getOrder() {

http://git-wip-us.apache.org/repos/asf/james-project/blob/43a6882f/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
index cc64297..2586f37 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
@@ -149,13 +149,13 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
 
                         if (childMappings.isEmpty()) {
                             // add mapping
-                            mappings.add(addressWithMappingApplied);
+                            mappings.add(toMapping(addressWithMappingApplied, type));
                         } else {
                             mappings = mappings.addAll(childMappings);
                         }
 
                     } else {
-                        mappings.add(addressWithMappingApplied);
+                        mappings.add(toMapping(addressWithMappingApplied, type));
                     }
                 }
                 return mappings.build();
@@ -165,6 +165,20 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
         return MappingsImpl.empty();
     }
 
+    private Mapping toMapping(String mappedAddress, Type type) {
+        switch (type) {
+            case Forward:
+            case Group:
+                return MappingImpl.of(type, mappedAddress);
+            case Regex:
+            case Domain:
+            case Error:
+            case Address:
+                return MappingImpl.address(mappedAddress);
+        }
+        throw new IllegalArgumentException("unhandled enum type");
+    }
+
     private Optional<String> applyMapping(String user, Domain domain, String target, Type type) {
         switch (type) {
             case Regex:
@@ -177,7 +191,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
             case Domain:
                 return Optional.of(user + "@" + Type.Domain.withoutPrefix(target));
             default:
-                return Optional.ofNullable(target);
+                return Optional.of(type.withoutPrefix(target));
         }
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/43a6882f/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingImpl.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingImpl.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingImpl.java
index 04ca426..c16d60c 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingImpl.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingImpl.java
@@ -33,7 +33,6 @@ import org.apache.james.rrt.api.RecipientRewriteTableException;
 import com.google.common.base.Objects;
 import com.google.common.base.Preconditions;
 
-
 public class MappingImpl implements Mapping, Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -66,6 +65,10 @@ public class MappingImpl implements Mapping, Serializable {
     public static MappingImpl forward(String mapping) {
         return new MappingImpl(Type.Forward, mapping);
     }
+
+    public static MappingImpl group(String mapping) {
+        return new MappingImpl(Type.Group, mapping);
+    }
     
     private final Type type;
     private final String mapping;
@@ -122,7 +125,7 @@ public class MappingImpl implements Mapping, Serializable {
 
     @Override
     public Optional<MailAddress> asMailAddress() {
-        if (type != Type.Address && type != Type.Forward) {
+        if (type != Type.Address && type != Type.Forward && type != Type.Group) {
             return Optional.empty();
         }
         try {

http://git-wip-us.apache.org/repos/asf/james-project/blob/43a6882f/server/data/data-library/src/test/java/org/apache/james/rrt/lib/MappingImplTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/test/java/org/apache/james/rrt/lib/MappingImplTest.java b/server/data/data-library/src/test/java/org/apache/james/rrt/lib/MappingImplTest.java
index 72c6439..8b16443 100644
--- a/server/data/data-library/src/test/java/org/apache/james/rrt/lib/MappingImplTest.java
+++ b/server/data/data-library/src/test/java/org/apache/james/rrt/lib/MappingImplTest.java
@@ -67,6 +67,12 @@ public class MappingImplTest {
         assertThatThrownBy(() -> MappingImpl.forward(null))
             .isInstanceOf(NullPointerException.class);
     }
+
+    @Test
+    public void groupFactoryMethodShouldThrowOnNull() {
+        assertThatThrownBy(() -> MappingImpl.group(null))
+            .isInstanceOf(NullPointerException.class);
+    }
     
     @Test
     public void hasDomainShouldReturnTrueWhenMappingContainAtMark() {
@@ -159,6 +165,11 @@ public class MappingImplTest {
     public void getTypeShouldReturnForwardWhenForwardPrefix() {
         assertThat(MappingImpl.forward("abc").getType()).isEqualTo(Mapping.Type.Forward);
     }
+
+    @Test
+    public void getTypeShouldReturnGroupWhenGroupPrefix() {
+        assertThat(MappingImpl.group("abc").getType()).isEqualTo(Mapping.Type.Group);
+    }
     
     @Test(expected = IllegalStateException.class)
     public void getErrorMessageShouldThrowWhenMappingIsNotAnError() {
@@ -169,7 +180,6 @@ public class MappingImplTest {
     public void getErrorMessageShouldReturnMessageWhenErrorWithMessage() {
         assertThat(MappingImpl.error("toto").getErrorMessage()).isEqualTo("toto");
     }
-    
 
     @Test
     public void getErrorMessageShouldReturnWhenErrorWithoutMessage() {

http://git-wip-us.apache.org/repos/asf/james-project/blob/43a6882f/server/data/data-library/src/test/java/org/apache/james/rrt/lib/MappingsImplTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/test/java/org/apache/james/rrt/lib/MappingsImplTest.java b/server/data/data-library/src/test/java/org/apache/james/rrt/lib/MappingsImplTest.java
index 1f8dcd9..213c3d1 100644
--- a/server/data/data-library/src/test/java/org/apache/james/rrt/lib/MappingsImplTest.java
+++ b/server/data/data-library/src/test/java/org/apache/james/rrt/lib/MappingsImplTest.java
@@ -339,4 +339,19 @@ public class MappingsImplTest {
                 .build();
         assertThat(mappingsImpl).containsExactly(domainMapping, forwardMapping, regexMapping);
     }
+
+    @Test
+    public void builderShouldPutGroupsBetweenDomainAndForward() {
+        MappingImpl regexMapping = MappingImpl.regex("regex");
+        MappingImpl forwardMapping = MappingImpl.forward("forward");
+        MappingImpl domainMapping = MappingImpl.domain(Domain.of("domain"));
+        MappingImpl groupMapping = MappingImpl.group("group");
+        MappingsImpl mappingsImpl = MappingsImpl.builder()
+                .add(regexMapping)
+                .add(forwardMapping)
+                .add(domainMapping)
+                .add(groupMapping)
+                .build();
+        assertThat(mappingsImpl).containsExactly(domainMapping, groupMapping, forwardMapping, regexMapping);
+    }
 }


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


[11/27] james-project git commit: JAMES-2366 adopt fail-fast coding style

Posted by ma...@apache.org.
JAMES-2366 adopt fail-fast coding style


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

Branch: refs/heads/master
Commit: 930e7e52f7f7b5138123009456d5e61afec96788
Parents: 949594c
Author: Matthieu Baechler <ma...@apache.org>
Authored: Tue Apr 17 15:02:05 2018 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:45:26 2018 +0200

----------------------------------------------------------------------
 .../rrt/lib/AbstractRecipientRewriteTable.java  | 82 ++++++++++----------
 1 file changed, 41 insertions(+), 41 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/930e7e52/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
index 7249250..001b554 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
@@ -109,59 +109,59 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
 
         if (targetMappings.contains(Type.Error)) {
             throw new ErrorMappingException(targetMappings.getError().getErrorMessage());
-        } else {
-            MappingsImpl.Builder mappings = MappingsImpl.builder();
+        }
 
-            for (String target : targetMappings.asStrings()) {
-                Type type = Mapping.detectType(target);
-                Optional<String> maybeAddressWithMappingApplied = applyMapping(user, domain, target, type);
+        MappingsImpl.Builder mappings = MappingsImpl.builder();
 
-                if (!maybeAddressWithMappingApplied.isPresent()) {
-                    continue;
-                }
-                String addressWithMappingApplied = maybeAddressWithMappingApplied.get();
-                LOGGER.debug("Valid virtual user mapping {}@{} to {}", user, domain.name(), addressWithMappingApplied);
-
-                if (recursive) {
-
-                    String userName;
-                    Domain targetDomain;
-                    String[] args = addressWithMappingApplied.split("@");
-
-                    if (args.length > 1) {
-                        userName = args[0];
-                        targetDomain = Domain.of(args[1]);
-                    } else {
-                        // TODO Is that the right todo here?
-                        userName = addressWithMappingApplied;
-                        targetDomain = domain;
-                    }
+        for (String target : targetMappings.asStrings()) {
+            Type type = Mapping.detectType(target);
+            Optional<String> maybeAddressWithMappingApplied = applyMapping(user, domain, target, type);
 
-                    // Check if the returned mapping is the same as the
-                    // input. If so return null to avoid loops
-                    if (userName.equalsIgnoreCase(user) && targetDomain.equals(domain)) {
-                        if (type.equals(Type.Forward)) {
-                            mappings.add(toMapping(addressWithMappingApplied, type));
-                            continue;
-                        }
-                        return MappingsImpl.empty();
-                    }
+            if (!maybeAddressWithMappingApplied.isPresent()) {
+                continue;
+            }
+            String addressWithMappingApplied = maybeAddressWithMappingApplied.get();
+            LOGGER.debug("Valid virtual user mapping {}@{} to {}", user, domain.name(), addressWithMappingApplied);
+
+            if (recursive) {
+
+                String userName;
+                Domain targetDomain;
+                String[] args = addressWithMappingApplied.split("@");
 
-                    Mappings childMappings = getMappings(userName, targetDomain, mappingLimit - 1);
+                if (args.length > 1) {
+                    userName = args[0];
+                    targetDomain = Domain.of(args[1]);
+                } else {
+                    // TODO Is that the right todo here?
+                    userName = addressWithMappingApplied;
+                    targetDomain = domain;
+                }
 
-                    if (childMappings.isEmpty()) {
-                        // add mapping
+                // Check if the returned mapping is the same as the
+                // input. If so return null to avoid loops
+                if (userName.equalsIgnoreCase(user) && targetDomain.equals(domain)) {
+                    if (type.equals(Type.Forward)) {
                         mappings.add(toMapping(addressWithMappingApplied, type));
-                    } else {
-                        mappings = mappings.addAll(childMappings);
+                        continue;
                     }
+                    return MappingsImpl.empty();
+                }
 
-                } else {
+                Mappings childMappings = getMappings(userName, targetDomain, mappingLimit - 1);
+
+                if (childMappings.isEmpty()) {
+                    // add mapping
                     mappings.add(toMapping(addressWithMappingApplied, type));
+                } else {
+                    mappings = mappings.addAll(childMappings);
                 }
+
+            } else {
+                mappings.add(toMapping(addressWithMappingApplied, type));
             }
-            return mappings.build();
         }
+        return mappings.build();
     }
 
     private Mapping toMapping(String mappedAddress, Type type) {


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


[25/27] james-project git commit: JAMES-2366 use an object MappingSource for input of RRT rewriting

Posted by ma...@apache.org.
JAMES-2366 use an object MappingSource for input of RRT rewriting


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

Branch: refs/heads/master
Commit: ff8107efb52239bf1fc3eddb906ba4889eb2d95b
Parents: bfec1af
Author: Matthieu Baechler <ma...@apache.org>
Authored: Wed Apr 18 17:09:34 2018 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:49:33 2018 +0200

----------------------------------------------------------------------
 .../james/cli/DataCommandsIntegrationTest.java  |  27 ++-
 .../james/cli/probe/impl/JmxDataProbe.java      |   1 -
 .../org/apache/james/utils/DataProbeImpl.java   |  36 ++--
 server/data/data-api/pom.xml                    |   4 +
 .../james/rrt/api/RecipientRewriteTable.java    | 172 ++++---------------
 .../java/org/apache/james/rrt/lib/Mapping.java  |   3 +-
 .../org/apache/james/rrt/lib/MappingSource.java | 144 ++++++++++++++++
 .../org/apache/james/rrt/lib/UserRewritter.java |   3 +-
 .../CassandraRecipientRewriteTable.java         |  51 +++---
 .../rrt/file/XMLRecipientRewriteTable.java      |  19 +-
 .../rrt/file/XMLRecipientRewriteTableTest.java  |  37 ++--
 .../rrt/hbase/HBaseRecipientRewriteTable.java   |  61 ++++---
 .../rrt/jdbc/JDBCRecipientRewriteTable.java     |  51 +++---
 .../james/rrt/jpa/JPARecipientRewriteTable.java |  49 +++---
 .../rrt/lib/AbstractRecipientRewriteTable.java  | 116 +++++--------
 .../lib/RecipientRewriteTableManagement.java    |  67 +++++---
 .../rrt/lib/RecipientRewriteTableUtil.java      |  37 +---
 .../user/lib/AbstractJamesUsersRepository.java  |  38 ++--
 .../lib/AbstractRecipientRewriteTableTest.java  | 113 ++++++------
 .../james/rrt/lib/RewriteTablesStepdefs.java    |  37 ++--
 .../rrt/memory/MemoryRecipientRewriteTable.java |  51 +++---
 .../mailets/XMLRecipientRewriteTable.java       |   5 +-
 .../james/smtpserver/ValidRcptHandlerTest.java  |   5 +-
 .../james/webadmin/routes/ForwardRoutes.java    |  14 +-
 .../james/webadmin/routes/GroupsRoutes.java     |  16 +-
 .../webadmin/routes/ForwardRoutesTest.java      |  19 +-
 .../james/webadmin/routes/GroupsRoutesTest.java |  19 +-
 27 files changed, 614 insertions(+), 581 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/server/container/cli-integration/src/test/java/org/apache/james/cli/DataCommandsIntegrationTest.java
----------------------------------------------------------------------
diff --git a/server/container/cli-integration/src/test/java/org/apache/james/cli/DataCommandsIntegrationTest.java b/server/container/cli-integration/src/test/java/org/apache/james/cli/DataCommandsIntegrationTest.java
index b6579d5..ed5a446 100644
--- a/server/container/cli-integration/src/test/java/org/apache/james/cli/DataCommandsIntegrationTest.java
+++ b/server/container/cli-integration/src/test/java/org/apache/james/cli/DataCommandsIntegrationTest.java
@@ -22,15 +22,12 @@ package org.apache.james.cli;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
 
-import java.util.AbstractMap;
-
 import org.apache.james.GuiceJamesServer;
 import org.apache.james.MemoryJmapTestRule;
 import org.apache.james.cli.util.OutputCapture;
 import org.apache.james.mailbox.store.search.ListeningMessageSearchIndex;
 import org.apache.james.modules.server.JMXServerModule;
 import org.apache.james.rrt.lib.Mapping;
-import org.apache.james.rrt.lib.Mappings;
 import org.apache.james.rrt.lib.MappingsImpl;
 import org.apache.james.utils.DataProbeImpl;
 import org.junit.After;
@@ -137,12 +134,12 @@ public class DataCommandsIntegrationTest {
         ServerCmd.doMain(new String[] {"-h", "127.0.0.1", "-p", "9999", "addaddressmapping", USER, DOMAIN, redirectionAddress});
 
         assertThat(dataProbe.listMappings())
-            .containsOnly(
-                new AbstractMap.SimpleEntry<String, Mappings>(
-                    MAIL_ADDRESS,
-                    MappingsImpl.builder()
-                        .add(Mapping.address(redirectionAddress))
-                        .build()));
+            .hasSize(1)
+            .containsEntry(
+                MAIL_ADDRESS,
+                MappingsImpl.builder()
+                    .add(Mapping.address(redirectionAddress))
+                    .build());
     }
 
     @Test
@@ -186,12 +183,12 @@ public class DataCommandsIntegrationTest {
         ServerCmd.doMain(new String[] {"-h", "127.0.0.1", "-p", "9999", "addregexmapping", USER, DOMAIN, regex});
 
         assertThat(dataProbe.listMappings())
-            .containsOnly(
-                new AbstractMap.SimpleEntry<String, Mappings>(
-                    MAIL_ADDRESS,
-                    MappingsImpl.builder()
-                        .add(Mapping.regex(regex))
-                        .build()));
+            .hasSize(1)
+            .containsEntry(
+                MAIL_ADDRESS,
+                MappingsImpl.builder()
+                    .add(Mapping.regex(regex))
+                    .build());
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/server/container/cli/src/main/java/org/apache/james/cli/probe/impl/JmxDataProbe.java
----------------------------------------------------------------------
diff --git a/server/container/cli/src/main/java/org/apache/james/cli/probe/impl/JmxDataProbe.java b/server/container/cli/src/main/java/org/apache/james/cli/probe/impl/JmxDataProbe.java
index 9cc3b60..dde2d88 100644
--- a/server/container/cli/src/main/java/org/apache/james/cli/probe/impl/JmxDataProbe.java
+++ b/server/container/cli/src/main/java/org/apache/james/cli/probe/impl/JmxDataProbe.java
@@ -26,7 +26,6 @@ import java.util.Map;
 
 import javax.management.MalformedObjectNameException;
 
-import org.apache.james.core.Domain;
 import org.apache.james.domainlist.api.DomainListManagementMBean;
 import org.apache.james.probe.DataProbe;
 import org.apache.james.rrt.api.RecipientRewriteTableManagementMBean;

http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/server/container/guice/guice-common/src/main/java/org/apache/james/utils/DataProbeImpl.java
----------------------------------------------------------------------
diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/DataProbeImpl.java b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/DataProbeImpl.java
index 592f3a8..38bc8ed 100644
--- a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/DataProbeImpl.java
+++ b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/DataProbeImpl.java
@@ -29,6 +29,7 @@ import org.apache.james.core.Domain;
 import org.apache.james.domainlist.api.DomainList;
 import org.apache.james.probe.DataProbe;
 import org.apache.james.rrt.api.RecipientRewriteTable;
+import org.apache.james.rrt.lib.MappingSource;
 import org.apache.james.rrt.lib.Mappings;
 import org.apache.james.user.api.UsersRepository;
 
@@ -100,7 +101,14 @@ public class DataProbeImpl implements GuiceProbe, DataProbe {
 
     @Override
     public Map<String, Mappings> listMappings() throws Exception {
-        return recipientRewriteTable.getAllMappings();
+        return recipientRewriteTable.getAllMappings()
+            .entrySet()
+            .stream()
+            .collect(
+                Guavate.toImmutableMap(
+                    entry -> entry.getKey().asString(),
+                    entry -> entry.getValue()));
+
     }
 
     @Override
@@ -110,47 +118,55 @@ public class DataProbeImpl implements GuiceProbe, DataProbe {
 
     @Override
     public void addAddressMapping(String user, String domain, String toAddress) throws Exception {
-        recipientRewriteTable.addAddressMapping(user, Domain.of(domain), toAddress);
+        MappingSource source = MappingSource.fromUser(user, domain);
+        recipientRewriteTable.addAddressMapping(source, toAddress);
     }
 
     @Override
     public void removeAddressMapping(String user, String domain, String fromAddress) throws Exception {
-        recipientRewriteTable.removeAddressMapping(user, Domain.of(domain), fromAddress);
+        MappingSource source = MappingSource.fromUser(user, domain);
+        recipientRewriteTable.removeAddressMapping(source, fromAddress);
     }
 
     @Override
     public void addRegexMapping(String user, String domain, String regex) throws Exception {
-        recipientRewriteTable.addRegexMapping(user, Domain.of(domain), regex);
+        MappingSource source = MappingSource.fromUser(user, domain);
+        recipientRewriteTable.addRegexMapping(source, regex);
     }
 
 
     @Override
     public void removeRegexMapping(String user, String domain, String regex) throws Exception {
-        recipientRewriteTable.removeRegexMapping(user, Domain.of(domain), regex);
+        MappingSource source = MappingSource.fromUser(user, domain);
+        recipientRewriteTable.removeRegexMapping(source, regex);
     }
 
     @Override
     public void addDomainAliasMapping(String aliasDomain, String deliveryDomain) throws Exception {
-        recipientRewriteTable.addAliasDomainMapping(Domain.of(aliasDomain), Domain.of(deliveryDomain));
+        recipientRewriteTable.addAliasDomainMapping(MappingSource.fromDomain(Domain.of(aliasDomain)), Domain.of(deliveryDomain));
     }
 
     @Override
     public void addForwardMapping(String user, String domain, String address) throws Exception {
-        recipientRewriteTable.addForwardMapping(user, Domain.of(domain), address);
+        MappingSource source = MappingSource.fromUser(user, domain);
+        recipientRewriteTable.addForwardMapping(source, address);
     }
 
     @Override
     public void removeForwardMapping(String user, String domain, String address) throws Exception {
-        recipientRewriteTable.removeForwardMapping(user, Domain.of(domain), address);
+        MappingSource source = MappingSource.fromUser(user, domain);
+        recipientRewriteTable.removeForwardMapping(source, address);
     }
 
     @Override
     public void addGroupMapping(String toUser, String toDomain, String fromAddress) throws Exception {
-        recipientRewriteTable.addGroupMapping(toUser, Domain.of(toDomain), fromAddress);
+        MappingSource source = MappingSource.fromUser(toUser, toDomain);
+        recipientRewriteTable.addGroupMapping(source, fromAddress);
     }
 
     @Override
     public void removeGroupMapping(String toUser, String toDomain, String fromAddress) throws Exception {
-        recipientRewriteTable.removeGroupMapping(toUser, Domain.of(toDomain), fromAddress);
+        MappingSource source = MappingSource.fromUser(toUser, toDomain);
+        recipientRewriteTable.removeGroupMapping(source, fromAddress);
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/server/data/data-api/pom.xml
----------------------------------------------------------------------
diff --git a/server/data/data-api/pom.xml b/server/data/data-api/pom.xml
index f04f3a7..35a2572 100644
--- a/server/data/data-api/pom.xml
+++ b/server/data/data-api/pom.xml
@@ -34,6 +34,10 @@
 
     <dependencies>
         <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>james-core</artifactId>
+        </dependency>
+        <dependency>
             <!-- only used by JamesUser (for MailAddress) -->
             <groupId>${project.groupId}</groupId>
             <artifactId>apache-mailet-api</artifactId>

http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/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 e2e7315..52ac402 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,6 +22,7 @@ import java.util.Map;
 
 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;
 
 /**
@@ -50,132 +51,51 @@ public interface RecipientRewriteTable {
      */
     String WILDCARD = "*";
 
-    /**
-     * Return the mapped MailAddress for the given address. Return null if no
-     * matched mapping was found
-     * 
-     * @param user
-     *            the MailAddress
-     * @return the mapped mailAddress
-     * @throws ErrorMappingException
-     *             get thrown if an error mapping was found
-     * @throws RecipientRewriteTableException
-     */
-    Mappings getMappings(String user, Domain domain) throws ErrorMappingException, RecipientRewriteTableException;
+    void addMapping(MappingSource source, Mapping mapping) throws RecipientRewriteTableException;
 
-    /**
-     * Add regex mapping
-     * 
-     * @param user
-     *            the username. Null if no username should be used
-     * @param domain
-     *            the domain. Null if no domain should be used
-     * @param regex
-     *            the regex.
-     * @throws RecipientRewriteTableException
-     */
-    void addRegexMapping(String user, Domain domain, String regex) throws RecipientRewriteTableException;
+    void removeMapping(MappingSource source, Mapping mapping) throws RecipientRewriteTableException;
 
-    /**
-     * Remove regex mapping
-     * 
-     * @param user
-     *            the username. Null if no username should be used
-     * @param domain
-     *            the domain. Null if no domain should be used
-     * @param regex
-     *            the regex.
-     * @throws RecipientRewriteTableException
-     */
-    void removeRegexMapping(String user, Domain domain, String regex) throws RecipientRewriteTableException;
+    void addRegexMapping(MappingSource source, String regex) throws RecipientRewriteTableException;
 
-    /***
-     * Add address mapping
-     * 
-     * @param user
-     *            the username. Null if no username should be used
-     * @param domain
-     *            the domain. Null if no domain should be used
-     * @param address
-     * @throws RecipientRewriteTableException
-     */
-    void addAddressMapping(String user, Domain domain, String address) throws RecipientRewriteTableException;
+    void removeRegexMapping(MappingSource source, String regex) throws RecipientRewriteTableException;
 
-    /**
-     * Remove address mapping
-     * 
-     * @param user
-     *            the username. Null if no username should be used
-     * @param domain
-     *            the domain. Null if no domain should be used
-     * @param address
-     * @throws RecipientRewriteTableException
-     */
-    void removeAddressMapping(String user, Domain domain, String address) throws RecipientRewriteTableException;
+    void addAddressMapping(MappingSource source, String address) throws RecipientRewriteTableException;
 
-    /**
-     * Add error mapping
-     * 
-     * @param user
-     *            the username. Null if no username should be used
-     * @param domain
-     *            the domain. Null if no domain should be used
-     * @param error
-     *            the regex.
-     * @throws RecipientRewriteTableException
-     */
-    void addErrorMapping(String user, Domain domain, String error) throws RecipientRewriteTableException;
+    void removeAddressMapping(MappingSource source, String address) throws RecipientRewriteTableException;
+
+    void addErrorMapping(MappingSource source, String error) throws RecipientRewriteTableException;
+
+    void removeErrorMapping(MappingSource source, String error) throws RecipientRewriteTableException;
+
+    void addAliasDomainMapping(MappingSource source, Domain realDomain) throws RecipientRewriteTableException;
+
+    void removeAliasDomainMapping(MappingSource source, Domain realDomain) throws RecipientRewriteTableException;
+
+    void addForwardMapping(MappingSource source, String address) throws RecipientRewriteTableException;
+
+    void removeForwardMapping(MappingSource source, String address) throws RecipientRewriteTableException;
+
+    void addGroupMapping(MappingSource source, String address) throws RecipientRewriteTableException;
+
+    void removeGroupMapping(MappingSource source, String address) throws RecipientRewriteTableException;
 
     /**
-     * Remove error mapping
-     * 
-     * @param user
-     *            the username. Null if no username should be used
-     * @param domain
-     *            the domain. Null if no domain should be used
-     * @param error
-     * @throws RecipientRewriteTableException
+     * Return the Mappings for the given source. Return null if no
+     * matched mapping was found
+     *
+     * @throws ErrorMappingException
+     *             get thrown if an error mapping was found
      */
-    void removeErrorMapping(String user, Domain domain, String error) throws RecipientRewriteTableException;
+    Mappings getMappings(String user, Domain domain) throws ErrorMappingException, RecipientRewriteTableException;
 
     /**
      * Return the explicit mapping stored for the given user and domain. Return
      * null if no mapping was found
      * 
-     * @param user
-     *            the username
-     * @param domain
-     *            the domain
      * @return the collection which holds the mappings.
      * @throws RecipientRewriteTableException
      */
-    Mappings getUserDomainMappings(String user, Domain domain) throws RecipientRewriteTableException;
-
-    /**
-     * Add mapping
-     * 
-     * @param user
-     *            the username. Null if no username should be used
-     * @param domain
-     *            the domain. Null if no domain should be used
-     * @param mapping
-     *            the mapping
-     * @throws RecipientRewriteTableException
-     */
-    void addMapping(String user, Domain domain, Mapping mapping) throws RecipientRewriteTableException;
-
-    /**
-     * Remove mapping
-     * 
-     * @param user
-     *            the username. Null if no username should be used
-     * @param domain
-     *            the domain. Null if no domain should be used
-     * @param mapping
-     *            the mapping
-     * @throws RecipientRewriteTableException
-     */
-    void removeMapping(String user, Domain domain, Mapping mapping) throws RecipientRewriteTableException;
+    Mappings getUserDomainMappings(MappingSource source) throws RecipientRewriteTableException;
 
     /**
      * Return a Map which holds all mappings. The key is the user@domain and the
@@ -184,37 +104,7 @@ public interface RecipientRewriteTable {
      * @return Map which holds all mappings
      * @throws RecipientRewriteTableException
      */
-    Map<String, Mappings> getAllMappings() throws RecipientRewriteTableException;
-
-    /**
-     * Add aliasDomain mapping
-     * 
-     * @param aliasDomain
-     *            the aliasdomain which should be mapped to the realDomain
-     * @param realDomain
-     *            the realDomain
-     * @throws RecipientRewriteTableException
-     */
-    void addAliasDomainMapping(Domain aliasDomain, Domain realDomain) throws RecipientRewriteTableException;
-
-    /**
-     * Remove aliasDomain mapping
-     * 
-     * @param aliasDomain
-     *            the aliasdomain which should be mapped to the realDomain
-     * @param realDomain
-     *            the realDomain
-     * @throws RecipientRewriteTableException
-     */
-    void removeAliasDomainMapping(Domain aliasDomain, Domain realDomain) throws RecipientRewriteTableException;
-
-    void addForwardMapping(String user, Domain domain, String address) throws RecipientRewriteTableException;
-
-    void removeForwardMapping(String user, Domain domain, String address) throws RecipientRewriteTableException;
-
-    void addGroupMapping(String user, Domain domain, String address) throws RecipientRewriteTableException;
-
-    void removeGroupMapping(String user, Domain domain, String address) throws RecipientRewriteTableException;
+    Map<MappingSource, Mappings> getAllMappings() throws RecipientRewriteTableException;
 
     class ErrorMappingException extends Exception {
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
index 7795014..53bfa67 100644
--- a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
@@ -20,6 +20,7 @@
 
 package org.apache.james.rrt.lib;
 
+import java.io.Serializable;
 import java.util.Optional;
 import java.util.function.Supplier;
 import java.util.stream.Stream;
@@ -211,7 +212,7 @@ public interface Mapping {
 
     Stream<Mapping> handleIdentity(Stream<Mapping> nonRecursiveResult);
 
-    class Impl implements Mapping {
+    class Impl implements Mapping, Serializable {
 
         private final Type type;
         private final String mapping;

http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/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
new file mode 100644
index 0000000..5539089
--- /dev/null
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/MappingSource.java
@@ -0,0 +1,144 @@
+/****************************************************************
+ * 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 java.io.Serializable;
+import java.util.Objects;
+import java.util.Optional;
+
+import javax.mail.internet.AddressException;
+
+import org.apache.james.core.Domain;
+import org.apache.james.core.MailAddress;
+import org.apache.james.core.User;
+import org.apache.james.util.OptionalUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MappingSource implements Serializable {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(MappingSource.class);
+    private static final String WILDCARD = "*";
+
+    private enum WildCard {
+        WildCard
+    }
+
+    public static MappingSource fromDomain(Domain domain) {
+        if (domain.asString().equals(WILDCARD)) {
+            return wildCard();
+        }
+        return new MappingSource(Optional.of(domain), Optional.empty(), Optional.empty());
+    }
+
+    public static MappingSource fromUser(String localPart, String domain) {
+        return fromUser(localPart, Domain.of(domain));
+    }
+
+    public static MappingSource fromUser(String localPart, Domain domain) {
+        User user = User.fromLocalPartWithDomain(localPart, domain);
+        return fromUser(user);
+    }
+
+    public static MappingSource fromUser(User user) {
+        if (user.getLocalPart().equals(WILDCARD)) {
+            return MappingSource.fromDomain(user.getDomainPart().get());
+        }
+        return new MappingSource(Optional.empty(), Optional.of(user), Optional.empty());
+    }
+
+    public static MappingSource wildCard() {
+        return new MappingSource(Optional.empty(), Optional.empty(), Optional.of(WildCard.WildCard));
+    }
+
+    public static MappingSource parse(String mappingSource) {
+        switch (mappingSource) {
+            case WILDCARD:
+                return wildCard();
+            default:
+                if (mappingSource.startsWith(WILDCARD + "@")) {
+                    return fromDomain(Domain.of(mappingSource.substring(2, mappingSource.length())));
+                }
+                return fromUser(User.fromUsername(mappingSource));
+        }
+    }
+
+    private final Optional<Domain> domain;
+    private final Optional<User> user;
+    private final Optional<WildCard> wildcard;
+
+    private MappingSource(Optional<Domain> domain, Optional<User> user, Optional<WildCard> wildcard) {
+        this.domain = domain;
+        this.user = user;
+        this.wildcard = wildcard;
+    }
+
+    public Optional<Domain> asDomain() {
+        return domain;
+    }
+
+    public Optional<MailAddress> asMailAddress() {
+        return user.flatMap(user -> {
+            try {
+                return Optional.of(user.asMailAddress());
+            } catch (AddressException e) {
+                LOGGER.warn("Ignoring failing MappingSource to MailAddress conversion for user {}", user, e);
+                return Optional.empty();
+            }
+        });
+    }
+
+    public String asString() {
+        return OptionalUtils.orSuppliers(
+                () -> wildcard.map(x -> "*"),
+                () -> user.map(User::asString),
+                () -> domain.map(Domain::asString))
+            .orElseThrow(IllegalStateException::new);
+    }
+
+    public String getFixedUser() {
+        return user.map(User::getLocalPart)
+            .orElse(WILDCARD);
+    }
+
+    public String getFixedDomain() {
+        return OptionalUtils.or(
+                user.flatMap(User::getDomainPart).map(Domain::asString),
+                domain.map(Domain::asString))
+            .orElse(WILDCARD);
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof MappingSource) {
+            MappingSource that = (MappingSource) o;
+
+            return Objects.equals(this.domain, that.domain)
+                && Objects.equals(this.user, that.user)
+                && Objects.equals(this.wildcard, that.wildcard);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(domain, user, wildcard);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/server/data/data-api/src/main/java/org/apache/james/rrt/lib/UserRewritter.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/UserRewritter.java b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/UserRewritter.java
index b9e96de..58950e5 100644
--- a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/UserRewritter.java
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/UserRewritter.java
@@ -19,6 +19,7 @@
 
 package org.apache.james.rrt.lib;
 
+import java.io.Serializable;
 import java.util.List;
 import java.util.Optional;
 import java.util.regex.Matcher;
@@ -40,7 +41,7 @@ import com.google.common.base.Splitter;
 import com.google.common.collect.ImmutableList;
 
 @FunctionalInterface
-public interface UserRewritter {
+public interface UserRewritter extends Serializable {
 
     Optional<User> rewrite(User user) throws AddressException, RecipientRewriteTable.ErrorMappingException;
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java b/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java
index 6e805a0..9df03c8 100644
--- a/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java
+++ b/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java
@@ -39,6 +39,7 @@ import org.apache.james.backends.cassandra.utils.CassandraUtils;
 import org.apache.james.core.Domain;
 import org.apache.james.rrt.lib.AbstractRecipientRewriteTable;
 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 org.apache.james.util.OptionalUtils;
@@ -94,33 +95,33 @@ public class CassandraRecipientRewriteTable extends AbstractRecipientRewriteTabl
     }
 
     @Override
-    public void addMapping(String user, Domain domain, Mapping mapping) {
+    public void addMapping(MappingSource source, Mapping mapping) {
         executor.executeVoid(insertStatement.bind()
-            .setString(USER, getFixedUser(user))
-            .setString(DOMAIN, getFixedDomain(domain).asString())
+            .setString(USER, source.getFixedUser())
+            .setString(DOMAIN, source.getFixedDomain())
             .setString(MAPPING, mapping.asString()))
             .join();
     }
 
     @Override
-    public void removeMapping(String user, Domain domain, Mapping mapping) {
+    public void removeMapping(MappingSource source, Mapping mapping) {
         executor.executeVoid(deleteStatement.bind()
-                .setString(USER, getFixedUser(user))
-                .setString(DOMAIN, getFixedDomain(domain).asString())
+                .setString(USER, source.getFixedUser())
+                .setString(DOMAIN, source.getFixedDomain())
                 .setString(MAPPING, mapping.asString()))
             .join();
     }
 
     @Override
-    public Mappings getUserDomainMappings(String user, Domain domain) {
-        return retrieveMappings(user, domain)
+    public Mappings getUserDomainMappings(MappingSource source) {
+        return retrieveMappings(source)
             .orElse(null);
     }
 
-    private Optional<Mappings> retrieveMappings(String user, Domain domain) {
+    private Optional<Mappings> retrieveMappings(MappingSource source) {
         List<String> mappings = executor.execute(retrieveMappingStatement.bind()
-            .setString(USER, getFixedUser(user))
-            .setString(DOMAIN, getFixedDomain(domain).asString()))
+            .setString(USER, source.getFixedUser())
+            .setString(DOMAIN, source.getFixedDomain()))
             .thenApply(resultSet -> cassandraUtils.convertToStream(resultSet)
                 .map(row -> row.getString(MAPPING))
                 .collect(Guavate.toImmutableList()))
@@ -130,12 +131,12 @@ public class CassandraRecipientRewriteTable extends AbstractRecipientRewriteTabl
     }
 
     @Override
-    public Map<String, Mappings> getAllMappings() {
+    public Map<MappingSource, Mappings> getAllMappings() {
         return executor.execute(retrieveAllMappingsStatement.bind())
             .thenApply(resultSet -> cassandraUtils.convertToStream(resultSet)
-                .map(row -> new UserMapping(row.getString(USER), Domain.of(row.getString(DOMAIN)), row.getString(MAPPING)))
+                .map(row -> new UserMapping(MappingSource.fromUser(row.getString(USER), row.getString(DOMAIN)), row.getString(MAPPING)))
                 .collect(Guavate.toImmutableMap(
-                    UserMapping::asKey,
+                    UserMapping::getSource,
                     UserMapping::toMapping,
                     Mappings::union)))
             .join();
@@ -143,22 +144,17 @@ public class CassandraRecipientRewriteTable extends AbstractRecipientRewriteTabl
 
     private static class UserMapping {
 
-        private final String user;
-        private final Domain domain;
+        private final MappingSource source;
         private final String mapping;
 
-        public UserMapping(String user, Domain domain, String mapping) {
-            this.user = user;
-            this.domain = domain;
+        public UserMapping(MappingSource source, String mapping) {
+            this.source = source;
             this.mapping = mapping;
         }
 
-        public String getUser() {
-            return user;
-        }
 
-        public Domain getDomain() {
-            return domain;
+        public MappingSource getSource() {
+            return source;
         }
 
         public String getMapping() {
@@ -169,16 +165,13 @@ public class CassandraRecipientRewriteTable extends AbstractRecipientRewriteTabl
             return MappingsImpl.fromRawString(getMapping());
         }
 
-        public String asKey() {
-            return getUser() + "@" + getDomain().asString();
-        }
     }
 
     @Override
     protected Mappings mapAddress(String user, Domain domain) {
         return OptionalUtils.orSuppliers(
-            () -> retrieveMappings(user, domain),
-            () -> retrieveMappings(WILDCARD, domain))
+            () -> retrieveMappings(MappingSource.fromUser(user, domain)),
+            () -> retrieveMappings(MappingSource.fromDomain(domain)))
                 .orElse(MappingsImpl.empty());
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/server/data/data-file/src/main/java/org/apache/james/rrt/file/XMLRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-file/src/main/java/org/apache/james/rrt/file/XMLRecipientRewriteTable.java b/server/data/data-file/src/main/java/org/apache/james/rrt/file/XMLRecipientRewriteTable.java
index e6a6f19..0f754a2 100644
--- a/server/data/data-file/src/main/java/org/apache/james/rrt/file/XMLRecipientRewriteTable.java
+++ b/server/data/data-file/src/main/java/org/apache/james/rrt/file/XMLRecipientRewriteTable.java
@@ -28,6 +28,7 @@ import org.apache.james.core.Domain;
 import org.apache.james.rrt.api.RecipientRewriteTableException;
 import org.apache.james.rrt.lib.AbstractRecipientRewriteTable;
 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 org.apache.james.rrt.lib.RecipientRewriteTableUtil;
@@ -43,7 +44,7 @@ public class XMLRecipientRewriteTable extends AbstractRecipientRewriteTable {
     /**
      * Holds the configured mappings
      */
-    private Map<String, String> mappings;
+    private Map<MappingSource, String> mappings;
 
     @Override
     protected void doConfigure(HierarchicalConfiguration arg0) throws ConfigurationException {
@@ -59,7 +60,7 @@ public class XMLRecipientRewriteTable extends AbstractRecipientRewriteTable {
     }
 
     @Override
-    protected Mappings mapAddress(String user, Domain domain) throws RecipientRewriteTableException {
+    protected Mappings mapAddress(String user, Domain domain) {
         return Optional.ofNullable(mappings)
             .map(mappings -> RecipientRewriteTableUtil.getTargetString(user, domain, mappings))
             .map(MappingsImpl::fromRawString)
@@ -67,11 +68,11 @@ public class XMLRecipientRewriteTable extends AbstractRecipientRewriteTable {
     }
 
     @Override
-    public Mappings getUserDomainMappings(String user, Domain domain) throws RecipientRewriteTableException {
+    public Mappings getUserDomainMappings(MappingSource source) {
         if (mappings == null) {
             return null;
         } else {
-            String maps = mappings.get(user + "@" + domain.asString());
+            String maps = mappings.get(source);
             if (maps != null) {
                 return MappingsImpl.fromRawString(maps);
             } else {
@@ -81,10 +82,10 @@ public class XMLRecipientRewriteTable extends AbstractRecipientRewriteTable {
     }
 
     @Override
-    public Map<String, Mappings> getAllMappings() throws RecipientRewriteTableException {
+    public Map<MappingSource, Mappings> getAllMappings() {
         if (mappings != null && mappings.size() > 0) {
-            Map<String, Mappings> mappingsNew = new HashMap<>();
-            for (String key : mappings.keySet()) {
+            Map<MappingSource, Mappings> mappingsNew = new HashMap<>();
+            for (MappingSource key : mappings.keySet()) {
                 mappingsNew.put(key, MappingsImpl.fromRawString(mappings.get(key)));
             }
             return mappingsNew;
@@ -94,12 +95,12 @@ public class XMLRecipientRewriteTable extends AbstractRecipientRewriteTable {
     }
 
     @Override
-    public void addMapping(String user, Domain domain, Mapping mapping) throws RecipientRewriteTableException {
+    public void addMapping(MappingSource source, Mapping mapping) throws RecipientRewriteTableException {
         throw new RecipientRewriteTableException("Read-Only implementation");
     }
 
     @Override
-    public void removeMapping(String user, Domain domain, Mapping mapping) throws RecipientRewriteTableException {
+    public void removeMapping(MappingSource source, Mapping mapping) throws RecipientRewriteTableException {
         throw new RecipientRewriteTableException("Read-Only implementation");
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/server/data/data-file/src/test/java/org/apache/james/rrt/file/XMLRecipientRewriteTableTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-file/src/test/java/org/apache/james/rrt/file/XMLRecipientRewriteTableTest.java b/server/data/data-file/src/test/java/org/apache/james/rrt/file/XMLRecipientRewriteTableTest.java
index 25defc6..3528b49 100644
--- a/server/data/data-file/src/test/java/org/apache/james/rrt/file/XMLRecipientRewriteTableTest.java
+++ b/server/data/data-file/src/test/java/org/apache/james/rrt/file/XMLRecipientRewriteTableTest.java
@@ -23,13 +23,12 @@ import java.util.List;
 import java.util.Optional;
 
 import org.apache.commons.configuration.DefaultConfigurationBuilder;
-import org.apache.james.core.Domain;
 import org.apache.james.rrt.api.RecipientRewriteTableException;
 import org.apache.james.rrt.lib.AbstractRecipientRewriteTable;
 import org.apache.james.rrt.lib.AbstractRecipientRewriteTableTest;
 import org.apache.james.rrt.lib.Mapping;
 import org.apache.james.rrt.lib.Mapping.Type;
-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 org.junit.After;
@@ -58,18 +57,18 @@ public class XMLRecipientRewriteTableTest extends AbstractRecipientRewriteTableT
     protected AbstractRecipientRewriteTable getRecipientRewriteTable() {
         return new XMLRecipientRewriteTable() {
             @Override
-            public void addMapping(String user, Domain domain, Mapping mapping) throws RecipientRewriteTableException {
-                addMappingToConfiguration(user, domain, mapping.getType().withoutPrefix(mapping.asString()), mapping.getType());
+            public void addMapping(MappingSource source, Mapping mapping) throws RecipientRewriteTableException {
+                addMappingToConfiguration(source, mapping.getType().withoutPrefix(mapping.asString()), mapping.getType());
             }
 
             @Override
-            public void removeMapping(String user, Domain domain, Mapping mapping) throws RecipientRewriteTableException {
-                removeMappingFromConfiguration(user, domain, mapping.getType().withoutPrefix(mapping.asString()), mapping.getType());
+            public void removeMapping(MappingSource source, Mapping mapping) throws RecipientRewriteTableException {
+                removeMappingFromConfiguration(source, mapping.getType().withoutPrefix(mapping.asString()), mapping.getType());
             }
 
             @Override
-            public void addAddressMapping(String user, Domain domain, String address) throws RecipientRewriteTableException {
-                addMapping(user, domain, Mapping.address(address));
+            public void addAddressMapping(MappingSource source, String address) throws RecipientRewriteTableException {
+                addMapping(source, Mapping.address(address));
             }
         };
     }
@@ -80,33 +79,33 @@ public class XMLRecipientRewriteTableTest extends AbstractRecipientRewriteTableT
     public void addMappingShouldThrowWhenMappingAlreadyExists() {
     }
 
-    protected void addMappingToConfiguration(String user, Domain domain, String mapping, Type type) throws RecipientRewriteTableException {
-        Mappings mappings = Optional.ofNullable(virtualUserTable.getUserDomainMappings(user, domain))
+    protected void addMappingToConfiguration(MappingSource source, String mapping, Type type) throws RecipientRewriteTableException {
+        Mappings mappings = Optional.ofNullable(virtualUserTable.getUserDomainMappings(source))
             .orElse(MappingsImpl.empty());
 
         Mappings updatedMappings = MappingsImpl.from(mappings)
             .add(Mapping.of(type, mapping))
             .build();
 
-        updateConfiguration(user, domain, mappings, updatedMappings);
+        updateConfiguration(source, mappings, updatedMappings);
     }
 
-    protected void removeMappingFromConfiguration(String user, Domain domain, String mapping, Type type) throws RecipientRewriteTableException {
-        Mappings oldMappings = Optional.ofNullable(virtualUserTable.getUserDomainMappings(user, domain))
+    protected void removeMappingFromConfiguration(MappingSource source, String mapping, Type type) throws RecipientRewriteTableException {
+        Mappings oldMappings = Optional.ofNullable(virtualUserTable.getUserDomainMappings(source))
             .orElseThrow(() -> new RecipientRewriteTableException("Cannot remove from null mappings"));
 
         Mappings updatedMappings = oldMappings.remove(Mapping.of(type, mapping));
 
-        updateConfiguration(user, domain, oldMappings, updatedMappings);
+        updateConfiguration(source, oldMappings, updatedMappings);
     }
 
-    private void updateConfiguration(String user, Domain domain, Mappings oldMappings, Mappings updatedMappings) throws RecipientRewriteTableException {
+    private void updateConfiguration(MappingSource source, Mappings oldMappings, Mappings updatedMappings) throws RecipientRewriteTableException {
         if (oldMappings != null) {
-            removeMappingsFromConfig(user, domain, oldMappings);
+            removeMappingsFromConfig(source, oldMappings);
         }
 
         if (!updatedMappings.isEmpty()) {
-            defaultConfiguration.addProperty("mapping", user + "@" + domain.asString() + "=" + updatedMappings.serialize());
+            defaultConfiguration.addProperty("mapping", source.getFixedUser() + "@" + source.getFixedDomain() + "=" + updatedMappings.serialize());
         }
 
         try {
@@ -118,10 +117,10 @@ public class XMLRecipientRewriteTableTest extends AbstractRecipientRewriteTableT
         }
     }
 
-    private void removeMappingsFromConfig(String user, Domain domain, Mappings mappings) {
+    private void removeMappingsFromConfig(MappingSource source, Mappings mappings) {
         List<String> stored = new ArrayList<>();
         for (String c : defaultConfiguration.getStringArray("mapping")) {
-            String mapping = user + "@" + domain.asString() + "=" + mappings.serialize();
+            String mapping = source.getFixedUser() + "@" + source.getFixedDomain() + "=" + mappings.serialize();
             if (!c.equalsIgnoreCase(mapping)) {
                 stored.add(c);
             }

http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/server/data/data-hbase/src/main/java/org/apache/james/rrt/hbase/HBaseRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-hbase/src/main/java/org/apache/james/rrt/hbase/HBaseRecipientRewriteTable.java b/server/data/data-hbase/src/main/java/org/apache/james/rrt/hbase/HBaseRecipientRewriteTable.java
index 7cfb6af..a601b65 100644
--- a/server/data/data-hbase/src/main/java/org/apache/james/rrt/hbase/HBaseRecipientRewriteTable.java
+++ b/server/data/data-hbase/src/main/java/org/apache/james/rrt/hbase/HBaseRecipientRewriteTable.java
@@ -39,6 +39,7 @@ import org.apache.james.rrt.api.RecipientRewriteTableException;
 import org.apache.james.rrt.hbase.def.HRecipientRewriteTable;
 import org.apache.james.rrt.lib.AbstractRecipientRewriteTable;
 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 org.apache.james.system.hbase.TablePool;
@@ -59,27 +60,25 @@ public class HBaseRecipientRewriteTable extends AbstractRecipientRewriteTable {
     private static final String COLUMN_SEPARATOR = ";";
 
     @Override
-    public void addMapping(String user, Domain domain, Mapping mapping) throws RecipientRewriteTableException {
-        String fixedUser = getFixedUser(user);
-        Domain fixedDomain = getFixedDomain(domain);
-        Mappings map = getUserDomainMappings(fixedUser, fixedDomain);
+    public void addMapping(MappingSource source, Mapping mapping) throws RecipientRewriteTableException {
+        Mappings map = getUserDomainMappings(source);
         if (!map.isEmpty()) {
             Mappings updatedMappings = MappingsImpl.from(map).add(mapping).build();
-            doUpdateMapping(fixedUser, fixedDomain, updatedMappings.serialize());
+            doUpdateMapping(source, updatedMappings.serialize());
         } else {
-            doAddMapping(fixedUser, fixedDomain, mapping.asString());
+            doAddMapping(source, mapping.asString());
         }
     }
 
     @Override
-    public Mappings getUserDomainMappings(String user, Domain domain) throws
+    public Mappings getUserDomainMappings(MappingSource source) throws
             RecipientRewriteTableException {
         HTableInterface table = null;
         Mappings list = MappingsImpl.empty();
         try {
             table = TablePool.getInstance().getRecipientRewriteTable();
             // Optimize this to only make one call.
-            return feedUserDomainMappingsList(table, user, domain, list);
+            return feedUserDomainMappingsList(table, source, list);
         } catch (IOException e) {
             log.error("Error while getting user domain mapping in HBase", e);
             throw new RecipientRewriteTableException("Error while getting user domain mapping in HBase", e);
@@ -88,9 +87,9 @@ public class HBaseRecipientRewriteTable extends AbstractRecipientRewriteTable {
         }
     }
 
-    private Mappings feedUserDomainMappingsList(HTableInterface table, String user, Domain domain, Mappings list) throws
+    private Mappings feedUserDomainMappingsList(HTableInterface table, MappingSource source, Mappings list) throws
             IOException {
-        Get get = new Get(Bytes.toBytes(getRowKey(user, domain)));
+        Get get = new Get(Bytes.toBytes(getRowKey(source)));
         Result result = table.get(get);
         List<KeyValue> keyValues = result.getColumn(HRecipientRewriteTable.COLUMN_FAMILY_NAME,
                                                     HRecipientRewriteTable.COLUMN.MAPPING);
@@ -102,10 +101,10 @@ public class HBaseRecipientRewriteTable extends AbstractRecipientRewriteTable {
     }
 
     @Override
-    public Map<String, Mappings> getAllMappings() throws RecipientRewriteTableException {
+    public Map<MappingSource, Mappings> getAllMappings() throws RecipientRewriteTableException {
         HTableInterface table = null;
         ResultScanner resultScanner = null;
-        Map<String, Mappings> map = new HashMap<>();
+        Map<MappingSource, Mappings> map = new HashMap<>();
         try {
             table = TablePool.getInstance().getRecipientRewriteTable();
             Scan scan = new Scan();
@@ -125,7 +124,7 @@ public class HBaseRecipientRewriteTable extends AbstractRecipientRewriteTable {
                                         .orElse(MappingsImpl.empty()))
                                 .addAll(Splitter.on(COLUMN_SEPARATOR).split(Bytes.toString(keyValue.getValue())))
                                 .build();
-                        map.put(email, mappings);
+                        map.put(MappingSource.parse(email), mappings);
                     }
                 }
             }
@@ -154,9 +153,9 @@ public class HBaseRecipientRewriteTable extends AbstractRecipientRewriteTable {
             table = TablePool.getInstance().getRecipientRewriteTable();
             HTableInterface tableCopy = table;
             return OptionalUtils.orSuppliers(
-                Throwing.supplier(() -> Optional.ofNullable(getMapping(tableCopy, user, domain))).sneakyThrow(),
-                Throwing.supplier(() -> Optional.ofNullable(getMapping(tableCopy, WILDCARD, domain))).sneakyThrow(),
-                Throwing.supplier(() -> Optional.ofNullable(getMapping(tableCopy, user, Domains.WILDCARD))).sneakyThrow());
+                Throwing.supplier(() -> Optional.ofNullable(getMapping(tableCopy, MappingSource.fromUser(user, domain)))).sneakyThrow(),
+                Throwing.supplier(() -> Optional.ofNullable(getMapping(tableCopy, MappingSource.fromDomain(domain)))).sneakyThrow(),
+                Throwing.supplier(() -> Optional.ofNullable(getMapping(tableCopy, MappingSource.fromUser(user, Domains.WILDCARD)))).sneakyThrow());
         } catch (IOException e) {
             log.error("Error while mapping address in HBase", e);
             throw new RecipientRewriteTableException("Error while mapping address in HBase", e);
@@ -165,8 +164,8 @@ public class HBaseRecipientRewriteTable extends AbstractRecipientRewriteTable {
         }
     }
 
-    private String getMapping(HTableInterface table, String user, Domain domain) throws IOException {
-        Get get = new Get(Bytes.toBytes(getRowKey(user, domain)));
+    private String getMapping(HTableInterface table, MappingSource source) throws IOException {
+        Get get = new Get(Bytes.toBytes(getRowKey(source)));
         Result result = table.get(get);
         List<KeyValue> keyValues = result.getColumn(HRecipientRewriteTable.COLUMN_FAMILY_NAME,
                                                     HRecipientRewriteTable.COLUMN.MAPPING);
@@ -177,16 +176,14 @@ public class HBaseRecipientRewriteTable extends AbstractRecipientRewriteTable {
     }
 
     @Override
-    public void removeMapping(String user, Domain domain, Mapping mapping) throws
+    public void removeMapping(MappingSource source, Mapping mapping) throws
             RecipientRewriteTableException {
-        String fixedUser = getFixedUser(user);
-        Domain fixedDomain = getFixedDomain(domain);
-        Mappings map = getUserDomainMappings(fixedUser, fixedDomain);
+        Mappings map = getUserDomainMappings(source);
         if (map.size() > 1) {
             Mappings updatedMappings = map.remove(mapping);
-            doUpdateMapping(fixedUser, fixedDomain, updatedMappings.serialize());
+            doUpdateMapping(source, updatedMappings.serialize());
         } else {
-            doRemoveMapping(fixedUser, fixedDomain);
+            doRemoveMapping(source);
         }
     }
 
@@ -200,8 +197,8 @@ public class HBaseRecipientRewriteTable extends AbstractRecipientRewriteTable {
      * @param mapping the mapping
      * @throws RecipientRewriteTableException
      */
-    private void doUpdateMapping(String user, Domain domain, String mapping) throws RecipientRewriteTableException {
-        doAddMapping(user, domain, mapping);
+    private void doUpdateMapping(MappingSource source, String mapping) throws RecipientRewriteTableException {
+        doAddMapping(source, mapping);
     }
 
     /**
@@ -211,11 +208,11 @@ public class HBaseRecipientRewriteTable extends AbstractRecipientRewriteTable {
      * @param domain the domain
      * @throws RecipientRewriteTableException
      */
-    private void doRemoveMapping(String user, Domain domain) throws RecipientRewriteTableException {
+    private void doRemoveMapping(MappingSource source) throws RecipientRewriteTableException {
         HTableInterface table = null;
         try {
             table = TablePool.getInstance().getRecipientRewriteTable();
-            Delete delete = new Delete(Bytes.toBytes(getRowKey(user, domain)));
+            Delete delete = new Delete(Bytes.toBytes(getRowKey(source)));
             table.delete(delete);
             table.flushCommits();
         } catch (IOException e) {
@@ -234,11 +231,11 @@ public class HBaseRecipientRewriteTable extends AbstractRecipientRewriteTable {
      * @param mapping the mapping
      * @throws RecipientRewriteTableException
      */
-    private void doAddMapping(String user, Domain domain, String mapping) throws RecipientRewriteTableException {
+    private void doAddMapping(MappingSource source, String mapping) throws RecipientRewriteTableException {
         HTableInterface table = null;
         try {
             table = TablePool.getInstance().getRecipientRewriteTable();
-            Put put = new Put(Bytes.toBytes(getRowKey(user, domain)));
+            Put put = new Put(Bytes.toBytes(getRowKey(source)));
             put.add(HRecipientRewriteTable.COLUMN_FAMILY_NAME, HRecipientRewriteTable.COLUMN.MAPPING, Bytes.toBytes(
                     mapping));
             table.put(put);
@@ -258,7 +255,7 @@ public class HBaseRecipientRewriteTable extends AbstractRecipientRewriteTable {
      * @param domain
      * @return the key
      */
-    private String getRowKey(String user, Domain domain) {
-        return user + ROW_SEPARATOR + domain.asString();
+    private String getRowKey(MappingSource source) {
+        return source.getFixedUser() + ROW_SEPARATOR + source.getFixedDomain();
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/server/data/data-jdbc/src/main/java/org/apache/james/rrt/jdbc/JDBCRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-jdbc/src/main/java/org/apache/james/rrt/jdbc/JDBCRecipientRewriteTable.java b/server/data/data-jdbc/src/main/java/org/apache/james/rrt/jdbc/JDBCRecipientRewriteTable.java
index 2cae41f..defea48 100644
--- a/server/data/data-jdbc/src/main/java/org/apache/james/rrt/jdbc/JDBCRecipientRewriteTable.java
+++ b/server/data/data-jdbc/src/main/java/org/apache/james/rrt/jdbc/JDBCRecipientRewriteTable.java
@@ -40,6 +40,7 @@ import org.apache.james.filesystem.api.FileSystem;
 import org.apache.james.rrt.api.RecipientRewriteTableException;
 import org.apache.james.rrt.lib.AbstractRecipientRewriteTable;
 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 org.apache.james.util.sql.JDBCUtil;
@@ -187,15 +188,13 @@ public class JDBCRecipientRewriteTable extends AbstractRecipientRewriteTable {
     }
 
     @Override
-    public void addMapping(String user, Domain domain, Mapping mapping) throws RecipientRewriteTableException {
-        String fixedUser = getFixedUser(user);
-        Domain fixedDomain = getFixedDomain(domain);
-        Mappings map = getUserDomainMappings(fixedUser, fixedDomain);
+    public void addMapping(MappingSource source, Mapping mapping) throws RecipientRewriteTableException {
+        Mappings map = getUserDomainMappings(source);
         if (map != null && map.size() != 0) {
             Mappings updatedMappings = MappingsImpl.from(map).add(mapping).build();
-            doUpdateMapping(fixedUser, fixedDomain, updatedMappings.serialize());
+            doUpdateMapping(source, updatedMappings.serialize());
         }
-        doAddMapping(fixedUser, fixedDomain, mapping.asString());
+        doAddMapping(source, mapping.asString());
     }
 
     @Override
@@ -229,7 +228,7 @@ public class JDBCRecipientRewriteTable extends AbstractRecipientRewriteTable {
     }
 
     @Override
-    public Mappings getUserDomainMappings(String user, Domain domain) throws RecipientRewriteTableException {
+    public Mappings getUserDomainMappings(MappingSource source) throws RecipientRewriteTableException {
         Connection conn = null;
         PreparedStatement mappingStmt = null;
         try {
@@ -237,8 +236,8 @@ public class JDBCRecipientRewriteTable extends AbstractRecipientRewriteTable {
             mappingStmt = conn.prepareStatement(sqlQueries.getSqlString("selectUserDomainMapping", true));
             ResultSet mappingRS = null;
             try {
-                mappingStmt.setString(1, user);
-                mappingStmt.setString(2, domain.asString());
+                mappingStmt.setString(1, source.getFixedUser());
+                mappingStmt.setString(2, source.getFixedDomain());
                 mappingRS = mappingStmt.executeQuery();
                 if (mappingRS.next()) {
                     return MappingsImpl.fromRawString(mappingRS.getString(1));
@@ -257,10 +256,10 @@ public class JDBCRecipientRewriteTable extends AbstractRecipientRewriteTable {
     }
 
     @Override
-    public Map<String, Mappings> getAllMappings() throws RecipientRewriteTableException {
+    public Map<MappingSource, Mappings> getAllMappings() throws RecipientRewriteTableException {
         Connection conn = null;
         PreparedStatement mappingStmt = null;
-        Map<String, Mappings> mapping = new HashMap<>();
+        Map<MappingSource, Mappings> mapping = new HashMap<>();
         try {
             conn = dataSource.getConnection();
             mappingStmt = conn.prepareStatement(sqlQueries.getSqlString("selectAllMappings", true));
@@ -271,7 +270,7 @@ public class JDBCRecipientRewriteTable extends AbstractRecipientRewriteTable {
                     String user = mappingRS.getString(1);
                     Domain domain = Domain.of(mappingRS.getString(2));
                     String map = mappingRS.getString(3);
-                    mapping.put(user + "@" + domain.asString(), MappingsImpl.fromRawString(map));
+                    mapping.put(MappingSource.fromUser(user, domain), MappingsImpl.fromRawString(map));
                 }
                 if (mapping.size() > 0) {
                     return mapping;
@@ -291,15 +290,13 @@ public class JDBCRecipientRewriteTable extends AbstractRecipientRewriteTable {
     }
 
     @Override
-    public void removeMapping(String user, Domain domain, Mapping mapping) throws RecipientRewriteTableException {
-        String fixedUser = getFixedUser(user);
-        Domain fixedDomain = getFixedDomain(domain);
-        Mappings map = getUserDomainMappings(fixedUser, fixedDomain);
+    public void removeMapping(MappingSource source, Mapping mapping) throws RecipientRewriteTableException {
+        Mappings map = getUserDomainMappings(source);
         if (map != null && map.size() > 1) {
             Mappings updatedMappings = map.remove(mapping);
-            doUpdateMapping(fixedUser, fixedDomain, updatedMappings.serialize());
+            doUpdateMapping(source, updatedMappings.serialize());
         } else {
-            doRemoveMapping(fixedUser, fixedDomain, mapping.asString());
+            doRemoveMapping(source, mapping.asString());
         }
     }
 
@@ -315,7 +312,7 @@ public class JDBCRecipientRewriteTable extends AbstractRecipientRewriteTable {
      * @return true if update was successfully
      * @throws RecipientRewriteTableException
      */
-    private void doUpdateMapping(String user, Domain domain, String mapping) throws RecipientRewriteTableException {
+    private void doUpdateMapping(MappingSource source, String mapping) throws RecipientRewriteTableException {
         Connection conn = null;
         PreparedStatement mappingStmt = null;
 
@@ -326,8 +323,8 @@ public class JDBCRecipientRewriteTable extends AbstractRecipientRewriteTable {
             ResultSet mappingRS = null;
             try {
                 mappingStmt.setString(1, mapping);
-                mappingStmt.setString(2, user);
-                mappingStmt.setString(3, domain.asString());
+                mappingStmt.setString(2, source.getFixedUser());
+                mappingStmt.setString(3, source.getFixedDomain());
 
                 if (mappingStmt.executeUpdate() < 1) {
                     throw new RecipientRewriteTableException("Mapping not found");
@@ -357,7 +354,7 @@ public class JDBCRecipientRewriteTable extends AbstractRecipientRewriteTable {
      * @return true if succesfully
      * @throws RecipientRewriteTableException
      */
-    private void doRemoveMapping(String user, Domain domain, String mapping) throws RecipientRewriteTableException {
+    private void doRemoveMapping(MappingSource source, String mapping) throws RecipientRewriteTableException {
         Connection conn = null;
         PreparedStatement mappingStmt = null;
 
@@ -367,8 +364,8 @@ public class JDBCRecipientRewriteTable extends AbstractRecipientRewriteTable {
 
             ResultSet mappingRS = null;
             try {
-                mappingStmt.setString(1, user);
-                mappingStmt.setString(2, domain.asString());
+                mappingStmt.setString(1, source.getFixedUser());
+                mappingStmt.setString(2, source.getFixedDomain());
                 mappingStmt.setString(3, mapping);
                 if (mappingStmt.executeUpdate() < 1) {
                     throw new RecipientRewriteTableException("Mapping not found");
@@ -397,7 +394,7 @@ public class JDBCRecipientRewriteTable extends AbstractRecipientRewriteTable {
      * @return true if successfully
      * @throws RecipientRewriteTableException
      */
-    private void doAddMapping(String user, Domain domain, String mapping) throws RecipientRewriteTableException {
+    private void doAddMapping(MappingSource source, String mapping) throws RecipientRewriteTableException {
         Connection conn = null;
         PreparedStatement mappingStmt = null;
 
@@ -407,8 +404,8 @@ public class JDBCRecipientRewriteTable extends AbstractRecipientRewriteTable {
 
             ResultSet mappingRS = null;
             try {
-                mappingStmt.setString(1, user);
-                mappingStmt.setString(2, domain.asString());
+                mappingStmt.setString(1, source.getFixedUser());
+                mappingStmt.setString(2, source.getFixedDomain());
                 mappingStmt.setString(3, mapping);
 
                 if (mappingStmt.executeUpdate() < 1) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/server/data/data-jpa/src/main/java/org/apache/james/rrt/jpa/JPARecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-jpa/src/main/java/org/apache/james/rrt/jpa/JPARecipientRewriteTable.java b/server/data/data-jpa/src/main/java/org/apache/james/rrt/jpa/JPARecipientRewriteTable.java
index c0ab2ce..cf09987 100644
--- a/server/data/data-jpa/src/main/java/org/apache/james/rrt/jpa/JPARecipientRewriteTable.java
+++ b/server/data/data-jpa/src/main/java/org/apache/james/rrt/jpa/JPARecipientRewriteTable.java
@@ -34,6 +34,7 @@ import org.apache.james.rrt.api.RecipientRewriteTableException;
 import org.apache.james.rrt.jpa.model.JPARecipientRewrite;
 import org.apache.james.rrt.lib.AbstractRecipientRewriteTable;
 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 org.slf4j.Logger;
@@ -63,15 +64,13 @@ public class JPARecipientRewriteTable extends AbstractRecipientRewriteTable {
     }
 
     @Override
-    public void addMapping(String user, Domain domain, Mapping mapping) throws RecipientRewriteTableException {
-        String fixedUser = getFixedUser(user);
-        Domain fixedDomain = getFixedDomain(domain);
-        Mappings map = getUserDomainMappings(fixedUser, fixedDomain);
+    public void addMapping(MappingSource source, Mapping mapping) throws RecipientRewriteTableException {
+        Mappings map = getUserDomainMappings(source);
         if (!map.isEmpty()) {
             Mappings updatedMappings = MappingsImpl.from(map).add(mapping).build();
-            doUpdateMapping(fixedUser, fixedDomain, updatedMappings.serialize());
+            doUpdateMapping(source, updatedMappings.serialize());
         } else {
-            doAddMapping(fixedUser, fixedDomain, mapping.asString());
+            doAddMapping(source, mapping.asString());
         }
     }
 
@@ -112,15 +111,15 @@ public class JPARecipientRewriteTable extends AbstractRecipientRewriteTable {
     }
 
     @Override
-    public Mappings getUserDomainMappings(String user, Domain domain) throws RecipientRewriteTableException {
+    public Mappings getUserDomainMappings(MappingSource source) throws RecipientRewriteTableException {
         EntityManager entityManager = entityManagerFactory.createEntityManager();
         final EntityTransaction transaction = entityManager.getTransaction();
         try {
             transaction.begin();
             @SuppressWarnings("unchecked")
             List<JPARecipientRewrite> virtualUsers = entityManager.createNamedQuery("selectUserDomainMapping")
-                .setParameter("user", user)
-                .setParameter("domain", domain.asString())
+                .setParameter("user", source.getFixedUser())
+                .setParameter("domain", source.getFixedDomain())
                 .getResultList();
             transaction.commit();
             if (virtualUsers.size() > 0) {
@@ -139,17 +138,17 @@ public class JPARecipientRewriteTable extends AbstractRecipientRewriteTable {
     }
 
     @Override
-    public Map<String, Mappings> getAllMappings() throws RecipientRewriteTableException {
+    public Map<MappingSource, Mappings> getAllMappings() throws RecipientRewriteTableException {
         EntityManager entityManager = entityManagerFactory.createEntityManager();
         final EntityTransaction transaction = entityManager.getTransaction();
-        Map<String, Mappings> mapping = new HashMap<>();
+        Map<MappingSource, Mappings> mapping = new HashMap<>();
         try {
             transaction.begin();
             @SuppressWarnings("unchecked")
             List<JPARecipientRewrite> virtualUsers = entityManager.createNamedQuery("selectAllMappings").getResultList();
             transaction.commit();
             for (JPARecipientRewrite virtualUser : virtualUsers) {
-                mapping.put(virtualUser.getUser() + "@" + virtualUser.getDomain(), MappingsImpl.fromRawString(virtualUser.getTargetAddress()));
+                mapping.put(MappingSource.fromUser(virtualUser.getUser(), virtualUser.getDomain()), MappingsImpl.fromRawString(virtualUser.getTargetAddress()));
             }
             return mapping;
         } catch (PersistenceException e) {
@@ -164,15 +163,13 @@ public class JPARecipientRewriteTable extends AbstractRecipientRewriteTable {
     }
 
     @Override
-    public void removeMapping(String user, Domain domain, Mapping mapping) throws RecipientRewriteTableException {
-        String fixedUser = getFixedUser(user);
-        Domain fixedDomain = getFixedDomain(domain);
-        Mappings map = getUserDomainMappings(fixedUser, fixedDomain);
+    public void removeMapping(MappingSource source, Mapping mapping) throws RecipientRewriteTableException {
+        Mappings map = getUserDomainMappings(source);
         if (map.size() > 1) {
             Mappings updatedMappings = map.remove(mapping);
-            doUpdateMapping(fixedUser, fixedDomain, updatedMappings.serialize());
+            doUpdateMapping(source, updatedMappings.serialize());
         } else {
-            doRemoveMapping(fixedUser, fixedDomain, mapping.asString());
+            doRemoveMapping(source, mapping.asString());
         }
     }
 
@@ -185,7 +182,7 @@ public class JPARecipientRewriteTable extends AbstractRecipientRewriteTable {
      * @return true if update was successfully
      * @throws RecipientRewriteTableException
      */
-    private boolean doUpdateMapping(String user, Domain domain, String mapping) throws RecipientRewriteTableException {
+    private boolean doUpdateMapping(MappingSource source, String mapping) throws RecipientRewriteTableException {
         EntityManager entityManager = entityManagerFactory.createEntityManager();
         final EntityTransaction transaction = entityManager.getTransaction();
         try {
@@ -193,8 +190,8 @@ public class JPARecipientRewriteTable extends AbstractRecipientRewriteTable {
             int updated = entityManager
                 .createNamedQuery("updateMapping")
                 .setParameter("targetAddress", mapping)
-                .setParameter("user", user)
-                .setParameter("domain", domain.asString())
+                .setParameter("user", source.getFixedUser())
+                .setParameter("domain", source.getFixedDomain())
                 .executeUpdate();
             transaction.commit();
             if (updated > 0) {
@@ -220,14 +217,14 @@ public class JPARecipientRewriteTable extends AbstractRecipientRewriteTable {
      * @param mapping the mapping
      * @throws RecipientRewriteTableException
      */
-    private void doRemoveMapping(String user, Domain domain, String mapping) throws RecipientRewriteTableException {
+    private void doRemoveMapping(MappingSource source, String mapping) throws RecipientRewriteTableException {
         EntityManager entityManager = entityManagerFactory.createEntityManager();
         final EntityTransaction transaction = entityManager.getTransaction();
         try {
             transaction.begin();
             entityManager.createNamedQuery("deleteMapping")
-                .setParameter("user", user)
-                .setParameter("domain", domain.asString())
+                .setParameter("user", source.getFixedUser())
+                .setParameter("domain", source.getFixedDomain())
                 .setParameter("targetAddress", mapping)
                 .executeUpdate();
             transaction.commit();
@@ -252,12 +249,12 @@ public class JPARecipientRewriteTable extends AbstractRecipientRewriteTable {
      * @param mapping the mapping
      * @throws RecipientRewriteTableException
      */
-    private void doAddMapping(String user, Domain domain, String mapping) throws RecipientRewriteTableException {
+    private void doAddMapping(MappingSource source, String mapping) throws RecipientRewriteTableException {
         EntityManager entityManager = entityManagerFactory.createEntityManager();
         final EntityTransaction transaction = entityManager.getTransaction();
         try {
             transaction.begin();
-            JPARecipientRewrite jpaRecipientRewrite = new JPARecipientRewrite(user, domain, mapping);
+            JPARecipientRewrite jpaRecipientRewrite = new JPARecipientRewrite(source.getFixedUser(), Domain.of(source.getFixedDomain()), mapping);
             entityManager.persist(jpaRecipientRewrite);
             transaction.commit();
         } catch (PersistenceException e) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
index 5f7d9d7..c8224dc 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
@@ -19,7 +19,6 @@
 package org.apache.james.rrt.lib;
 
 import java.util.Map;
-import java.util.Optional;
 import java.util.function.Function;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
@@ -42,7 +41,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.github.fge.lambdas.Throwing;
-import com.google.common.base.Preconditions;
 
 public abstract class AbstractRecipientRewriteTable implements RecipientRewriteTable, Configurable {
     private static final Logger LOGGER = LoggerFactory.getLogger(AbstractRecipientRewriteTable.class);
@@ -114,7 +112,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
         try {
             return MappingsImpl.fromMappings(
                 targetMappings.asStream()
-                    .flatMap(Throwing.<Mapping, Stream<Mapping>>function(target -> convertAndRecurseMapping(user, target, mappingLimit)).sneakyThrow()));
+                    .flatMap(Throwing.function((Mapping target) -> convertAndRecurseMapping(user, target, mappingLimit)).sneakyThrow()));
         } catch (SkipMappingProcessingException e) {
             return MappingsImpl.empty();
         }
@@ -174,7 +172,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
     }
 
     @Override
-    public void addRegexMapping(String user, Domain domain, String regex) throws RecipientRewriteTableException {
+    public void addRegexMapping(MappingSource source, String regex) throws RecipientRewriteTableException {
         try {
             Pattern.compile(regex);
         } catch (PatternSyntaxException e) {
@@ -182,28 +180,27 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
         }
 
         Mapping mapping = Mapping.regex(regex);
-        checkDuplicateMapping(user, domain, mapping);
-        LOGGER.info("Add regex mapping => {} for user: {} domain: {}", regex, user, domain.name());
-        addMapping(user, domain, mapping);
-
+        checkDuplicateMapping(source, mapping);
+        LOGGER.info("Add regex mapping => {} for source {}", regex, source.asString());
+        addMapping(source, mapping);
     }
 
     @Override
-    public void removeRegexMapping(String user, Domain domain, String regex) throws RecipientRewriteTableException {
-        LOGGER.info("Remove regex mapping => {} for user: {} domain: {}", regex, user, domain.name());
-        removeMapping(user, domain, Mapping.regex(regex));
+    public void removeRegexMapping(MappingSource source, String regex) throws RecipientRewriteTableException {
+        LOGGER.info("Remove regex mapping => {} for source: {}", regex, source.asString());
+        removeMapping(source, Mapping.regex(regex));
     }
 
     @Override
-    public void addAddressMapping(String user, Domain domain, String address) throws RecipientRewriteTableException {
+    public void addAddressMapping(MappingSource source, String address) throws RecipientRewriteTableException {
         Mapping mapping = Mapping.address(address)
             .appendDomainFromThrowingSupplierIfNone(this::defaultDomain);
 
         checkHasValidAddress(mapping);
-        checkDuplicateMapping(user, domain, mapping);
+        checkDuplicateMapping(source, mapping);
 
-        LOGGER.info("Add address mapping => {} for user: {} domain: {}", mapping, user, domain.name());
-        addMapping(user, domain, mapping);
+        LOGGER.info("Add address mapping => {} for source: {}", mapping, source.asString());
+        addMapping(source, mapping);
     }
 
     private Domain defaultDomain() throws RecipientRewriteTableException {
@@ -221,82 +218,82 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
     }
 
     @Override
-    public void removeAddressMapping(String user, Domain domain, String address) throws RecipientRewriteTableException {
+    public void removeAddressMapping(MappingSource source, String address) throws RecipientRewriteTableException {
         Mapping mapping = Mapping.address(address)
             .appendDomainFromThrowingSupplierIfNone(this::defaultDomain);
 
-        LOGGER.info("Remove address mapping => {} for user: {} domain: {}", mapping, user, domain.name());
-        removeMapping(user, domain, mapping);
+        LOGGER.info("Remove address mapping => {} for source: {}", mapping, source.asString());
+        removeMapping(source, mapping);
     }
 
     @Override
-    public void addErrorMapping(String user, Domain domain, String error) throws RecipientRewriteTableException {
+    public void addErrorMapping(MappingSource source, String error) throws RecipientRewriteTableException {
         Mapping mapping = Mapping.error(error);
 
-        checkDuplicateMapping(user, domain, mapping);
-        LOGGER.info("Add error mapping => {} for user: {} domain: {}", error, user, domain.name());
-        addMapping(user, domain, mapping);
+        checkDuplicateMapping(source, mapping);
+        LOGGER.info("Add error mapping => {} for source: {}", error, source.asString());
+        addMapping(source, mapping);
 
     }
 
     @Override
-    public void removeErrorMapping(String user, Domain domain, String error) throws RecipientRewriteTableException {
-        LOGGER.info("Remove error mapping => {} for user: {} domain: {}", error, user, domain.name());
-        removeMapping(user, domain, Mapping.error(error));
+    public void removeErrorMapping(MappingSource source, String error) throws RecipientRewriteTableException {
+        LOGGER.info("Remove error mapping => {} for source: {}", error, source.asString());
+        removeMapping(source, Mapping.error(error));
     }
 
     @Override
-    public void addAliasDomainMapping(Domain aliasDomain, Domain realDomain) throws RecipientRewriteTableException {
-        LOGGER.info("Add domain mapping: {} => {}", aliasDomain, realDomain);
-        addMapping(null, aliasDomain, Mapping.domain(realDomain));
+    public void addAliasDomainMapping(MappingSource source, Domain realDomain) throws RecipientRewriteTableException {
+        LOGGER.info("Add domain mapping: {} => {}", source.asDomain().map(Domain::asString).orElse("null"), realDomain);
+        addMapping(source, Mapping.domain(realDomain));
     }
 
     @Override
-    public void removeAliasDomainMapping(Domain aliasDomain, Domain realDomain) throws RecipientRewriteTableException {
-        LOGGER.info("Remove domain mapping: {} => {}", aliasDomain, realDomain);
-        removeMapping(null, aliasDomain, Mapping.domain(realDomain));
+    public void removeAliasDomainMapping(MappingSource source, Domain realDomain) throws RecipientRewriteTableException {
+        LOGGER.info("Remove domain mapping: {} => {}", source.asDomain().map(Domain::asString).orElse("null"), realDomain);
+        removeMapping(source, Mapping.domain(realDomain));
     }
 
     @Override
-    public void addForwardMapping(String user, Domain domain, String address) throws RecipientRewriteTableException {
+    public void addForwardMapping(MappingSource source, String address) throws RecipientRewriteTableException {
         Mapping mapping = Mapping.forward(address)
             .appendDomainFromThrowingSupplierIfNone(this::defaultDomain);
 
         checkHasValidAddress(mapping);
-        checkDuplicateMapping(user, domain, mapping);
+        checkDuplicateMapping(source, mapping);
 
-        LOGGER.info("Add forward mapping => {} for user: {} domain: {}", mapping, user, domain.name());
-        addMapping(user, domain, mapping);
+        LOGGER.info("Add forward mapping => {} for source: {}", mapping, source.asString());
+        addMapping(source, mapping);
     }
 
     @Override
-    public void removeForwardMapping(String user, Domain domain, String address) throws RecipientRewriteTableException {
+    public void removeForwardMapping(MappingSource source, String address) throws RecipientRewriteTableException {
         Mapping mapping = Mapping.forward(address)
             .appendDomainFromThrowingSupplierIfNone(this::defaultDomain);
 
-        LOGGER.info("Remove forward mapping => {} for user: {} domain: {}", mapping, user, domain.name());
-        removeMapping(user, domain, mapping);
+        LOGGER.info("Remove forward mapping => {} for source: {}", mapping, source.asString());
+        removeMapping(source, mapping);
     }
 
     @Override
-    public void addGroupMapping(String user, Domain domain, String address) throws RecipientRewriteTableException {
+    public void addGroupMapping(MappingSource source, String address) throws RecipientRewriteTableException {
         Mapping mapping = Mapping.group(address)
             .appendDomainFromThrowingSupplierIfNone(this::defaultDomain);
 
         checkHasValidAddress(mapping);
-        checkDuplicateMapping(user, domain, mapping);
+        checkDuplicateMapping(source, mapping);
 
-        LOGGER.info("Add forward mapping => {} for user: {} domain: {}", mapping, user, domain.name());
-        addMapping(user, domain, mapping);
+        LOGGER.info("Add forward mapping => {} for source: {}", mapping, source.asString());
+        addMapping(source, mapping);
     }
 
     @Override
-    public void removeGroupMapping(String user, Domain domain, String address) throws RecipientRewriteTableException {
+    public void removeGroupMapping(MappingSource source, String address) throws RecipientRewriteTableException {
         Mapping mapping = Mapping.group(address)
             .appendDomainFromThrowingSupplierIfNone(this::defaultDomain);
 
-        LOGGER.info("Remove forward mapping => {} for user: {} domain: {}", mapping, user, domain.name());
-        removeMapping(user, domain, mapping);
+        LOGGER.info("Remove forward mapping => {} for source: {}", mapping, source.asString());
+        removeMapping(source, mapping);
     }
 
     /**
@@ -304,7 +301,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
      * 
      * @return Map
      */
-    public abstract Map<String, Mappings> getAllMappings() throws RecipientRewriteTableException;
+    public abstract Map<MappingSource, Mappings> getAllMappings() throws RecipientRewriteTableException;
 
     /**
      * This method must return stored Mappings for the given user.
@@ -313,32 +310,11 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
      */
     protected abstract Mappings mapAddress(String user, Domain domain) throws RecipientRewriteTableException;
 
-    private void checkDuplicateMapping(String user, Domain domain, Mapping mapping) throws RecipientRewriteTableException {
-        Mappings mappings = getUserDomainMappings(user, domain);
+    private void checkDuplicateMapping(MappingSource source, Mapping mapping) throws RecipientRewriteTableException {
+        Mappings mappings = getUserDomainMappings(source);
         if (mappings != null && mappings.contains(mapping)) {
-            throw new RecipientRewriteTableException("Mapping " + mapping + " for user " + user + " domain " + domain + " already exist!");
+            throw new RecipientRewriteTableException("Mapping " + mapping + " for " + source.asString() + " already exist!");
         }
     }
 
-    /**
-     * Return user String for the given argument.
-     * If give value is null, return a wildcard.
-     * 
-     * @param user the given user String
-     * @return fixedUser the fixed user String
-     */
-    protected String getFixedUser(String user) {
-        String sanitizedUser = Optional.ofNullable(user).orElse(WILDCARD);
-        Preconditions.checkArgument(sanitizedUser.equals(WILDCARD) || !sanitizedUser.contains("@"));
-        return sanitizedUser;
-    }
-
-    /**
-     * Fix the domain for the given argument.
-     * If give value is null, return a wildcard.
-     */
-    protected Domain getFixedDomain(Domain domain) {
-        return Optional.ofNullable(domain).orElse(Domains.WILDCARD);
-    }
-
 }


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


[21/27] james-project git commit: JAMES-2366 Break getMappings into smaller chunks

Posted by ma...@apache.org.
JAMES-2366 Break getMappings into smaller chunks

Handling non recursive mappings first allow to gain one level of indentation


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

Branch: refs/heads/master
Commit: a64ee17466d7fb591971496252e8341830f3de62
Parents: 465da0e
Author: Matthieu Baechler <ma...@apache.org>
Authored: Tue Apr 17 16:37:08 2018 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:45:26 2018 +0200

----------------------------------------------------------------------
 .../java/org/apache/james/rrt/lib/Mapping.java  |   2 +
 .../rrt/lib/AbstractRecipientRewriteTable.java  | 119 +++++++++----------
 .../org/apache/james/rrt/lib/MappingImpl.java   |  30 +++++
 3 files changed, 87 insertions(+), 64 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/a64ee174/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
index d85a6d2..3a7757a 100644
--- a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
@@ -100,4 +100,6 @@ public interface Mapping {
 
     String getErrorMessage();
 
+    Optional<String> apply(MailAddress input);
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/a64ee174/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
index 80d526d..ce9701c 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
@@ -22,9 +22,10 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
+import java.util.stream.Stream;
 
 import javax.inject.Inject;
-import javax.mail.internet.ParseException;
+import javax.mail.internet.AddressException;
 
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.commons.configuration.HierarchicalConfiguration;
@@ -39,6 +40,7 @@ import org.apache.james.rrt.lib.Mapping.Type;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.github.fge.lambdas.Throwing;
 import com.google.common.base.Preconditions;
 
 public abstract class AbstractRecipientRewriteTable implements RecipientRewriteTable, Configurable {
@@ -111,57 +113,62 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
             throw new ErrorMappingException(targetMappings.getError().getErrorMessage());
         }
 
-        MappingsImpl.Builder mappings = MappingsImpl.builder();
+        try {
+            return MappingsImpl.fromMappings(
+                targetMappings.asStream()
+                    .flatMap(Throwing.<Mapping, Stream<Mapping>>function(target -> convertAndRecurseMapping(target, user, domain, mappingLimit)).sneakyThrow()));
+        } catch (EmptyMappingException e) {
+            return MappingsImpl.empty();
+        }
+    }
 
-        for (String target : targetMappings.asStrings()) {
-            Type type = Mapping.detectType(target);
-            Optional<String> maybeAddressWithMappingApplied = applyMapping(user, domain, target, type);
+    private static class EmptyMappingException extends RuntimeException {
 
-            if (!maybeAddressWithMappingApplied.isPresent()) {
-                continue;
-            }
-            String addressWithMappingApplied = maybeAddressWithMappingApplied.get();
-            LOGGER.debug("Valid virtual user mapping {}@{} to {}", user, domain.name(), addressWithMappingApplied);
-
-            if (recursive) {
-
-                String userName;
-                Domain targetDomain;
-                String[] args = addressWithMappingApplied.split("@");
-
-                if (args.length > 1) {
-                    userName = args[0];
-                    targetDomain = Domain.of(args[1]);
-                } else {
-                    // TODO Is that the right todo here?
-                    userName = addressWithMappingApplied;
-                    targetDomain = domain;
-                }
-
-                // Check if the returned mapping is the same as the
-                // input. If so return null to avoid loops
-                if (userName.equalsIgnoreCase(user) && targetDomain.equals(domain)) {
-                    if (type.equals(Type.Forward)) {
-                        mappings.add(toMapping(addressWithMappingApplied, type));
-                        continue;
-                    }
-                    return MappingsImpl.empty();
-                }
-
-                Mappings childMappings = getMappings(userName, targetDomain, mappingLimit - 1);
-
-                if (childMappings.isEmpty()) {
-                    // add mapping
-                    mappings.add(toMapping(addressWithMappingApplied, type));
-                } else {
-                    mappings = mappings.addAll(childMappings);
-                }
-
-            } else {
-                mappings.add(toMapping(addressWithMappingApplied, type));
+    }
+
+    private Stream<Mapping> convertAndRecurseMapping(Mapping target, String user, Domain domain, int remainingLoops) throws ErrorMappingException, RecipientRewriteTableException, EmptyMappingException, AddressException {
+        Optional<String> maybeAddressWithMappingApplied = target.apply(new MailAddress(user, domain));
+
+        if (!maybeAddressWithMappingApplied.isPresent()) {
+            return Stream.empty();
+        }
+        String addressWithMappingApplied = maybeAddressWithMappingApplied.get();
+        LOGGER.debug("Valid virtual user mapping {}@{} to {}", user, domain.name(), addressWithMappingApplied);
+
+        if (!recursive) {
+            return Stream.of(toMapping(addressWithMappingApplied, target.getType()));
+        }
+
+        String userName;
+        Domain targetDomain;
+        String[] args = addressWithMappingApplied.split("@");
+
+        if (args.length > 1) {
+            userName = args[0];
+            targetDomain = Domain.of(args[1]);
+        } else {
+            // TODO Is that the right todo here?
+            userName = addressWithMappingApplied;
+            targetDomain = domain;
+        }
+
+        // Check if the returned mapping is the same as the
+        // input. If so return null to avoid loops
+        if (userName.equalsIgnoreCase(user) && targetDomain.equals(domain)) {
+            if (target.getType().equals(Type.Forward)) {
+                return Stream.of(toMapping(addressWithMappingApplied, target.getType()));
             }
+            //throw exception ?
+            throw new EmptyMappingException();
+        }
+
+        Mappings childMappings = getMappings(userName, targetDomain, remainingLoops - 1);
+
+        if (childMappings.isEmpty()) {
+            return Stream.of(toMapping(addressWithMappingApplied, target.getType()));
+        } else {
+            return childMappings.asStream();
         }
-        return mappings.build();
     }
 
     private Mapping toMapping(String mappedAddress, Type type) {
@@ -178,22 +185,6 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
         throw new IllegalArgumentException("unhandled enum type");
     }
 
-    private Optional<String> applyMapping(String user, Domain domain, String target, Type type) {
-        switch (type) {
-            case Regex:
-                try {
-                    return RecipientRewriteTableUtil.regexMap(new MailAddress(user, domain.asString()), MappingImpl.of(target));
-                } catch (PatternSyntaxException | ParseException e) {
-                    LOGGER.error("Exception during regexMap processing: ", e);
-                    return Optional.ofNullable(target);
-                }
-            case Domain:
-                return Optional.of(user + "@" + Type.Domain.withoutPrefix(target));
-            default:
-                return Optional.of(type.withoutPrefix(target));
-        }
-    }
-
     @Override
     public void addRegexMapping(String user, Domain domain, String regex) throws RecipientRewriteTableException {
         try {

http://git-wip-us.apache.org/repos/asf/james-project/blob/a64ee174/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingImpl.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingImpl.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingImpl.java
index c16d60c..54d265e 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingImpl.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingImpl.java
@@ -23,18 +23,23 @@ package org.apache.james.rrt.lib;
 import java.io.Serializable;
 import java.util.Optional;
 import java.util.function.Supplier;
+import java.util.regex.PatternSyntaxException;
 
 import javax.mail.internet.AddressException;
 
 import org.apache.james.core.Domain;
 import org.apache.james.core.MailAddress;
 import org.apache.james.rrt.api.RecipientRewriteTableException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Objects;
 import com.google.common.base.Preconditions;
 
 public class MappingImpl implements Mapping, Serializable {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(MappingImpl.class);
+
     private static final long serialVersionUID = 1L;
 
     public static MappingImpl of(String mapping) {
@@ -136,6 +141,31 @@ public class MappingImpl implements Mapping, Serializable {
     }
 
     @Override
+    public Optional<String> apply(MailAddress address) {
+        switch (getType()) {
+            case Regex:
+                try {
+                    return RecipientRewriteTableUtil.regexMap(address, this);
+                } catch (PatternSyntaxException e) {
+                    LOGGER.error("Exception during regexMap processing: ", e);
+                    return Optional.of(asString());
+                }
+            case Domain:
+                return Optional.of(address.getLocalPart() + "@" + mapping);
+            case Forward:
+                return Optional.of(mapping);
+            case Group:
+                return Optional.of(mapping);
+            case Address:
+                return Optional.of(mapping);
+            case Error:
+                return Optional.empty();
+        }
+        throw new IllegalArgumentException("unhandle enum type: " + getType());
+    }
+
+
+    @Override
     public final boolean equals(Object other) {
         if (other instanceof MappingImpl) {
             MappingImpl otherMapping = (MappingImpl) other;


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


[22/27] james-project git commit: JAMES-2366 refactor RecipientRewriteTableUtil.regexMap

Posted by ma...@apache.org.
JAMES-2366 refactor RecipientRewriteTableUtil.regexMap


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

Branch: refs/heads/master
Commit: 620bf69202726a672189c11ecb195a4c543c20f8
Parents: 930e7e5
Author: Matthieu Baechler <ma...@apache.org>
Authored: Tue Apr 17 16:24:50 2018 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:45:26 2018 +0200

----------------------------------------------------------------------
 .../rrt/lib/AbstractRecipientRewriteTable.java  |   2 +-
 .../rrt/lib/RecipientRewriteTableUtil.java      | 101 ++++++-------------
 .../rrt/lib/RecipientRewriteTableUtilTest.java  |  51 +++++++++-
 .../mailets/AbstractRecipientRewriteTable.java  |   3 +-
 4 files changed, 83 insertions(+), 74 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/620bf692/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
index 001b554..8fb522e 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
@@ -182,7 +182,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
         switch (type) {
             case Regex:
                 try {
-                    return Optional.ofNullable(RecipientRewriteTableUtil.regexMap(new MailAddress(user, domain.asString()), target));
+                    return Optional.ofNullable(RecipientRewriteTableUtil.regexMap(new MailAddress(user, domain.asString()), MappingImpl.of(target)));
                 } catch (PatternSyntaxException | ParseException e) {
                     LOGGER.error("Exception during regexMap processing: ", e);
                     return Optional.ofNullable(target);

http://git-wip-us.apache.org/repos/asf/james-project/blob/620bf692/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableUtil.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableUtil.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableUtil.java
index ef4febe..d849a8b 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableUtil.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableUtil.java
@@ -19,6 +19,7 @@
 package org.apache.james.rrt.lib;
 
 import java.util.HashMap;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Optional;
@@ -26,17 +27,26 @@ import java.util.StringTokenizer;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
+import java.util.stream.IntStream;
 
 import org.apache.james.core.Domain;
 import org.apache.james.core.MailAddress;
 import org.apache.james.rrt.lib.Mapping.Type;
 import org.apache.james.util.OptionalUtils;
 
+import com.github.steveash.guavate.Guavate;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableList;
+
 /**
  * This helper class contains methods for the RecipientRewriteTable implementations
  */
 public class RecipientRewriteTableUtil {
 
+    private static final int REGEX = 1;
+    private static final int PARAMETERIZED_STRING = 2;
+
     private RecipientRewriteTableUtil() {
     }
 
@@ -46,89 +56,38 @@ public class RecipientRewriteTableUtil {
      * If a mapped target string begins with the prefix regex:, it must be
      * formatted as regex:<regular-expression>:<parameterized-string>, e.g.,
      * regex:(.*)@(.*):${1}@tld
-     * 
-     * @param address
-     *            the MailAddress to be mapped
-     * @param targetString
-     *            a String specifying the mapping
-     * @throws MalformedPatternException
      */
-    public static String regexMap(MailAddress address, String targetString) {
-        String result = null;
-        int identifierLength = Type.Regex.asPrefix().length();
-
-        int msgPos = targetString.indexOf(':', identifierLength + 1);
+    public static String regexMap(MailAddress address, Mapping mapping) {
+        Preconditions.checkArgument(mapping.getType() == Type.Regex);
 
-        // Throw exception on invalid format
-        if (msgPos < identifierLength + 1) {
-            throw new PatternSyntaxException("Regex should be formatted as regex:<regular-expression>:<parameterized-string>", targetString, 0);
+        List<String> parts = Splitter.on(':').splitToList(mapping.asString());
+        if (parts.size() != 3) {
+            throw new PatternSyntaxException("Regex should be formatted as regex:<regular-expression>:<parameterized-string>", mapping.asString(), 0);
         }
 
-        Pattern pattern = Pattern.compile(targetString.substring(identifierLength, msgPos));
-        Matcher match = pattern.matcher(address.toString());
+        Pattern pattern = Pattern.compile(parts.get(REGEX));
+        Matcher match = pattern.matcher(address.asString());
 
         if (match.matches()) {
-            Map<String, String> parameters = new HashMap<>(match.groupCount());
-            for (int i = 1; i < match.groupCount(); i++) {
-                parameters.put(Integer.toString(i), match.group(i));
-            }
-            result = replaceParameters(targetString.substring(msgPos + 1), parameters);
+            ImmutableList<String> parameters = listMatchingGroups(match);
+            return replaceParameters(parts.get(PARAMETERIZED_STRING), parameters);
         }
-        return result;
+        return null;
     }
 
-    /**
-     * Returns a named string, replacing parameters with the values set.
-     * 
-     * @param str
-     *            the name of the String resource required.
-     * @param parameters
-     *            a map of parameters (name-value string pairs) which are
-     *            replaced where found in the input strings
-     * @return the requested resource
-     */
-    public static String replaceParameters(String str, Map<String, String> parameters) {
-        if (str != null && parameters != null) {
-            // Do parameter replacements for this string resource.
-            StringBuilder replaceBuffer = new StringBuilder(64);
-            for (Map.Entry<String, String> entry : parameters.entrySet()) {
-                replaceBuffer.setLength(0);
-                replaceBuffer.append("${").append(entry.getKey()).append("}");
-                str = substituteSubString(str, replaceBuffer.toString(), entry.getValue());
-            }
-        }
-
-        return str;
+    private static ImmutableList<String> listMatchingGroups(Matcher match) {
+        return IntStream
+            .rangeClosed(1, match.groupCount())
+            .mapToObj(match::group)
+            .collect(Guavate.toImmutableList());
     }
 
-    /**
-     * Replace substrings of one string with another string and return altered
-     * string.
-     * 
-     * @param input
-     *            input string
-     * @param find
-     *            the string to replace
-     * @param replace
-     *            the string to replace with
-     * @return the substituted string
-     */
-    private static String substituteSubString(String input, String find, String replace) {
-        int findLength = find.length();
-        int replaceLength = replace.length();
-
-        StringBuilder output = new StringBuilder(input);
-        int index = input.indexOf(find);
-        int outputOffset = 0;
-
-        while (index > -1) {
-            output.replace(index + outputOffset, index + outputOffset + findLength, replace);
-            outputOffset = outputOffset + (replaceLength - findLength);
-
-            index = input.indexOf(find, index + findLength);
+    private static String replaceParameters(String input, List<String> parameters) {
+        int i = 1;
+        for (String parameter: parameters) {
+            input = input.replace("${" + i++ + "}", parameter);
         }
-
-        return output.toString();
+        return input;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/james-project/blob/620bf692/server/data/data-library/src/test/java/org/apache/james/rrt/lib/RecipientRewriteTableUtilTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/test/java/org/apache/james/rrt/lib/RecipientRewriteTableUtilTest.java b/server/data/data-library/src/test/java/org/apache/james/rrt/lib/RecipientRewriteTableUtilTest.java
index 3c0b9b4..f9394a9 100644
--- a/server/data/data-library/src/test/java/org/apache/james/rrt/lib/RecipientRewriteTableUtilTest.java
+++ b/server/data/data-library/src/test/java/org/apache/james/rrt/lib/RecipientRewriteTableUtilTest.java
@@ -19,6 +19,9 @@
 package org.apache.james.rrt.lib;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.util.regex.PatternSyntaxException;
 
 import org.apache.james.core.MailAddress;
 import org.junit.Test;
@@ -28,11 +31,57 @@ public class RecipientRewriteTableUtilTest {
     @Test
     public void regexMapShouldCorrectlyReplaceMatchingUsername() throws Exception {
         MailAddress mailAddress = new MailAddress("prefix_abc@test");
-        assertThat(RecipientRewriteTableUtil.regexMap(mailAddress, "regex:prefix_.*:admin@test"))
+        assertThat(RecipientRewriteTableUtil.regexMap(mailAddress, MappingImpl.regex("prefix_.*:admin@test")))
             .isEqualTo("admin@test");
     }
 
     @Test
+    public void regexMapShouldThrowOnNullAddress() throws Exception {
+        MailAddress address = null;
+        assertThatThrownBy(() -> RecipientRewriteTableUtil.regexMap(address, MappingImpl.regex("prefix_.*:admin@test")))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    public void regexMapShouldThrowOnNullRegexMapping() throws Exception {
+        Mapping regexMapping = null;
+        assertThatThrownBy(() -> RecipientRewriteTableUtil.regexMap(new MailAddress("abc@test"), regexMapping))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    public void regexMapShouldThrowOnNonRegexMapping() throws Exception {
+        assertThatThrownBy(() -> RecipientRewriteTableUtil.regexMap(new MailAddress("abc@test"), MappingImpl.error("mapping")))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void regexMapShouldThrowOnInvalidSyntax() throws Exception {
+        assertThatThrownBy(() -> RecipientRewriteTableUtil.regexMap(new MailAddress("abc@test"), MappingImpl.regex("singlepart")))
+            .isInstanceOf(PatternSyntaxException.class);
+    }
+
+    @Test
+    public void regexMapShouldReturnInputWhenRegexDoesntMatch() throws Exception {
+        assertThat(RecipientRewriteTableUtil.regexMap(new MailAddress("abc@test"), MappingImpl.regex("notmatching:notreplaced")))
+            .isNull();
+    }
+
+    @Test
+    public void regexMapShouldCorrectlyReplaceMatchingGroups() throws Exception {
+        MailAddress mailAddress = new MailAddress("prefix_abc@test");
+        assertThat(RecipientRewriteTableUtil.regexMap(mailAddress, MappingImpl.regex("prefix_(.*)@test:admin@${1}")))
+            .isEqualTo("admin@abc");
+    }
+
+    @Test
+    public void regexMapShouldCorrectlyReplaceSeveralMatchingGroups() throws Exception {
+        MailAddress mailAddress = new MailAddress("prefix_abc_def@test");
+        assertThat(RecipientRewriteTableUtil.regexMap(mailAddress, MappingImpl.regex("prefix_(.*)_(.*)@test:admin@${1}.${2}")))
+            .isEqualTo("admin@abc.def");
+    }
+
+    @Test
     public void getSeparatorShouldReturnCommaWhenCommaIsPresent() {
         String separator = RecipientRewriteTableUtil.getSeparator("regex:(.*)@localhost, regex:user@test");
         assertThat(separator).isEqualTo(",");

http://git-wip-us.apache.org/repos/asf/james-project/blob/620bf692/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/AbstractRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/AbstractRecipientRewriteTable.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/AbstractRecipientRewriteTable.java
index 44044e3..1efb4c1 100755
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/AbstractRecipientRewriteTable.java
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/AbstractRecipientRewriteTable.java
@@ -36,6 +36,7 @@ import org.apache.james.core.MailAddress;
 import org.apache.james.dnsservice.api.DNSService;
 import org.apache.james.domainlist.api.DomainList;
 import org.apache.james.domainlist.api.DomainListException;
+import org.apache.james.rrt.lib.MappingImpl;
 import org.apache.james.rrt.lib.RecipientRewriteTableUtil;
 import org.apache.james.server.core.MailImpl;
 import org.apache.mailet.Experimental;
@@ -116,7 +117,7 @@ public abstract class AbstractRecipientRewriteTable extends GenericMailet {
 
                         if (targetAddress.startsWith("regex:")) {
                             try {
-                                targetAddress = RecipientRewriteTableUtil.regexMap(source, targetAddress);
+                                targetAddress = RecipientRewriteTableUtil.regexMap(source, MappingImpl.of(targetAddress));
                             } catch (PatternSyntaxException e) {
                                 LOGGER.error("Exception during regexMap processing: ", e);
                             }


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


[26/27] james-project git commit: JAMES-2366 migration of MappingTest to junit 5

Posted by ma...@apache.org.
JAMES-2366 migration of MappingTest to junit 5


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

Branch: refs/heads/master
Commit: 776fc33acb59de3772b63fc6a8c278f7dd57d088
Parents: f0ce9cc
Author: Matthieu Baechler <ma...@apache.org>
Authored: Fri Apr 20 15:33:33 2018 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:49:33 2018 +0200

----------------------------------------------------------------------
 .../org/apache/james/rrt/lib/MappingTest.java   | 98 ++++++++++----------
 1 file changed, 49 insertions(+), 49 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/776fc33a/server/data/data-api/src/test/java/org/apache/james/rrt/lib/MappingTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/test/java/org/apache/james/rrt/lib/MappingTest.java b/server/data/data-api/src/test/java/org/apache/james/rrt/lib/MappingTest.java
index d14dd6b..63fd182 100644
--- a/server/data/data-api/src/test/java/org/apache/james/rrt/lib/MappingTest.java
+++ b/server/data/data-api/src/test/java/org/apache/james/rrt/lib/MappingTest.java
@@ -31,276 +31,276 @@ import nl.jqno.equalsverifier.EqualsVerifier;
 public class MappingTest {
 
     @Test
-    public void hasPrefixShouldReturnTrueWhenRegex() {
+    void hasPrefixShouldReturnTrueWhenRegex() {
         boolean hasPrefix = Mapping.Type.hasPrefix(Type.Regex.asPrefix() + "myRegex");
         assertThat(hasPrefix).isTrue();
     }
 
     @Test
-    public void hasPrefixShouldReturnTrueWhenDomain() {
+    void hasPrefixShouldReturnTrueWhenDomain() {
         boolean hasPrefix = Mapping.Type.hasPrefix(Type.Domain.asPrefix() + "myRegex");
         assertThat(hasPrefix).isTrue();
     }
 
     @Test
-    public void hasPrefixShouldReturnTrueWhenError() {
+    void hasPrefixShouldReturnTrueWhenError() {
         boolean hasPrefix = Mapping.Type.hasPrefix(Type.Error.asPrefix() + "myRegex");
         assertThat(hasPrefix).isTrue();
     }
 
     @Test
-    public void hasPrefixShouldReturnTrueWhenForward() {
+    void hasPrefixShouldReturnTrueWhenForward() {
         boolean hasPrefix = Mapping.Type.hasPrefix(Type.Forward.asPrefix() + "myRegex");
         assertThat(hasPrefix).isTrue();
     }
 
     @Test
-    public void hasPrefixShouldReturnFalseWhenAddress() {
+    void hasPrefixShouldReturnFalseWhenAddress() {
         boolean hasPrefix = Mapping.Type.hasPrefix(Type.Address.asPrefix() + "myRegex");
         assertThat(hasPrefix).isFalse();
     }
 
     @Test
-    public void detectTypeShouldReturnAddressWhenAddressPrefix() {
+    void detectTypeShouldReturnAddressWhenAddressPrefix() {
         assertThat(Mapping.detectType(Type.Address.asPrefix() + "mapping"))
             .isEqualTo(Type.Address);
     }
 
     @Test
-    public void detectTypeShouldReturnRegexWhenRegexPrefix() {
+    void detectTypeShouldReturnRegexWhenRegexPrefix() {
         assertThat(Mapping.detectType(Type.Regex.asPrefix() + "mapping"))
             .isEqualTo(Type.Regex);
     }
 
     @Test
-    public void detectTypeShouldReturnErrorWhenErrorPrefix() {
+    void detectTypeShouldReturnErrorWhenErrorPrefix() {
         assertThat(Mapping.detectType(Type.Error.asPrefix() + "mapping"))
             .isEqualTo(Type.Error);
     }
 
     @Test
-    public void detectTypeShouldReturnDomainWhenDomainPrefix() {
+    void detectTypeShouldReturnDomainWhenDomainPrefix() {
         assertThat(Mapping.detectType(Type.Domain.asPrefix() + "mapping"))
             .isEqualTo(Type.Domain);
     }
 
     @Test
-    public void detectTypeShouldReturnForwardWhenForwardPrefix() {
+    void detectTypeShouldReturnForwardWhenForwardPrefix() {
         assertThat(Mapping.detectType(Type.Forward.asPrefix() + "mapping"))
             .isEqualTo(Type.Forward);
     }
 
     @Test
-    public void withoutPrefixShouldRemoveAddressPrefix() {
+    void withoutPrefixShouldRemoveAddressPrefix() {
         assertThat(Type.Address.withoutPrefix(Type.Address.asPrefix() + "mapping"))
             .isEqualTo("mapping");
     }
 
     @Test
-    public void withoutPrefixShouldDoNothingWhenAddressAndNoPrefix() {
+    void withoutPrefixShouldDoNothingWhenAddressAndNoPrefix() {
         assertThat(Type.Address.withoutPrefix("mapping"))
             .isEqualTo("mapping");
     }
 
     @Test
-    public void withoutPrefixShouldRemoveDomainPrefix() {
+    void withoutPrefixShouldRemoveDomainPrefix() {
         assertThat(Type.Domain.withoutPrefix(Type.Domain.asPrefix() + "mapping"))
             .isEqualTo("mapping");
     }
 
     @Test
-    public void withoutPrefixShouldRemoveErrorPrefix() {
+    void withoutPrefixShouldRemoveErrorPrefix() {
         assertThat(Type.Error.withoutPrefix(Type.Error.asPrefix() + "mapping"))
             .isEqualTo("mapping");
     }
 
     @Test
-    public void withoutPrefixShouldRemoveRegexPrefix() {
+    void withoutPrefixShouldRemoveRegexPrefix() {
         assertThat(Type.Regex.withoutPrefix(Type.Regex.asPrefix() + "mapping"))
             .isEqualTo("mapping");
     }
 
     @Test
-    public void withoutPrefixShouldRemoveForwardPrefix() {
+    void withoutPrefixShouldRemoveForwardPrefix() {
         assertThat(Type.Forward.withoutPrefix(Type.Forward.asPrefix() + "mapping"))
             .isEqualTo("mapping");
     }
 
     @Test
-    public void withoutPrefixShouldThrowOnBadPrefix() {
+    void withoutPrefixShouldThrowOnBadPrefix() {
         assertThatThrownBy(() -> Type.Regex.withoutPrefix(Type.Domain.asPrefix() + "mapping"))
             .isInstanceOf(IllegalArgumentException.class);
     }
 
     @Test
-    public void withoutPrefixShouldThrowWhenNoPrefix() {
+    void withoutPrefixShouldThrowWhenNoPrefix() {
         assertThatThrownBy(() -> Type.Regex.withoutPrefix("mapping"))
             .isInstanceOf(IllegalArgumentException.class);
     }
 
     @Test
-    public void withoutPrefixShouldThrowWhenNoPrefixOnForwardType() {
+    void withoutPrefixShouldThrowWhenNoPrefixOnForwardType() {
         assertThatThrownBy(() -> Type.Forward.withoutPrefix("mapping"))
             .isInstanceOf(IllegalArgumentException.class);
     }
 
     @Test
-    public void beanShouldRespectBeanContract() {
+    void beanShouldRespectBeanContract() {
         EqualsVerifier.forClass(Mapping.Impl.class)
             .verify();
     }
 
     @Test
-    public void addressFactoryMethodShouldThrowOnNull() {
+    void addressFactoryMethodShouldThrowOnNull() {
         assertThatThrownBy(() -> Mapping.address(null))
             .isInstanceOf(NullPointerException.class);
     }
 
     @Test
-    public void regexFactoryMethodShouldThrowOnNull() {
+    void regexFactoryMethodShouldThrowOnNull() {
         assertThatThrownBy(() -> Mapping.regex(null))
             .isInstanceOf(NullPointerException.class);
     }
 
     @Test
-    public void domainFactoryMethodShouldThrowOnNull() {
+    void domainFactoryMethodShouldThrowOnNull() {
         assertThatThrownBy(() -> Mapping.domain(null))
             .isInstanceOf(NullPointerException.class);
     }
 
     @Test
-    public void errorFactoryMethodShouldThrowOnNull() {
+    void errorFactoryMethodShouldThrowOnNull() {
         assertThatThrownBy(() -> Mapping.error(null))
             .isInstanceOf(NullPointerException.class);
     }
 
     @Test
-    public void forwardFactoryMethodShouldThrowOnNull() {
+    void forwardFactoryMethodShouldThrowOnNull() {
         assertThatThrownBy(() -> Mapping.forward(null))
             .isInstanceOf(NullPointerException.class);
     }
 
     @Test
-    public void groupFactoryMethodShouldThrowOnNull() {
+    void groupFactoryMethodShouldThrowOnNull() {
         assertThatThrownBy(() -> Mapping.group(null))
             .isInstanceOf(NullPointerException.class);
     }
 
     @Test
-    public void hasDomainShouldReturnTrueWhenMappingContainAtMark() {
+    void hasDomainShouldReturnTrueWhenMappingContainAtMark() {
         assertThat(Mapping.address("a@b").hasDomain()).isTrue();
     }
 
     @Test
-    public void hasDomainShouldReturnFalseWhenMappingIsEmpty() {
+    void hasDomainShouldReturnFalseWhenMappingIsEmpty() {
         assertThat(Mapping.address("").hasDomain()).isFalse();
     }
 
     @Test
-    public void hasDomainShouldReturnFalseWhenMappingIsBlank() {
+    void hasDomainShouldReturnFalseWhenMappingIsBlank() {
         assertThat(Mapping.address(" ").hasDomain()).isFalse();
     }
 
     @Test
-    public void hasDomainShouldReturnFalseWhenMappingDoesntContainAtMark() {
+    void hasDomainShouldReturnFalseWhenMappingDoesntContainAtMark() {
         assertThat(Mapping.address("abc").hasDomain()).isFalse();
     }
 
     @Test
-    public void appendDefaultDomainShouldWorkOnValidDomain() {
+    void appendDefaultDomainShouldWorkOnValidDomain() {
         assertThat(Mapping.address("abc").appendDomainIfNone(() -> Domain.of("domain"))).isEqualTo(Mapping.address("abc@domain"));
     }
 
     @Test
-    public void appendDefaultDomainShouldNotAddDomainWhenMappingAlreadyContainsDomains() {
+    void appendDefaultDomainShouldNotAddDomainWhenMappingAlreadyContainsDomains() {
         assertThat(Mapping.address("abc@d").appendDomainIfNone(() -> Domain.of("domain"))).isEqualTo(Mapping.address("abc@d"));
     }
 
     @Test
-    public void appendDomainShouldThrowWhenNullDomain() {
+    void appendDomainShouldThrowWhenNullDomain() {
         assertThatThrownBy(() -> Mapping.address("abc@d").appendDomainIfNone(null)).isInstanceOf(NullPointerException.class);
     }
 
     @Test
-    public void getTypeShouldReturnAddressWhenNoPrefix() {
+    void getTypeShouldReturnAddressWhenNoPrefix() {
         assertThat(Mapping.address("abc").getType()).isEqualTo(Mapping.Type.Address);
     }
 
     @Test
-    public void getTypeShouldReturnAddressWhenEmpty() {
+    void getTypeShouldReturnAddressWhenEmpty() {
         assertThat(Mapping.address("").getType()).isEqualTo(Mapping.Type.Address);
     }
 
     @Test
-    public void getTypeShouldReturnRegexWhenRegexPrefix() {
+    void getTypeShouldReturnRegexWhenRegexPrefix() {
         assertThat(Mapping.regex("abc").getType()).isEqualTo(Mapping.Type.Regex);
     }
 
     @Test
-    public void getTypeShouldReturnErrorWhenErrorPrefix() {
+    void getTypeShouldReturnErrorWhenErrorPrefix() {
         assertThat(Mapping.error("abc").getType()).isEqualTo(Mapping.Type.Error);
     }
 
     @Test
-    public void getTypeShouldReturnDomainWhenDomainPrefix() {
+    void getTypeShouldReturnDomainWhenDomainPrefix() {
         assertThat(Mapping.domain(Domain.of("abc")).getType()).isEqualTo(Mapping.Type.Domain);
     }
 
     @Test
-    public void getTypeShouldReturnForwardWhenForwardPrefix() {
+    void getTypeShouldReturnForwardWhenForwardPrefix() {
         assertThat(Mapping.forward("abc").getType()).isEqualTo(Mapping.Type.Forward);
     }
 
     @Test
-    public void getTypeShouldReturnGroupWhenGroupPrefix() {
+    void getTypeShouldReturnGroupWhenGroupPrefix() {
         assertThat(Mapping.group("abc").getType()).isEqualTo(Mapping.Type.Group);
     }
 
     @Test
-    public void getErrorMessageShouldThrowWhenMappingIsNotAnError() {
+    void getErrorMessageShouldThrowWhenMappingIsNotAnError() {
         assertThatThrownBy(() -> Mapping.domain(Domain.of("toto")).getErrorMessage())
             .isInstanceOf(IllegalStateException.class);
     }
 
     @Test
-    public void getErrorMessageShouldReturnMessageWhenErrorWithMessage() {
+    void getErrorMessageShouldReturnMessageWhenErrorWithMessage() {
         assertThat(Mapping.error("toto").getErrorMessage()).isEqualTo("toto");
     }
 
     @Test
-    public void getErrorMessageShouldReturnWhenErrorWithoutMessage() {
+    void getErrorMessageShouldReturnWhenErrorWithoutMessage() {
         assertThat(Mapping.error("").getErrorMessage()).isEqualTo("");
     }
 
     @Test
-    public void asMailAddressShouldReturnMappingValueForAddress() throws Exception {
+    void asMailAddressShouldReturnMappingValueForAddress() throws Exception {
         assertThat(Mapping.address("value@domain").asMailAddress())
             .contains(new MailAddress("value@domain"));
     }
 
     @Test
-    public void asMailAddressShouldReturnEmptyOnInvalidAddress() {
+    void asMailAddressShouldReturnEmptyOnInvalidAddress() {
         assertThat(Mapping.address("value").asMailAddress())
             .isEmpty();
     }
 
     @Test
-    public void asMailAddressShouldReturnEmptyForError() {
+    void asMailAddressShouldReturnEmptyForError() {
         assertThat(Mapping.error("value").asMailAddress()).isEmpty();
     }
 
     @Test
-    public void asMailAddressShouldReturnEmptyForRegex() {
+    void asMailAddressShouldReturnEmptyForRegex() {
         assertThat(Mapping.regex("value").asMailAddress()).isEmpty();
     }
 
     @Test
-    public void asMailAddressShouldReturnEmptyForDomain() {
+    void asMailAddressShouldReturnEmptyForDomain() {
         assertThat(Mapping.domain(Domain.of("value")).asMailAddress()).isEmpty();
     }
 
     @Test
-    public void asMailAddressShouldReturnMappingValueForForward() throws Exception {
+    void asMailAddressShouldReturnMappingValueForForward() throws Exception {
         assertThat(Mapping.forward("value@domain").asMailAddress())
             .contains(new MailAddress("value@domain"));
     }


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


[16/27] james-project git commit: JAMES-2366 Error mapping should throw when trying to rewrite a User

Posted by ma...@apache.org.
JAMES-2366 Error mapping should throw when trying to rewrite a User


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

Branch: refs/heads/master
Commit: 6a5b348d5538adbc3baf4ff64eb08b1e310448bb
Parents: ef5ff3f
Author: Matthieu Baechler <ma...@apache.org>
Authored: Wed Apr 18 15:07:05 2018 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:45:26 2018 +0200

----------------------------------------------------------------------
 .../java/org/apache/james/rrt/lib/Mapping.java  |  7 ++--
 .../org/apache/james/rrt/lib/UserRewritter.java |  9 +++--
 .../apache/james/rrt/lib/NoneRewiterTest.java   | 36 -------------------
 .../james/rrt/lib/ThrowingRewriterTest.java     | 38 ++++++++++++++++++++
 .../rrt/lib/AbstractRecipientRewriteTable.java  |  3 --
 .../mailets/AbstractRecipientRewriteTable.java  |  3 ++
 6 files changed, 51 insertions(+), 45 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/6a5b348d/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
index 7f0e684..7795014 100644
--- a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
@@ -29,6 +29,7 @@ import javax.mail.internet.AddressException;
 import org.apache.james.core.Domain;
 import org.apache.james.core.MailAddress;
 import org.apache.james.core.User;
+import org.apache.james.rrt.api.RecipientRewriteTable;
 import org.apache.james.rrt.api.RecipientRewriteTableException;
 
 import com.google.common.base.Objects;
@@ -55,7 +56,7 @@ public interface Mapping {
             case Domain:
                 return new UserRewritter.DomainRewriter();
             case Error:
-                return new UserRewritter.NoneRewriter();
+                return new UserRewritter.ThrowingRewriter();
             case Forward:
             case Group:
             case Address:
@@ -276,7 +277,7 @@ public interface Mapping {
         }
 
         @Override
-        public Optional<User> rewriteUser(User user) throws AddressException {
+        public Optional<User> rewriteUser(User user) throws AddressException, RecipientRewriteTable.ErrorMappingException {
             return rewriter.rewrite(user);
         }
 
@@ -328,6 +329,6 @@ public interface Mapping {
 
     String getErrorMessage();
 
-    Optional<User> rewriteUser(User user) throws AddressException;
+    Optional<User> rewriteUser(User user) throws AddressException, RecipientRewriteTable.ErrorMappingException;
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/6a5b348d/server/data/data-api/src/main/java/org/apache/james/rrt/lib/UserRewritter.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/UserRewritter.java b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/UserRewritter.java
index df97d17..b9e96de 100644
--- a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/UserRewritter.java
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/UserRewritter.java
@@ -31,6 +31,7 @@ import javax.mail.internet.AddressException;
 import org.apache.james.core.Domain;
 import org.apache.james.core.MailAddress;
 import org.apache.james.core.User;
+import org.apache.james.rrt.api.RecipientRewriteTable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -41,7 +42,7 @@ import com.google.common.collect.ImmutableList;
 @FunctionalInterface
 public interface UserRewritter {
 
-    Optional<User> rewrite(User user) throws AddressException;
+    Optional<User> rewrite(User user) throws AddressException, RecipientRewriteTable.ErrorMappingException;
 
     interface MappingUserRewriter {
         UserRewritter generateUserRewriter(String mapping);
@@ -65,10 +66,12 @@ public interface UserRewritter {
         }
     }
 
-    class NoneRewriter implements MappingUserRewriter {
+    class ThrowingRewriter implements MappingUserRewriter {
         @Override
         public UserRewritter generateUserRewriter(String mapping) {
-            return oldUser -> Optional.empty();
+            return user -> {
+                throw new RecipientRewriteTable.ErrorMappingException(mapping);
+            };
         }
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/6a5b348d/server/data/data-api/src/test/java/org/apache/james/rrt/lib/NoneRewiterTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/test/java/org/apache/james/rrt/lib/NoneRewiterTest.java b/server/data/data-api/src/test/java/org/apache/james/rrt/lib/NoneRewiterTest.java
deleted file mode 100644
index c1cdd8c..0000000
--- a/server/data/data-api/src/test/java/org/apache/james/rrt/lib/NoneRewiterTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.rrt.lib;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import org.apache.james.core.User;
-import org.junit.jupiter.api.Test;
-
-public class NoneRewiterTest {
-    @Test
-    public void rewriteShouldReturnEmpty() throws Exception {
-        assertThat(
-            new UserRewritter.NoneRewriter()
-                .generateUserRewriter("any")
-                .rewrite(User.fromUsername("any")))
-            .isEmpty();
-    }
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/6a5b348d/server/data/data-api/src/test/java/org/apache/james/rrt/lib/ThrowingRewriterTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/test/java/org/apache/james/rrt/lib/ThrowingRewriterTest.java b/server/data/data-api/src/test/java/org/apache/james/rrt/lib/ThrowingRewriterTest.java
new file mode 100644
index 0000000..8bcf06e
--- /dev/null
+++ b/server/data/data-api/src/test/java/org/apache/james/rrt/lib/ThrowingRewriterTest.java
@@ -0,0 +1,38 @@
+/****************************************************************
+ * 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 static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.apache.james.core.User;
+import org.apache.james.rrt.api.RecipientRewriteTable;
+import org.junit.jupiter.api.Test;
+
+public class ThrowingRewriterTest {
+    @Test
+    public void rewriteShouldReturnEmpty() throws Exception {
+        assertThatThrownBy(() ->
+            new UserRewritter.ThrowingRewriter()
+                .generateUserRewriter("any")
+                .rewrite(User.fromUsername("any")))
+            .isInstanceOf(RecipientRewriteTable.ErrorMappingException.class);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/6a5b348d/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
index 4a22f4b..b842dc7 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
@@ -110,9 +110,6 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
 
         Mappings targetMappings = mapAddress(user.getLocalPart(), user.getDomainPart().get());
 
-        if (targetMappings.contains(Type.Error)) {
-            throw new ErrorMappingException(targetMappings.getError().getErrorMessage());
-        }
 
         try {
             return MappingsImpl.fromMappings(

http://git-wip-us.apache.org/repos/asf/james-project/blob/6a5b348d/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/AbstractRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/AbstractRecipientRewriteTable.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/AbstractRecipientRewriteTable.java
index 94b9794..391da56 100755
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/AbstractRecipientRewriteTable.java
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/AbstractRecipientRewriteTable.java
@@ -38,6 +38,7 @@ import org.apache.james.core.User;
 import org.apache.james.dnsservice.api.DNSService;
 import org.apache.james.domainlist.api.DomainList;
 import org.apache.james.domainlist.api.DomainListException;
+import org.apache.james.rrt.api.RecipientRewriteTable;
 import org.apache.james.rrt.lib.Mapping;
 import org.apache.james.rrt.lib.UserRewritter;
 import org.apache.james.server.core.MailImpl;
@@ -129,6 +130,8 @@ public abstract class AbstractRecipientRewriteTable extends GenericMailet {
                                 targetAddress = maybeTarget.get();
                             } catch (PatternSyntaxException e) {
                                 LOGGER.error("Exception during regexMap processing: ", e);
+                            } catch (RecipientRewriteTable.ErrorMappingException e) {
+                                LOGGER.error("Regex mapping should not throw ErrorMappingException", e);
                             }
                         }
 


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


[03/27] james-project git commit: JAMES-2366 reduce getMappings method scope to private

Posted by ma...@apache.org.
JAMES-2366 reduce getMappings method scope to private


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

Branch: refs/heads/master
Commit: e2c0bcdb036197fd47ad5af956be2ecec267e3a8
Parents: 6a5b348
Author: Matthieu Baechler <ma...@apache.org>
Authored: Wed Apr 18 15:41:54 2018 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:45:26 2018 +0200

----------------------------------------------------------------------
 .../org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/e2c0bcdb/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
index b842dc7..21066af 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
@@ -100,7 +100,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
         return getMappings(User.fromLocalPartWithDomain(user, domain), mappingLimit);
     }
 
-    public Mappings getMappings(User user, int mappingLimit) throws ErrorMappingException, RecipientRewriteTableException {
+    private Mappings getMappings(User user, int mappingLimit) throws ErrorMappingException, RecipientRewriteTableException {
 
         // We have to much mappings throw ErrorMappingException to avoid
         // infinity loop


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


[19/27] james-project git commit: JAMES-2366 remove a duplicate condition in mappings logic

Posted by ma...@apache.org.
JAMES-2366 remove a duplicate condition in mappings logic


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

Branch: refs/heads/master
Commit: 949594cfd6ba6414ba885649acf1c40b96caee4a
Parents: f8c43ad
Author: Matthieu Baechler <ma...@apache.org>
Authored: Tue Apr 17 15:00:27 2018 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:45:26 2018 +0200

----------------------------------------------------------------------
 .../rrt/lib/AbstractRecipientRewriteTable.java  | 93 +++++++++-----------
 1 file changed, 44 insertions(+), 49 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/949594cf/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
index 69370c6..7249250 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
@@ -107,66 +107,61 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
 
         Mappings targetMappings = mapAddress(user, domain);
 
-        // Only non-null mappings are translated
-        if (!targetMappings.isEmpty()) {
-            if (targetMappings.contains(Type.Error)) {
-                throw new ErrorMappingException(targetMappings.getError().getErrorMessage());
-            } else {
-                MappingsImpl.Builder mappings = MappingsImpl.builder();
-
-                for (String target : targetMappings.asStrings()) {
-                    Type type = Mapping.detectType(target);
-                    Optional<String> maybeAddressWithMappingApplied = applyMapping(user, domain, target, type);
-
-                    if (!maybeAddressWithMappingApplied.isPresent()) {
-                        continue;
-                    }
-                    String addressWithMappingApplied = maybeAddressWithMappingApplied.get();
-                    LOGGER.debug("Valid virtual user mapping {}@{} to {}", user, domain.name(), addressWithMappingApplied);
-
-                    if (recursive) {
-
-                        String userName;
-                        Domain targetDomain;
-                        String[] args = addressWithMappingApplied.split("@");
-
-                        if (args.length > 1) {
-                            userName = args[0];
-                            targetDomain = Domain.of(args[1]);
-                        } else {
-                            // TODO Is that the right todo here?
-                            userName = addressWithMappingApplied;
-                            targetDomain = domain;
-                        }
+        if (targetMappings.contains(Type.Error)) {
+            throw new ErrorMappingException(targetMappings.getError().getErrorMessage());
+        } else {
+            MappingsImpl.Builder mappings = MappingsImpl.builder();
 
-                        // Check if the returned mapping is the same as the
-                        // input. If so return null to avoid loops
-                        if (userName.equalsIgnoreCase(user) && targetDomain.equals(domain)) {
-                            if (type.equals(Type.Forward)) {
-                                mappings.add(toMapping(addressWithMappingApplied, type));
-                                continue;
-                            }
-                            return MappingsImpl.empty();
-                        }
+            for (String target : targetMappings.asStrings()) {
+                Type type = Mapping.detectType(target);
+                Optional<String> maybeAddressWithMappingApplied = applyMapping(user, domain, target, type);
+
+                if (!maybeAddressWithMappingApplied.isPresent()) {
+                    continue;
+                }
+                String addressWithMappingApplied = maybeAddressWithMappingApplied.get();
+                LOGGER.debug("Valid virtual user mapping {}@{} to {}", user, domain.name(), addressWithMappingApplied);
+
+                if (recursive) {
 
-                        Mappings childMappings = getMappings(userName, targetDomain, mappingLimit - 1);
+                    String userName;
+                    Domain targetDomain;
+                    String[] args = addressWithMappingApplied.split("@");
 
-                        if (childMappings.isEmpty()) {
-                            // add mapping
+                    if (args.length > 1) {
+                        userName = args[0];
+                        targetDomain = Domain.of(args[1]);
+                    } else {
+                        // TODO Is that the right todo here?
+                        userName = addressWithMappingApplied;
+                        targetDomain = domain;
+                    }
+
+                    // Check if the returned mapping is the same as the
+                    // input. If so return null to avoid loops
+                    if (userName.equalsIgnoreCase(user) && targetDomain.equals(domain)) {
+                        if (type.equals(Type.Forward)) {
                             mappings.add(toMapping(addressWithMappingApplied, type));
-                        } else {
-                            mappings = mappings.addAll(childMappings);
+                            continue;
                         }
+                        return MappingsImpl.empty();
+                    }
 
-                    } else {
+                    Mappings childMappings = getMappings(userName, targetDomain, mappingLimit - 1);
+
+                    if (childMappings.isEmpty()) {
+                        // add mapping
                         mappings.add(toMapping(addressWithMappingApplied, type));
+                    } else {
+                        mappings = mappings.addAll(childMappings);
                     }
+
+                } else {
+                    mappings.add(toMapping(addressWithMappingApplied, type));
                 }
-                return mappings.build();
             }
+            return mappings.build();
         }
-
-        return MappingsImpl.empty();
     }
 
     private Mapping toMapping(String mappedAddress, Type type) {


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


[27/27] james-project git commit: JAMES-2366 migration RegexRewriterTest to junit 5

Posted by ma...@apache.org.
JAMES-2366 migration RegexRewriterTest to junit 5


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

Branch: refs/heads/master
Commit: f0ce9cc7d8dda486628f5bd8140a8626a77bfe85
Parents: a7a8735
Author: Matthieu Baechler <ma...@apache.org>
Authored: Fri Apr 20 15:14:22 2018 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:49:33 2018 +0200

----------------------------------------------------------------------
 .../apache/james/rrt/lib/RegexRewriterTest.java | 21 ++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/f0ce9cc7/server/data/data-api/src/test/java/org/apache/james/rrt/lib/RegexRewriterTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/test/java/org/apache/james/rrt/lib/RegexRewriterTest.java b/server/data/data-api/src/test/java/org/apache/james/rrt/lib/RegexRewriterTest.java
index b8682a3..30be389 100644
--- a/server/data/data-api/src/test/java/org/apache/james/rrt/lib/RegexRewriterTest.java
+++ b/server/data/data-api/src/test/java/org/apache/james/rrt/lib/RegexRewriterTest.java
@@ -27,56 +27,57 @@ import java.util.regex.PatternSyntaxException;
 import org.apache.james.core.MailAddress;
 import org.junit.jupiter.api.Test;
 
-public class RegexRewriterTest {
+class RegexRewriterTest {
+    
     @Test
-    public void regexMapShouldCorrectlyReplaceMatchingUsername() throws Exception {
+    void regexMapShouldCorrectlyReplaceMatchingUsername() throws Exception {
         MailAddress mailAddress = new MailAddress("prefix_abc@test");
         assertThat(new UserRewritter.RegexRewriter().regexMap(mailAddress,"prefix_.*:admin@test"))
             .contains("admin@test");
     }
 
     @Test
-    public void regexMapShouldThrowOnNullAddress() throws Exception {
+    void regexMapShouldThrowOnNullAddress() throws Exception {
         MailAddress address = null;
         assertThatThrownBy(() -> new UserRewritter.RegexRewriter().regexMap(address, "prefix_.*:admin@test"))
             .isInstanceOf(NullPointerException.class);
     }
 
     @Test
-    public void regexMapShouldThrowOnNullRegexMapping() throws Exception {
+    void regexMapShouldThrowOnNullRegexMapping() throws Exception {
         String regexMapping = null;
         assertThatThrownBy(() -> new UserRewritter.RegexRewriter().regexMap(new MailAddress("abc@test"), regexMapping))
             .isInstanceOf(NullPointerException.class);
     }
 
     @Test
-    public void regexMapShouldThrowOnInvalidSyntax() throws Exception {
+    void regexMapShouldThrowOnInvalidSyntax() throws Exception {
         assertThatThrownBy(() -> new UserRewritter.RegexRewriter().regexMap(new MailAddress("abc@test"), "singlepart"))
             .isInstanceOf(PatternSyntaxException.class);
     }
 
     @Test
-    public void regexMapShouldReturnInputWhenRegexDoesntMatch() throws Exception {
+    void regexMapShouldReturnInputWhenRegexDoesntMatch() throws Exception {
         assertThat(new UserRewritter.RegexRewriter().regexMap(new MailAddress("abc@test"), "notmatching:notreplaced"))
             .isEmpty();
     }
 
     @Test
-    public void regexMapShouldCorrectlyReplaceMatchingGroups() throws Exception {
+    void regexMapShouldCorrectlyReplaceMatchingGroups() throws Exception {
         MailAddress mailAddress = new MailAddress("prefix_abc@test");
         assertThat(new UserRewritter.RegexRewriter().regexMap(mailAddress, "prefix_(.*)@test:admin@${1}"))
             .contains("admin@abc");
     }
 
     @Test
-    public void regexMapShouldCorrectlyReplaceSeveralMatchingGroups() throws Exception {
+    void regexMapShouldCorrectlyReplaceSeveralMatchingGroups() throws Exception {
         MailAddress mailAddress = new MailAddress("prefix_abc_def@test");
         assertThat(new UserRewritter.RegexRewriter().regexMap(mailAddress, "prefix_(.*)_(.*)@test:admin@${1}.${2}"))
             .contains("admin@abc.def");
     }
 
     @Test
-    public void regexMapShouldCorrectlyReplaceSeveralOutOfOrderMatchingGroups() throws Exception {
+    void regexMapShouldCorrectlyReplaceSeveralOutOfOrderMatchingGroups() throws Exception {
         MailAddress mailAddress = new MailAddress("prefix_abc_def@test");
         assertThat(new UserRewritter.RegexRewriter().regexMap(mailAddress, "prefix_(.*)_(.*)@test:admin@${2}.${1}"))
             .contains("admin@def.abc");
@@ -84,7 +85,7 @@ public class RegexRewriterTest {
 
 
     @Test
-    public void regexMapShouldCorrectlyReplaceRepeatingMatchingGroups() throws Exception {
+    void regexMapShouldCorrectlyReplaceRepeatingMatchingGroups() throws Exception {
         MailAddress mailAddress = new MailAddress("prefix_abc_def@test");
         assertThat(new UserRewritter.RegexRewriter().regexMap(mailAddress, "prefix_(.*)_(.*)@test:admin@${1}.${1}"))
             .contains("admin@abc.abc");


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


[07/27] james-project git commit: JAMES-2366 Rely more on Strong typing and better extract methods

Posted by ma...@apache.org.
JAMES-2366 Rely more on Strong typing and better extract 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/8947eeea
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/8947eeea
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/8947eeea

Branch: refs/heads/master
Commit: 8947eeea67c2aa4f83c74a3415043cb02cb7f0bd
Parents: a71d033
Author: benwa <bt...@linagora.com>
Authored: Wed Apr 18 09:40:07 2018 +0700
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:45:26 2018 +0200

----------------------------------------------------------------------
 .../main/java/org/apache/james/core/User.java   |  7 +++
 .../rrt/lib/AbstractRecipientRewriteTable.java  | 51 +++++++++++---------
 2 files changed, 34 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/8947eeea/core/src/main/java/org/apache/james/core/User.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/james/core/User.java b/core/src/main/java/org/apache/james/core/User.java
index 8b5421e..a3f07ff 100644
--- a/core/src/main/java/org/apache/james/core/User.java
+++ b/core/src/main/java/org/apache/james/core/User.java
@@ -23,6 +23,8 @@ import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
 
+import javax.mail.internet.AddressException;
+
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Splitter;
@@ -101,6 +103,11 @@ public class User {
             .orElse(localPart);
     }
 
+    public MailAddress asMailAddress() throws AddressException {
+        Preconditions.checkState(hasDomainPart());
+        return new MailAddress(localPart, domainPart.get());
+    }
+
     @Override
     public final boolean equals(Object o) {
         if (o instanceof User) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/8947eeea/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
index 23c60c2..f5da229 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
@@ -20,6 +20,7 @@ package org.apache.james.rrt.lib;
 
 import java.util.Map;
 import java.util.Optional;
+import java.util.function.Function;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 import java.util.stream.Stream;
@@ -30,7 +31,6 @@ import javax.mail.internet.AddressException;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.commons.configuration.HierarchicalConfiguration;
 import org.apache.james.core.Domain;
-import org.apache.james.core.MailAddress;
 import org.apache.james.core.User;
 import org.apache.james.domainlist.api.DomainList;
 import org.apache.james.domainlist.api.DomainListException;
@@ -97,10 +97,10 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
 
     @Override
     public Mappings getMappings(String user, Domain domain) throws ErrorMappingException, RecipientRewriteTableException {
-        return getMappings(user, domain, mappingLimit);
+        return getMappings(User.fromLocalPartWithDomain(user, domain), mappingLimit);
     }
 
-    public Mappings getMappings(String user, Domain domain, int mappingLimit) throws ErrorMappingException, RecipientRewriteTableException {
+    public Mappings getMappings(User user, int mappingLimit) throws ErrorMappingException, RecipientRewriteTableException {
 
         // We have to much mappings throw ErrorMappingException to avoid
         // infinity loop
@@ -108,7 +108,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
             throw new ErrorMappingException("554 Too many mappings to process");
         }
 
-        Mappings targetMappings = mapAddress(user, domain);
+        Mappings targetMappings = mapAddress(user.getLocalPart(), user.getDomainPart().get());
 
         if (targetMappings.contains(Type.Error)) {
             throw new ErrorMappingException(targetMappings.getError().getErrorMessage());
@@ -117,7 +117,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
         try {
             return MappingsImpl.fromMappings(
                 targetMappings.asStream()
-                    .flatMap(Throwing.<Mapping, Stream<Mapping>>function(target -> convertAndRecurseMapping(target, user, domain, mappingLimit)).sneakyThrow()));
+                    .flatMap(Throwing.<Mapping, Stream<Mapping>>function(target -> convertAndRecurseMapping(user, target, mappingLimit)).sneakyThrow()));
         } catch (EmptyMappingException e) {
             return MappingsImpl.empty();
         }
@@ -127,39 +127,42 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
 
     }
 
-    private Stream<Mapping> convertAndRecurseMapping(Mapping target, String user, Domain domain, int remainingLoops) throws ErrorMappingException, RecipientRewriteTableException, EmptyMappingException, AddressException {
-        Optional<String> maybeAddressWithMappingApplied = target.apply(new MailAddress(user, domain));
+    private Stream<Mapping> convertAndRecurseMapping(User user, Mapping associatedMapping, int remainingLoops) throws ErrorMappingException, RecipientRewriteTableException, EmptyMappingException, AddressException {
 
-        if (!maybeAddressWithMappingApplied.isPresent()) {
-            return Stream.empty();
-        }
-        String addressWithMappingApplied = maybeAddressWithMappingApplied.get();
-        LOGGER.debug("Valid virtual user mapping {}@{} to {}", user, domain.name(), addressWithMappingApplied);
+        Function<String, Stream<Mapping>> convertAndRecurseMapping =
+            Throwing
+                .function((String stringMapping) -> convertAndRecurseMapping(associatedMapping.getType(), user, remainingLoops, stringMapping))
+                .sneakyThrow();
+
+        return associatedMapping.apply(user.asMailAddress())
+            .map(convertAndRecurseMapping)
+            .orElse(Stream.empty());
+    }
 
+    private Stream<Mapping> convertAndRecurseMapping(Type mappingType, User originalUser, int remainingLoops, String addressWithMappingApplied) throws ErrorMappingException, RecipientRewriteTableException {
+        LOGGER.debug("Valid virtual user mapping {} to {}", originalUser, addressWithMappingApplied);
+
+        Stream<Mapping> nonRecursiveResult = Stream.of(toMapping(addressWithMappingApplied, mappingType));
         if (!recursive) {
-            return Stream.of(toMapping(addressWithMappingApplied, target.getType()));
+            return nonRecursiveResult;
         }
 
-        User coreUser = User.fromUsername(addressWithMappingApplied)
-            .withDefaultDomain(domain);
-
-        String userName = coreUser.getLocalPart();
-        Domain targetDomain = coreUser.getDomainPart().get();
+        User targetUser = User.fromUsername(addressWithMappingApplied)
+            .withDefaultDomain(originalUser.getDomainPart().get());
 
         // Check if the returned mapping is the same as the
         // input. If so return null to avoid loops
-        if (userName.equalsIgnoreCase(user) && targetDomain.equals(domain)) {
-            if (target.getType().equals(Type.Forward)) {
-                return Stream.of(toMapping(addressWithMappingApplied, target.getType()));
+        if (originalUser.equals(targetUser)) {
+            if (mappingType.equals(Type.Forward)) {
+                return nonRecursiveResult;
             }
-            //throw exception ?
             throw new EmptyMappingException();
         }
 
-        Mappings childMappings = getMappings(userName, targetDomain, remainingLoops - 1);
+        Mappings childMappings = getMappings(targetUser, remainingLoops - 1);
 
         if (childMappings.isEmpty()) {
-            return Stream.of(toMapping(addressWithMappingApplied, target.getType()));
+            return nonRecursiveResult;
         } else {
             return childMappings.asStream();
         }


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


[14/27] james-project git commit: JAMES-2366 regexMap no longer use null but Optional

Posted by ma...@apache.org.
JAMES-2366 regexMap no longer use null but Optional


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

Branch: refs/heads/master
Commit: 465da0e1196c147790878cc876df5a577de336b4
Parents: 620bf69
Author: Matthieu Baechler <ma...@apache.org>
Authored: Tue Apr 17 16:32:11 2018 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:45:26 2018 +0200

----------------------------------------------------------------------
 .../james/rrt/lib/AbstractRecipientRewriteTable.java      |  2 +-
 .../apache/james/rrt/lib/RecipientRewriteTableUtil.java   |  6 +++---
 .../transport/mailets/AbstractRecipientRewriteTable.java  | 10 ++++++----
 3 files changed, 10 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/465da0e1/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
index 8fb522e..80d526d 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
@@ -182,7 +182,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
         switch (type) {
             case Regex:
                 try {
-                    return Optional.ofNullable(RecipientRewriteTableUtil.regexMap(new MailAddress(user, domain.asString()), MappingImpl.of(target)));
+                    return RecipientRewriteTableUtil.regexMap(new MailAddress(user, domain.asString()), MappingImpl.of(target));
                 } catch (PatternSyntaxException | ParseException e) {
                     LOGGER.error("Exception during regexMap processing: ", e);
                     return Optional.ofNullable(target);

http://git-wip-us.apache.org/repos/asf/james-project/blob/465da0e1/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableUtil.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableUtil.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableUtil.java
index d849a8b..f711178 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableUtil.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableUtil.java
@@ -57,7 +57,7 @@ public class RecipientRewriteTableUtil {
      * formatted as regex:<regular-expression>:<parameterized-string>, e.g.,
      * regex:(.*)@(.*):${1}@tld
      */
-    public static String regexMap(MailAddress address, Mapping mapping) {
+    public static Optional<String> regexMap(MailAddress address, Mapping mapping) {
         Preconditions.checkArgument(mapping.getType() == Type.Regex);
 
         List<String> parts = Splitter.on(':').splitToList(mapping.asString());
@@ -70,9 +70,9 @@ public class RecipientRewriteTableUtil {
 
         if (match.matches()) {
             ImmutableList<String> parameters = listMatchingGroups(match);
-            return replaceParameters(parts.get(PARAMETERIZED_STRING), parameters);
+            return Optional.of(replaceParameters(parts.get(PARAMETERIZED_STRING), parameters));
         }
-        return null;
+        return Optional.empty();
     }
 
     private static ImmutableList<String> listMatchingGroups(Matcher match) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/465da0e1/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/AbstractRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/AbstractRecipientRewriteTable.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/AbstractRecipientRewriteTable.java
index 1efb4c1..3d4c9ee 100755
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/AbstractRecipientRewriteTable.java
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/AbstractRecipientRewriteTable.java
@@ -25,6 +25,7 @@ import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
+import java.util.Optional;
 import java.util.StringTokenizer;
 import java.util.regex.PatternSyntaxException;
 
@@ -117,13 +118,14 @@ public abstract class AbstractRecipientRewriteTable extends GenericMailet {
 
                         if (targetAddress.startsWith("regex:")) {
                             try {
-                                targetAddress = RecipientRewriteTableUtil.regexMap(source, MappingImpl.of(targetAddress));
+                                Optional<String> maybeTarget = RecipientRewriteTableUtil.regexMap(source, MappingImpl.of(targetAddress));
+                                if (!maybeTarget.isPresent()) {
+                                    continue;
+                                }
+                                targetAddress = maybeTarget.get();
                             } catch (PatternSyntaxException e) {
                                 LOGGER.error("Exception during regexMap processing: ", e);
                             }
-                            if (targetAddress == null) {
-                                continue;
-                            }
                         }
 
                         try {


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


[06/27] james-project git commit: JAMES-2366 Storage of group prefixed mappings

Posted by ma...@apache.org.
JAMES-2366 Storage of group prefixed mappings


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

Branch: refs/heads/master
Commit: 7208b3ced11625d3c79ddc5677faa9c1e660fde8
Parents: 43a6882
Author: benwa <bt...@linagora.com>
Authored: Fri Apr 6 11:28:06 2018 +0700
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:45:26 2018 +0200

----------------------------------------------------------------------
 .../james/rrt/api/RecipientRewriteTable.java    |  4 +++
 .../rrt/lib/AbstractRecipientRewriteTable.java  | 21 ++++++++++++++
 .../user/lib/AbstractJamesUsersRepository.java  | 10 +++++++
 .../lib/AbstractRecipientRewriteTableTest.java  | 30 ++++++++++++++++++++
 .../james/rrt/lib/RewriteTablesStepdefs.java    | 10 +++++++
 .../resources/cucumber/rewrite_tables.feature   | 24 +++++++++++++++-
 6 files changed, 98 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/7208b3ce/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 92c803d..e2e7315 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
@@ -212,6 +212,10 @@ public interface RecipientRewriteTable {
 
     void removeForwardMapping(String user, Domain domain, String address) throws RecipientRewriteTableException;
 
+    void addGroupMapping(String user, Domain domain, String address) throws RecipientRewriteTableException;
+
+    void removeGroupMapping(String user, Domain domain, String address) throws RecipientRewriteTableException;
+
     class ErrorMappingException extends Exception {
 
         private static final long serialVersionUID = 2348752938798L;

http://git-wip-us.apache.org/repos/asf/james-project/blob/7208b3ce/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
index 2586f37..134f57c 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
@@ -308,6 +308,27 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
         removeMapping(user, domain, mapping);
     }
 
+    @Override
+    public void addGroupMapping(String user, Domain domain, String address) throws RecipientRewriteTableException {
+        Mapping mapping = MappingImpl.group(address)
+            .appendDomainFromThrowingSupplierIfNone(this::defaultDomain);
+
+        checkHasValidAddress(mapping);
+        checkMapping(user, domain, mapping);
+
+        LOGGER.info("Add forward mapping => {} for user: {} domain: {}", mapping, user, domain.name());
+        addMapping(user, domain, mapping);
+    }
+
+    @Override
+    public void removeGroupMapping(String user, Domain domain, String address) throws RecipientRewriteTableException {
+        Mapping mapping = MappingImpl.group(address)
+            .appendDomainFromThrowingSupplierIfNone(this::defaultDomain);
+
+        LOGGER.info("Remove forward mapping => {} for user: {} domain: {}", mapping, user, domain.name());
+        removeMapping(user, domain, mapping);
+    }
+
     /**
      * Return a Map which holds all Mappings
      * 

http://git-wip-us.apache.org/repos/asf/james-project/blob/7208b3ce/server/data/data-library/src/main/java/org/apache/james/user/lib/AbstractJamesUsersRepository.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/user/lib/AbstractJamesUsersRepository.java b/server/data/data-library/src/main/java/org/apache/james/user/lib/AbstractJamesUsersRepository.java
index 6328ed3..3f9c4d3 100644
--- a/server/data/data-library/src/main/java/org/apache/james/user/lib/AbstractJamesUsersRepository.java
+++ b/server/data/data-library/src/main/java/org/apache/james/user/lib/AbstractJamesUsersRepository.java
@@ -276,4 +276,14 @@ public abstract class AbstractJamesUsersRepository extends AbstractUsersReposito
     public void removeForwardMapping(String user, Domain domain, String address) throws RecipientRewriteTableException {
         throw new RecipientRewriteTableException("Read-Only RecipientRewriteTable");
     }
+
+    @Override
+    public void addGroupMapping(String user, Domain domain, String address) throws RecipientRewriteTableException {
+        throw new RecipientRewriteTableException("Read-Only RecipientRewriteTable");
+    }
+
+    @Override
+    public void removeGroupMapping(String user, Domain domain, String address) throws RecipientRewriteTableException {
+        throw new RecipientRewriteTableException("Read-Only RecipientRewriteTable");
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/7208b3ce/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 6ce90e4..84f204d 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
@@ -311,4 +311,34 @@ public abstract class AbstractRecipientRewriteTableTest {
         assertThat(virtualUserTable.getMappings(user, domain))
             .isEqualTo(MappingsImpl.empty());
     }
+
+    @Test
+    public void addGroupMappingShouldStore() throws ErrorMappingException, RecipientRewriteTableException {
+        String user = "test";
+        Domain domain = Domain.LOCALHOST;
+        String address = "test@localhost2";
+        String address2 = "test@james";
+
+        virtualUserTable.addMapping(user, domain, MappingImpl.group(address));
+        virtualUserTable.addMapping(user, domain, MappingImpl.group(address2));
+
+        assertThat(virtualUserTable.getMappings(user, domain)).hasSize(2);
+    }
+
+    @Test
+    public void removeGroupMappingShouldDelete() throws ErrorMappingException, RecipientRewriteTableException {
+        String user = "test";
+        Domain domain = Domain.LOCALHOST;
+        String address = "test@localhost2";
+        String address2 = "test@james";
+
+        virtualUserTable.addMapping(user, domain, MappingImpl.group(address));
+        virtualUserTable.addMapping(user, domain, MappingImpl.group(address2));
+
+        virtualUserTable.removeMapping(user, domain, MappingImpl.group(address));
+        virtualUserTable.removeMapping(user, domain, MappingImpl.group(address2));
+
+        assertThat(virtualUserTable.getMappings(user, domain))
+            .isEqualTo(MappingsImpl.empty());
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/7208b3ce/server/data/data-library/src/test/java/org/apache/james/rrt/lib/RewriteTablesStepdefs.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/test/java/org/apache/james/rrt/lib/RewriteTablesStepdefs.java b/server/data/data-library/src/test/java/org/apache/james/rrt/lib/RewriteTablesStepdefs.java
index c274bc1..bd888ca 100644
--- a/server/data/data-library/src/test/java/org/apache/james/rrt/lib/RewriteTablesStepdefs.java
+++ b/server/data/data-library/src/test/java/org/apache/james/rrt/lib/RewriteTablesStepdefs.java
@@ -76,6 +76,11 @@ public class RewriteTablesStepdefs {
         rewriteTable.addForwardMapping(user, Domain.of(domain), address);
     }
 
+    @Given("store \"([^\"]*)\" group mapping for user \"([^\"]*)\" at domain \"([^\"]*)\"")
+    public void storeGroupMappingForUserAtDomain(String address, String user, String domain) throws Throwable {
+        rewriteTable.addGroupMapping(user, Domain.of(domain), address);
+    }
+
     @Given("recursive mapping is disable")
     public void disableRecursiveMapping() {
         rewriteTable.setRecursiveMapping(false);
@@ -106,6 +111,11 @@ public class RewriteTablesStepdefs {
         rewriteTable.removeForwardMapping(user, Domain.of(domain), address);
     }
 
+    @When("user \"([^\"]*)\" at domain \"([^\"]*)\" removes a group mapping \"([^\"]*)\"")
+    public void userAtDomainRemovesGroupMapping(String user, String domain, String address) throws Throwable {
+        rewriteTable.removeGroupMapping(user, Domain.of(domain), address);
+    }
+
     @When("wildcard address mapping \"([^\"]*)\" at domain \"([^\"]*)\" is removed")
     public void removeWildcardAddressMappingAtDomain(String address, String domain) throws Throwable {
         userAtDomainRemovesAddressMapping(RecipientRewriteTable.WILDCARD, domain, address);

http://git-wip-us.apache.org/repos/asf/james-project/blob/7208b3ce/server/data/data-library/src/test/resources/cucumber/rewrite_tables.feature
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/test/resources/cucumber/rewrite_tables.feature b/server/data/data-library/src/test/resources/cucumber/rewrite_tables.feature
index 03d4c55..16be5f1 100644
--- a/server/data/data-library/src/test/resources/cucumber/rewrite_tables.feature
+++ b/server/data/data-library/src/test/resources/cucumber/rewrite_tables.feature
@@ -240,4 +240,26 @@ Feature: Rewrite Tables tests
     Given store "test@localhost2" forward mapping for user "test" at domain "localhost"
     And store "test@james" forward mapping for user "test" at domain "localhost"
     When user "test" at domain "localhost" removes a forward mapping "test@james"
-    Then mappings for user "test" at domain "localhost" should contain only "forward:test@localhost2"
\ No newline at end of file
+    Then mappings for user "test" at domain "localhost" should contain only "forward:test@localhost2"
+
+# Group mapping
+
+  Scenario: stored group mapping should be retrieved when one mapping is matching
+    Given store "test@localhost2" group mapping for user "test" at domain "localhost"
+    Then mappings for user "test" at domain "localhost" should contain only "group:test@localhost2"
+
+  Scenario: stored group mapping should be retrieved when two mappings are matching
+    Given store "test@localhost2" group mapping for user "test" at domain "localhost"
+    And store "test@james" group mapping for user "test" at domain "localhost"
+    Then mappings for user "test" at domain "localhost" should contain only "group:test@localhost2, group:test@james"
+
+  Scenario: stored group mapping should not be retrieved by another user
+    Given store "test@localhost2" group mapping for user "test" at domain "localhost"
+    And store "test@james" group mapping for user "test" at domain "localhost"
+    Then mappings for user "test2" at domain "localhost" should be empty
+
+  Scenario: removing a stored group mapping should work
+    Given store "test@localhost2" group mapping for user "test" at domain "localhost"
+    And store "test@james" group mapping for user "test" at domain "localhost"
+    When user "test" at domain "localhost" removes a group mapping "test@james"
+    Then mappings for user "test" at domain "localhost" should contain only "group:test@localhost2"
\ 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


[24/27] james-project git commit: JAMES-2366 use an object MappingSource for input of RRT rewriting

Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableManagement.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableManagement.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableManagement.java
index 14aa1c8..9ee4bb5 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableManagement.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableManagement.java
@@ -29,7 +29,7 @@ import org.apache.james.rrt.api.RecipientRewriteTable;
 import org.apache.james.rrt.api.RecipientRewriteTableException;
 import org.apache.james.rrt.api.RecipientRewriteTableManagementMBean;
 
-import com.google.common.collect.ImmutableMap;
+import com.github.steveash.guavate.Guavate;
 
 /**
  * Management for RecipientRewriteTables
@@ -46,89 +46,102 @@ public class RecipientRewriteTableManagement extends StandardMBean implements Re
 
     @Override
     public void addRegexMapping(String user, String domain, String regex) throws RecipientRewriteTableException {
-        rrt.addRegexMapping(user, Domain.of(domain), regex);
+        MappingSource source = MappingSource.fromUser(user, domain);
+        rrt.addRegexMapping(source, regex);
     }
 
     @Override
     public void removeRegexMapping(String user, String domain, String regex) throws RecipientRewriteTableException {
-        rrt.removeRegexMapping(user, Domain.of(domain), regex);
+        MappingSource source = MappingSource.fromUser(user, domain);
+        rrt.removeRegexMapping(source, regex);
     }
 
     @Override
     public void addAddressMapping(String user, String domain, String address) throws RecipientRewriteTableException {
-        rrt.addAddressMapping(user, Domain.of(domain), address);
+        MappingSource source = MappingSource.fromUser(user, domain);
+        rrt.addAddressMapping(source, address);
     }
 
     @Override
     public void removeAddressMapping(String user, String domain, String address) throws RecipientRewriteTableException {
-        rrt.removeAddressMapping(user, Domain.of(domain), address);
+        MappingSource source = MappingSource.fromUser(user, domain);
+        rrt.removeAddressMapping(source, address);
     }
 
     @Override
     public void addErrorMapping(String user, String domain, String error) throws RecipientRewriteTableException {
-        rrt.addErrorMapping(user, Domain.of(domain), error);
+        MappingSource source = MappingSource.fromUser(user, domain);
+        rrt.addErrorMapping(source, error);
     }
 
     @Override
     public void removeErrorMapping(String user, String domain, String error) throws RecipientRewriteTableException {
-        rrt.removeErrorMapping(user, Domain.of(domain), error);
+        MappingSource source = MappingSource.fromUser(user, domain);
+        rrt.removeErrorMapping(source, error);
     }
 
     @Override
     public void addDomainMapping(String domain, String targetDomain) throws RecipientRewriteTableException {
-        rrt.addAliasDomainMapping(Domain.of(domain), Domain.of(targetDomain));
+        MappingSource source = MappingSource.fromDomain(Domain.of(domain));
+        rrt.addAliasDomainMapping(source, Domain.of(targetDomain));
     }
 
     @Override
     public void removeDomainMapping(String domain, String targetDomain) throws RecipientRewriteTableException {
-        rrt.removeAliasDomainMapping(Domain.of(domain), Domain.of(targetDomain));
+        MappingSource source = MappingSource.fromDomain(Domain.of(domain));
+        rrt.removeAliasDomainMapping(source, Domain.of(targetDomain));
     }
 
     @Override
     public Mappings getUserDomainMappings(String user, String domain) throws RecipientRewriteTableException {
-        return rrt.getUserDomainMappings(user, Domain.of(domain));
+        MappingSource source = MappingSource.fromUser(user, domain);
+        return rrt.getUserDomainMappings(source);
     }
 
     @Override
     public void addMapping(String user, String domain, String mapping) throws RecipientRewriteTableException {
-        rrt.addMapping(user, Domain.of(domain), Mapping.of(mapping));
+        MappingSource source = MappingSource.fromUser(user, domain);
+        rrt.addMapping(source, Mapping.of(mapping));
     }
 
     @Override
     public void removeMapping(String user, String domain, String mapping) throws RecipientRewriteTableException {
-        rrt.removeMapping(user, Domain.of(domain), Mapping.of(mapping));
+        MappingSource source = MappingSource.fromUser(user, domain);
+        rrt.removeMapping(source, Mapping.of(mapping));
     }
 
     @Override
     public Map<String, Mappings> getAllMappings() throws RecipientRewriteTableException {
-        return ImmutableMap.copyOf(rrt.getAllMappings());
+        return rrt.getAllMappings()
+            .entrySet()
+            .stream()
+            .collect(
+                Guavate.toImmutableMap(
+                    entry -> entry.getKey().asString(),
+                    entry -> entry.getValue()));
     }
 
     @Override
     public void addForwardMapping(String user, String domain, String address) throws RecipientRewriteTableException {
-        rrt.addForwardMapping(user, Domain.of(domain), address);
+        MappingSource source = MappingSource.fromUser(user, domain);
+        rrt.addForwardMapping(source, address);
     }
 
     @Override
     public void removeForwardMapping(String user, String domain, String address) throws RecipientRewriteTableException {
-        rrt.removeForwardMapping(user, Domain.of(domain), address);
+        MappingSource source = MappingSource.fromUser(user, domain);
+        rrt.removeForwardMapping(source, address);
     }
 
     @Override
-    public void addGroupMapping(String toUser, String toDomain, String fromAddress) {
-        try {
-            rrt.addGroupMapping(toUser, Domain.of(toDomain), fromAddress);
-        } catch (RecipientRewriteTableException e) {
-            throw new RuntimeException(e);
-        }
+    public void addGroupMapping(String toUser, String toDomain, String fromAddress) throws RecipientRewriteTableException {
+        MappingSource source = MappingSource.fromUser(toUser, toDomain);
+        rrt.addGroupMapping(source, fromAddress);
     }
 
     @Override
-    public void removeGroupMapping(String toUser, String toDomain, String fromAddress) {
-        try {
-            rrt.removeForwardMapping(toUser, Domain.of(toDomain), fromAddress);
-        } catch (RecipientRewriteTableException e) {
-            throw new RuntimeException(e);
-        }
+    public void removeGroupMapping(String toUser, String toDomain, String fromAddress) throws RecipientRewriteTableException {
+        MappingSource source = MappingSource.fromUser(toUser, toDomain);
+        rrt.removeForwardMapping(source, fromAddress);
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableUtil.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableUtil.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableUtil.java
index 1546a84..6de8378 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableUtil.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableUtil.java
@@ -46,32 +46,11 @@ public class RecipientRewriteTableUtil {
      * @return the real recipient address, or <code>null</code> if no mapping
      *         exists
      */
-    public static String getTargetString(String user, Domain domain, Map<String, String> mappings) {
-        StringBuffer buf;
-        String target;
-
-        // Look for exact (user@domain) match
-        buf = new StringBuffer().append(user).append("@").append(domain.asString());
-        target = mappings.get(buf.toString());
-        if (target != null) {
-            return target;
-        }
-
-        // Look for user@* match
-        buf = new StringBuffer().append(user).append("@*");
-        target = mappings.get(buf.toString());
-        if (target != null) {
-            return target;
-        }
-
-        // Look for *@domain match
-        buf = new StringBuffer().append("*@").append(domain.asString());
-        target = mappings.get(buf.toString());
-        if (target != null) {
-            return target;
-        }
-
-        return null;
+    public static String getTargetString(String user, Domain domain, Map<MappingSource, String> mappings) {
+        return OptionalUtils.or(
+                Optional.ofNullable(mappings.get(MappingSource.fromUser(user, domain))),
+                Optional.ofNullable(mappings.get(MappingSource.fromDomain(domain))))
+            .orElse(null);
     }
 
     /**
@@ -116,15 +95,15 @@ public class RecipientRewriteTableUtil {
      *            A String which contains a list of mappings
      * @return Map which contains the mappings
      */
-    public static Map<String, String> getXMLMappings(String mapping) {
-        Map<String, String> mappings = new HashMap<>();
+    public static Map<MappingSource, String> getXMLMappings(String mapping) {
+        Map<MappingSource, String> mappings = new HashMap<>();
         StringTokenizer tokenizer = new StringTokenizer(mapping, ",");
         while (tokenizer.hasMoreTokens()) {
             String mappingItem = tokenizer.nextToken();
             int index = mappingItem.indexOf('=');
             String virtual = mappingItem.substring(0, index).trim().toLowerCase(Locale.US);
             String real = mappingItem.substring(index + 1).trim().toLowerCase(Locale.US);
-            mappings.put(virtual, real);
+            mappings.put(MappingSource.parse(virtual), real);
         }
         return mappings;
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/server/data/data-library/src/main/java/org/apache/james/user/lib/AbstractJamesUsersRepository.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/user/lib/AbstractJamesUsersRepository.java b/server/data/data-library/src/main/java/org/apache/james/user/lib/AbstractJamesUsersRepository.java
index 3f9c4d3..491accb 100644
--- a/server/data/data-library/src/main/java/org/apache/james/user/lib/AbstractJamesUsersRepository.java
+++ b/server/data/data-library/src/main/java/org/apache/james/user/lib/AbstractJamesUsersRepository.java
@@ -29,6 +29,7 @@ import org.apache.james.core.Domain;
 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.lib.Mappings;
 import org.apache.james.rrt.lib.MappingsImpl;
 import org.apache.james.rrt.lib.MappingsImpl.Builder;
@@ -172,8 +173,8 @@ public abstract class AbstractJamesUsersRepository extends AbstractUsersReposito
     }
 
     @Override
-    public Map<String, Mappings> getAllMappings() throws RecipientRewriteTableException {
-        Map<String, Mappings> mappings = new HashMap<>();
+    public Map<MappingSource, Mappings> getAllMappings() throws RecipientRewriteTableException {
+        Map<MappingSource, Mappings> mappings = new HashMap<>();
         if (enableAliases || enableForwarding) {
             try {
                 Iterator<String> users = list();
@@ -190,7 +191,8 @@ public abstract class AbstractJamesUsersRepository extends AbstractUsersReposito
                         domain = Domain.LOCALHOST;
                     }
                     try {
-                        mappings.put(user, getMappings(username, domain));
+                        MappingSource source = MappingSource.fromUser(org.apache.james.core.User.fromUsername(user));
+                        mappings.put(source, getMappings(username, domain));
                     } catch (ErrorMappingException e) {
                         // shold never happen here
                     }
@@ -204,86 +206,86 @@ public abstract class AbstractJamesUsersRepository extends AbstractUsersReposito
     }
 
     @Override
-    public Mappings getUserDomainMappings(String user, Domain domain) throws RecipientRewriteTableException {
+    public Mappings getUserDomainMappings(MappingSource source) throws RecipientRewriteTableException {
         return MappingsImpl.empty();
     }
 
     @Override
-    public void addRegexMapping(String user, Domain domain, String regex) throws RecipientRewriteTableException {
+    public void addRegexMapping(MappingSource source, String regex) throws RecipientRewriteTableException {
         throw new RecipientRewriteTableException("Read-Only RecipientRewriteTable");
     }
 
     @Override
-    public void removeRegexMapping(String user, Domain domain, String regex) throws RecipientRewriteTableException {
+    public void removeRegexMapping(MappingSource source, String regex) throws RecipientRewriteTableException {
         throw new RecipientRewriteTableException("Read-Only RecipientRewriteTable");
 
     }
 
     @Override
-    public void addAddressMapping(String user, Domain domain, String address) throws RecipientRewriteTableException {
+    public void addAddressMapping(MappingSource source, String address) throws RecipientRewriteTableException {
         throw new RecipientRewriteTableException("Read-Only RecipientRewriteTable");
 
     }
 
     @Override
-    public void removeAddressMapping(String user, Domain domain, String address) throws RecipientRewriteTableException {
+    public void removeAddressMapping(MappingSource source, String address) throws RecipientRewriteTableException {
         throw new RecipientRewriteTableException("Read-Only RecipientRewriteTable");
 
     }
 
     @Override
-    public void addErrorMapping(String user, Domain domain, String error) throws RecipientRewriteTableException {
+    public void addErrorMapping(MappingSource source, String error) throws RecipientRewriteTableException {
         throw new RecipientRewriteTableException("Read-Only RecipientRewriteTable");
 
     }
 
     @Override
-    public void removeErrorMapping(String user, Domain domain, String error) throws RecipientRewriteTableException {
+    public void removeErrorMapping(MappingSource source, String error) throws RecipientRewriteTableException {
         throw new RecipientRewriteTableException("Read-Only RecipientRewriteTable");
 
     }
 
     @Override
-    public void addMapping(String user, Domain domain, Mapping mapping) throws RecipientRewriteTableException {
+    public void addMapping(MappingSource source, Mapping mapping) throws RecipientRewriteTableException {
         throw new RecipientRewriteTableException("Read-Only RecipientRewriteTable");
 
     }
 
     @Override
-    public void removeMapping(String user, Domain domain, Mapping mapping) throws RecipientRewriteTableException {
+    public void removeMapping(MappingSource source, Mapping mapping) throws RecipientRewriteTableException {
         throw new RecipientRewriteTableException("Read-Only RecipientRewriteTable");
 
     }
 
     @Override
-    public void addAliasDomainMapping(Domain aliasDomain, Domain realDomain) throws RecipientRewriteTableException {
+    public void addAliasDomainMapping(MappingSource source, Domain realDomain) throws RecipientRewriteTableException {
         throw new RecipientRewriteTableException("Read-Only RecipientRewriteTable");
 
     }
 
     @Override
-    public void removeAliasDomainMapping(Domain aliasDomain, Domain realDomain) throws RecipientRewriteTableException {
+    public void removeAliasDomainMapping(MappingSource source, Domain realDomain) throws RecipientRewriteTableException {
         throw new RecipientRewriteTableException("Read-Only RecipientRewriteTable");
 
     }
 
     @Override
-    public void addForwardMapping(String user, Domain domain, String address) throws RecipientRewriteTableException {
+    public void addForwardMapping(MappingSource source, String address) throws RecipientRewriteTableException {
         throw new RecipientRewriteTableException("Read-Only RecipientRewriteTable");
     }
 
     @Override
-    public void removeForwardMapping(String user, Domain domain, String address) throws RecipientRewriteTableException {
+    public void removeForwardMapping(MappingSource source, String address) throws RecipientRewriteTableException {
         throw new RecipientRewriteTableException("Read-Only RecipientRewriteTable");
     }
 
     @Override
-    public void addGroupMapping(String user, Domain domain, String address) throws RecipientRewriteTableException {
+    public void addGroupMapping(MappingSource source, String address) throws RecipientRewriteTableException {
         throw new RecipientRewriteTableException("Read-Only RecipientRewriteTable");
     }
 
     @Override
-    public void removeGroupMapping(String user, Domain domain, String address) throws RecipientRewriteTableException {
+    public void removeGroupMapping(MappingSource source, String address) throws RecipientRewriteTableException {
         throw new RecipientRewriteTableException("Read-Only RecipientRewriteTable");
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/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 2873feb..17bb88e 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
@@ -26,7 +26,6 @@ import java.util.Map;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.james.core.Domain;
 import org.apache.james.lifecycle.api.LifecycleUtil;
-import org.apache.james.rrt.api.RecipientRewriteTable;
 import org.apache.james.rrt.api.RecipientRewriteTable.ErrorMappingException;
 import org.apache.james.rrt.api.RecipientRewriteTableException;
 import org.junit.Rule;
@@ -53,16 +52,15 @@ public abstract class AbstractRecipientRewriteTableTest {
     }
 
     public void tearDown() throws Exception {
-        Map<String, Mappings> mappings = virtualUserTable.getAllMappings();
+        Map<MappingSource, Mappings> mappings = virtualUserTable.getAllMappings();
 
         if (mappings != null) {
-            for (String key : virtualUserTable.getAllMappings().keySet()) {
+            for (MappingSource key : virtualUserTable.getAllMappings().keySet()) {
                 Mappings map = mappings.get(key);
-                String[] args = key.split("@");
 
                 map.asStream()
                     .forEach(Throwing.consumer(mapping ->
-                        virtualUserTable.removeMapping(args[0], Domain.of(args[1]), mapping)));
+                        virtualUserTable.removeMapping(key, mapping)));
             }
         }
 
@@ -71,9 +69,8 @@ public abstract class AbstractRecipientRewriteTableTest {
 
     @Test
     public void testStoreAndGetMappings() throws ErrorMappingException, RecipientRewriteTableException {
-        String user = "*";
         Domain domain = Domain.of("test");
-        virtualUserTable.addMapping(user, domain, Mapping.regex("prefix_.*:admin@test"));
+        virtualUserTable.addMapping(MappingSource.fromDomain(domain), Mapping.regex("prefix_.*:admin@test"));
         assertThat(virtualUserTable.getMappings("prefix_abc", domain)).isNotEmpty();
     }
 
@@ -81,6 +78,7 @@ public abstract class AbstractRecipientRewriteTableTest {
     public void testStoreAndRetrieveRegexMapping() throws ErrorMappingException, RecipientRewriteTableException {
         String user = "test";
         Domain domain = Domain.LOCALHOST;
+        MappingSource source = MappingSource.fromUser(user, domain);
         // String regex = "(.*):{$1}@localhost";
         // String regex2 = "(.+):{$1}@test";
         String regex = "(.*)@localhost";
@@ -90,18 +88,18 @@ public abstract class AbstractRecipientRewriteTableTest {
         assertThat(virtualUserTable.getMappings(user, domain)).describedAs("No mapping")
             .isEqualTo(MappingsImpl.empty());
 
-        virtualUserTable.addMapping(user, domain, Mapping.regex(regex));
-        virtualUserTable.addMapping(user, domain, Mapping.regex(regex2));
+        virtualUserTable.addMapping(source, Mapping.regex(regex));
+        virtualUserTable.addMapping(source, Mapping.regex(regex2));
         assertThat(virtualUserTable.getMappings(user, domain)).describedAs("Two mappings").hasSize(2);
         assertThat(virtualUserTable.getAllMappings()).describedAs("One mappingline").hasSize(1);
-        virtualUserTable.removeMapping(user, domain, Mapping.regex(regex));
+        virtualUserTable.removeMapping(source, Mapping.regex(regex));
 
-        assertThatThrownBy(() -> virtualUserTable.addRegexMapping(user, domain, invalidRegex))
+        assertThatThrownBy(() -> virtualUserTable.addRegexMapping(source, invalidRegex))
             .describedAs("Invalid Mapping throw exception")
             .isInstanceOf(RecipientRewriteTableException.class);
 
 
-        virtualUserTable.removeMapping(user, domain, Mapping.regex(regex2));
+        virtualUserTable.removeMapping(source, Mapping.regex(regex2));
 
 
         assertThat(virtualUserTable.getMappings(user, domain)).describedAs("No mapping")
@@ -116,18 +114,21 @@ public abstract class AbstractRecipientRewriteTableTest {
         String regex = "(.*)@localhost";
         String regex2 = "(.+)@test";
 
-        virtualUserTable.addMapping(user, Domain.LOCALHOST, Mapping.regex(regex));
-        virtualUserTable.addMapping(user, Domain.LOCALHOST, Mapping.regex(regex2));
-        virtualUserTable.addMapping(user2, Domain.LOCALHOST, Mapping.address(user + "@" + Domain.LOCALHOST.asString()));
+        MappingSource source1 = MappingSource.fromUser(user, Domain.LOCALHOST);
+        MappingSource source2 = MappingSource.fromUser(user2, Domain.LOCALHOST);
+
+        virtualUserTable.addMapping(source1, Mapping.regex(regex));
+        virtualUserTable.addMapping(source1, Mapping.regex(regex2));
+        virtualUserTable.addMapping(source2, Mapping.address(user + "@" + Domain.LOCALHOST.asString()));
 
         assertThat(virtualUserTable.getAllMappings())
             .describedAs("One mappingline")
             .containsOnly(
-                Pair.of(user + "@" + Domain.LOCALHOST.asString(), MappingsImpl.builder()
+                Pair.of(source1, MappingsImpl.builder()
                     .add(Mapping.regex(regex))
                     .add(Mapping.regex(regex2))
                     .build()),
-                Pair.of(user2 + "@" + Domain.LOCALHOST.asString(), MappingsImpl.builder()
+                Pair.of(source2, MappingsImpl.builder()
                     .add(Mapping.address(user + "@" + Domain.LOCALHOST.asString()))
                     .build()));
     }
@@ -137,20 +138,21 @@ public abstract class AbstractRecipientRewriteTableTest {
 
         String user = "test";
         Domain domain = Domain.LOCALHOST;
+        MappingSource source = MappingSource.fromUser(user, domain);
         String address = "test@localhost2";
         String address2 = "test@james";
 
         assertThat(virtualUserTable.getMappings(user, domain)).describedAs("No mapping")
             .isEqualTo(MappingsImpl.empty());
 
-        virtualUserTable.addMapping(user, domain, Mapping.address(address));
-        virtualUserTable.addMapping(user, domain, Mapping.address(address2));
+        virtualUserTable.addMapping(source, Mapping.address(address));
+        virtualUserTable.addMapping(source, Mapping.address(address2));
 
         assertThat(virtualUserTable.getMappings(user, domain)).describedAs("Two mappings").hasSize(2);
         assertThat(virtualUserTable.getAllMappings()).describedAs("One mappingline").hasSize(1);
 
-        virtualUserTable.removeMapping(user, domain, Mapping.address(address));
-        virtualUserTable.removeMapping(user, domain, Mapping.address(address2));
+        virtualUserTable.removeMapping(source, Mapping.address(address));
+        virtualUserTable.removeMapping(source, Mapping.address(address2));
 
         assertThat(virtualUserTable.getMappings(user, domain)).describedAs("No mapping")
             .isEqualTo(MappingsImpl.empty());
@@ -161,12 +163,13 @@ public abstract class AbstractRecipientRewriteTableTest {
     public void testStoreAndRetrieveErrorMapping() throws ErrorMappingException, RecipientRewriteTableException {
         String user = "test";
         Domain domain = Domain.LOCALHOST;
+        MappingSource source = MappingSource.fromUser(user, domain);
         String error = "bounce!";
 
         assertThat(virtualUserTable.getMappings(user, domain)).describedAs("No mapping")
             .isEqualTo(MappingsImpl.empty());
 
-        virtualUserTable.addMapping(user, domain, Mapping.error(error));
+        virtualUserTable.addMapping(source, Mapping.error(error));
         assertThat(virtualUserTable.getAllMappings()).describedAs("One mappingline").hasSize(1);
 
         assertThatThrownBy(() ->
@@ -174,7 +177,7 @@ public abstract class AbstractRecipientRewriteTableTest {
             .describedAs("Exception thrown on to many mappings")
             .isInstanceOf(ErrorMappingException.class);
 
-        virtualUserTable.removeMapping(user, domain, Mapping.error(error));
+        virtualUserTable.removeMapping(source, Mapping.error(error));
 
         assertThat(virtualUserTable.getMappings(user, domain)).describedAs("No mapping")
             .isEqualTo(MappingsImpl.empty());
@@ -188,18 +191,19 @@ public abstract class AbstractRecipientRewriteTableTest {
         Domain domain = Domain.LOCALHOST;
         String address = "test@localhost2";
         String address2 = "test@james";
+        MappingSource source = MappingSource.fromUser(user, domain);
 
         assertThat(virtualUserTable.getMappings(user, domain)).describedAs("No mapping")
             .isEqualTo(MappingsImpl.empty());
 
-        virtualUserTable.addMapping(RecipientRewriteTable.WILDCARD, domain, Mapping.address(address));
-        virtualUserTable.addMapping(user, domain, Mapping.address(address2));
+        virtualUserTable.addMapping(MappingSource.fromDomain(domain), Mapping.address(address));
+        virtualUserTable.addMapping(source, Mapping.address(address2));
 
         assertThat(virtualUserTable.getMappings(user, domain)).describedAs("One mappings").hasSize(1);
         assertThat(virtualUserTable.getMappings(user2, domain)).describedAs("One mappings").hasSize(1);
 
-        virtualUserTable.removeMapping(user, domain, Mapping.address(address2));
-        virtualUserTable.removeMapping(RecipientRewriteTable.WILDCARD, domain, Mapping.address(address));
+        virtualUserTable.removeMapping(source, Mapping.address(address2));
+        virtualUserTable.removeMapping(MappingSource.fromDomain(domain), Mapping.address(address));
 
         assertThat(virtualUserTable.getMappings(user, domain)).describedAs("No mapping")
             .isEqualTo(MappingsImpl.empty());
@@ -215,15 +219,18 @@ public abstract class AbstractRecipientRewriteTableTest {
         Domain domain1 = Domain.of("domain1");
         Domain domain2 = Domain.of("domain2");
         Domain domain3 = Domain.of("domain3");
+        MappingSource source1 = MappingSource.fromUser(user1, domain1);
+        MappingSource source2 = MappingSource.fromUser(user2, domain2);
+        MappingSource source3 = MappingSource.fromUser(user3, domain3);
 
         virtualUserTable.setRecursiveMapping(true);
 
         assertThat(virtualUserTable.getAllMappings()).describedAs("No mapping").isEmpty();
 
-        virtualUserTable.addMapping(user1, domain1, Mapping.address(user2 + "@" + domain2.asString()));
-        virtualUserTable.addMapping(user2, domain2, Mapping.address(user3 + "@" + domain3.asString()));
+        virtualUserTable.addMapping(source1, Mapping.address(user2 + "@" + domain2.asString()));
+        virtualUserTable.addMapping(source2, Mapping.address(user3 + "@" + domain3.asString()));
         assertThat(virtualUserTable.getMappings(user1, domain1)).containsOnly(Mapping.address(user3 + "@" + domain3.asString()));
-        virtualUserTable.addMapping(user3, domain3, Mapping.address(user1 + "@" + domain1.asString()));
+        virtualUserTable.addMapping(source3, Mapping.address(user1 + "@" + domain1.asString()));
 
         assertThatThrownBy(() ->
             virtualUserTable.getMappings(user1, domain1))
@@ -244,8 +251,8 @@ public abstract class AbstractRecipientRewriteTableTest {
 
         assertThat(virtualUserTable.getAllMappings()).describedAs("No mappings").isEmpty();
 
-        virtualUserTable.addMapping(RecipientRewriteTable.WILDCARD, aliasDomain, Mapping.address(user2 + "@" + domain));
-        virtualUserTable.addMapping(RecipientRewriteTable.WILDCARD, aliasDomain, Mapping.domain(Domain.of(domain)));
+        virtualUserTable.addMapping(MappingSource.fromDomain(aliasDomain), Mapping.address(user2 + "@" + domain));
+        virtualUserTable.addMapping(MappingSource.fromDomain(aliasDomain), Mapping.domain(Domain.of(domain)));
 
         assertThat(virtualUserTable.getMappings(user, aliasDomain))
             .describedAs("Domain mapped as first, Address mapped as second")
@@ -254,8 +261,8 @@ public abstract class AbstractRecipientRewriteTableTest {
                 .add(Mapping.address(user2 + "@" + domain))
                 .build());
 
-        virtualUserTable.removeMapping(RecipientRewriteTable.WILDCARD, aliasDomain, Mapping.address(user2 + "@" + domain));
-        virtualUserTable.removeMapping(RecipientRewriteTable.WILDCARD, aliasDomain, Mapping.domain(Domain.of(domain)));
+        virtualUserTable.removeMapping(MappingSource.fromDomain(aliasDomain), Mapping.address(user2 + "@" + domain));
+        virtualUserTable.removeMapping(MappingSource.fromDomain(aliasDomain), Mapping.domain(Domain.of(domain)));
     }
 
     @Test
@@ -263,11 +270,12 @@ public abstract class AbstractRecipientRewriteTableTest {
         String user = "test";
         Domain domain = Domain.LOCALHOST;
         String address = "test@localhost2";
+        MappingSource source = MappingSource.fromUser(user, domain);
 
         expectedException.expect(RecipientRewriteTableException.class);
 
-        virtualUserTable.addAddressMapping(user, domain, address);
-        virtualUserTable.addAddressMapping(user, domain, address);
+        virtualUserTable.addAddressMapping(source, address);
+        virtualUserTable.addAddressMapping(source, address);
     }
 
     @Test
@@ -275,9 +283,10 @@ public abstract class AbstractRecipientRewriteTableTest {
         String user = "test";
         Domain domain = Domain.LOCALHOST;
         String address = "test@localhost2";
+        MappingSource source = MappingSource.fromUser(user, domain);
 
-        virtualUserTable.addMapping(user, domain, Mapping.address(address));
-        virtualUserTable.addMapping(user, domain, Mapping.regex(address));
+        virtualUserTable.addMapping(source, Mapping.address(address));
+        virtualUserTable.addMapping(source, Mapping.regex(address));
 
         assertThat(virtualUserTable.getMappings(user, domain)).hasSize(2);
     }
@@ -288,9 +297,10 @@ public abstract class AbstractRecipientRewriteTableTest {
         Domain domain = Domain.LOCALHOST;
         String address = "test@localhost2";
         String address2 = "test@james";
+        MappingSource source = MappingSource.fromUser(user, domain);
 
-        virtualUserTable.addMapping(user, domain, Mapping.forward(address));
-        virtualUserTable.addMapping(user, domain, Mapping.forward(address2));
+        virtualUserTable.addMapping(source, Mapping.forward(address));
+        virtualUserTable.addMapping(source, Mapping.forward(address2));
 
         assertThat(virtualUserTable.getMappings(user, domain)).hasSize(2);
     }
@@ -301,12 +311,13 @@ public abstract class AbstractRecipientRewriteTableTest {
         Domain domain = Domain.LOCALHOST;
         String address = "test@localhost2";
         String address2 = "test@james";
+        MappingSource source = MappingSource.fromUser(user, domain);
 
-        virtualUserTable.addMapping(user, domain, Mapping.forward(address));
-        virtualUserTable.addMapping(user, domain, Mapping.forward(address2));
+        virtualUserTable.addMapping(source, Mapping.forward(address));
+        virtualUserTable.addMapping(source, Mapping.forward(address2));
 
-        virtualUserTable.removeMapping(user, domain, Mapping.forward(address));
-        virtualUserTable.removeMapping(user, domain, Mapping.forward(address2));
+        virtualUserTable.removeMapping(source, Mapping.forward(address));
+        virtualUserTable.removeMapping(source, Mapping.forward(address2));
 
         assertThat(virtualUserTable.getMappings(user, domain))
             .isEqualTo(MappingsImpl.empty());
@@ -318,9 +329,10 @@ public abstract class AbstractRecipientRewriteTableTest {
         Domain domain = Domain.LOCALHOST;
         String address = "test@localhost2";
         String address2 = "test@james";
+        MappingSource source = MappingSource.fromUser(user, domain);
 
-        virtualUserTable.addMapping(user, domain, Mapping.group(address));
-        virtualUserTable.addMapping(user, domain, Mapping.group(address2));
+        virtualUserTable.addMapping(source, Mapping.group(address));
+        virtualUserTable.addMapping(source, Mapping.group(address2));
 
         assertThat(virtualUserTable.getMappings(user, domain)).hasSize(2);
     }
@@ -331,12 +343,13 @@ public abstract class AbstractRecipientRewriteTableTest {
         Domain domain = Domain.LOCALHOST;
         String address = "test@localhost2";
         String address2 = "test@james";
+        MappingSource source = MappingSource.fromUser(user, domain);
 
-        virtualUserTable.addMapping(user, domain, Mapping.group(address));
-        virtualUserTable.addMapping(user, domain, Mapping.group(address2));
+        virtualUserTable.addMapping(source, Mapping.group(address));
+        virtualUserTable.addMapping(source, Mapping.group(address2));
 
-        virtualUserTable.removeMapping(user, domain, Mapping.group(address));
-        virtualUserTable.removeMapping(user, domain, Mapping.group(address2));
+        virtualUserTable.removeMapping(source, Mapping.group(address));
+        virtualUserTable.removeMapping(source, Mapping.group(address2));
 
         assertThat(virtualUserTable.getMappings(user, domain))
             .isEqualTo(MappingsImpl.empty());

http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/server/data/data-library/src/test/java/org/apache/james/rrt/lib/RewriteTablesStepdefs.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/test/java/org/apache/james/rrt/lib/RewriteTablesStepdefs.java b/server/data/data-library/src/test/java/org/apache/james/rrt/lib/RewriteTablesStepdefs.java
index bd888ca..a2e83b7 100644
--- a/server/data/data-library/src/test/java/org/apache/james/rrt/lib/RewriteTablesStepdefs.java
+++ b/server/data/data-library/src/test/java/org/apache/james/rrt/lib/RewriteTablesStepdefs.java
@@ -39,13 +39,15 @@ public class RewriteTablesStepdefs {
 
     @Given("store \"([^\"]*)\" regexp mapping for user \"([^\"]*)\" at domain \"([^\"]*)\"")
     public void storeRegexpMappingForUserAtDomain(String regexp, String user, String domain) throws Throwable {
-        rewriteTable.addRegexMapping(user, Domain.of(domain), regexp);
+        MappingSource source = MappingSource.fromUser(user, domain);
+        rewriteTable.addRegexMapping(source, regexp);
     }
 
     @Given("store an invalid \"([^\"]*)\" regexp mapping for user \"([^\"]*)\" at domain \"([^\"]*)\"")
     public void storeInvalidRegexpMappingForUserAtDomain(String regexp, String user, String domain) {
         try {
-            rewriteTable.addRegexMapping(user, Domain.of(domain), regexp);
+            MappingSource source = MappingSource.fromUser(user, domain);
+            rewriteTable.addRegexMapping(source, regexp);
         } catch (RecipientRewriteTableException e) {
             this.exception = e;
         }
@@ -53,12 +55,14 @@ public class RewriteTablesStepdefs {
 
     @Given("store \"([^\"]*)\" address mapping for user \"([^\"]*)\" at domain \"([^\"]*)\"")
     public void storeAddressMappingForUserAtDomain(String address, String user, String domain) throws Throwable {
-        rewriteTable.addAddressMapping(user, Domain.of(domain), address);
+        MappingSource source = MappingSource.fromUser(user, domain);
+        rewriteTable.addAddressMapping(source, address);
     }
 
     @Given("store \"([^\"]*)\" error mapping for user \"([^\"]*)\" at domain \"([^\"]*)\"")
     public void storeErrorMappingForUserAtDomain(String error, String user, String domain) throws Throwable {
-        rewriteTable.addErrorMapping(user, Domain.of(domain), error);
+        MappingSource source = MappingSource.fromUser(user, domain);
+        rewriteTable.addErrorMapping(source, error);
     }
 
     @Given("store \"([^\"]*)\" address mapping as wildcard for domain \"([^\"]*)\"")
@@ -68,17 +72,19 @@ public class RewriteTablesStepdefs {
 
     @Given("store \"([^\"]*)\" alias domain mapping for domain \"([^\"]*)\"")
     public void storeAliasDomainMappingForDomain(String aliasDomain, String domain) throws Throwable {
-        rewriteTable.addAliasDomainMapping(Domain.of(aliasDomain), Domain.of(domain));
+        rewriteTable.addAliasDomainMapping(MappingSource.fromDomain(Domain.of(aliasDomain)), Domain.of(domain));
     }
 
     @Given("store \"([^\"]*)\" forward mapping for user \"([^\"]*)\" at domain \"([^\"]*)\"")
     public void storeForwardMappingForUserAtDomain(String address, String user, String domain) throws Throwable {
-        rewriteTable.addForwardMapping(user, Domain.of(domain), address);
+        MappingSource source = MappingSource.fromUser(user, domain);
+        rewriteTable.addForwardMapping(source, address);
     }
 
     @Given("store \"([^\"]*)\" group mapping for user \"([^\"]*)\" at domain \"([^\"]*)\"")
     public void storeGroupMappingForUserAtDomain(String address, String user, String domain) throws Throwable {
-        rewriteTable.addGroupMapping(user, Domain.of(domain), address);
+        MappingSource source = MappingSource.fromUser(user, domain);
+        rewriteTable.addGroupMapping(source, address);
     }
 
     @Given("recursive mapping is disable")
@@ -93,27 +99,32 @@ public class RewriteTablesStepdefs {
 
     @When("user \"([^\"]*)\" at domain \"([^\"]*)\" removes a regexp mapping \"([^\"]*)\"")
     public void userAtDomainRemovesRegexpMapping(String user, String domain, String regexp) throws Throwable {
-        rewriteTable.removeRegexMapping(user, Domain.of(domain), regexp);
+        MappingSource source = MappingSource.fromUser(user, domain);
+        rewriteTable.removeRegexMapping(source, regexp);
     }
 
     @When("user \"([^\"]*)\" at domain \"([^\"]*)\" removes a address mapping \"([^\"]*)\"")
     public void userAtDomainRemovesAddressMapping(String user, String domain, String address) throws Throwable {
-        rewriteTable.removeAddressMapping(user, Domain.of(domain), address);
+        MappingSource source = MappingSource.fromUser(user, domain);
+        rewriteTable.removeAddressMapping(source, address);
     }
 
     @When("user \"([^\"]*)\" at domain \"([^\"]*)\" removes a error mapping \"([^\"]*)\"")
     public void userAtDomainRemovesErrorMapping(String user, String domain, String error) throws Throwable {
-        rewriteTable.removeErrorMapping(user, Domain.of(domain), error);
+        MappingSource source = MappingSource.fromUser(user, domain);
+        rewriteTable.removeErrorMapping(source, error);
     }
 
     @When("user \"([^\"]*)\" at domain \"([^\"]*)\" removes a forward mapping \"([^\"]*)\"")
     public void userAtDomainRemovesForwardMapping(String user, String domain, String address) throws Throwable {
-        rewriteTable.removeForwardMapping(user, Domain.of(domain), address);
+        MappingSource source = MappingSource.fromUser(user, domain);
+        rewriteTable.removeForwardMapping(source, address);
     }
 
     @When("user \"([^\"]*)\" at domain \"([^\"]*)\" removes a group mapping \"([^\"]*)\"")
     public void userAtDomainRemovesGroupMapping(String user, String domain, String address) throws Throwable {
-        rewriteTable.removeGroupMapping(user, Domain.of(domain), address);
+        MappingSource source = MappingSource.fromUser(user, domain);
+        rewriteTable.removeGroupMapping(source, address);
     }
 
     @When("wildcard address mapping \"([^\"]*)\" at domain \"([^\"]*)\" is removed")
@@ -123,7 +134,7 @@ public class RewriteTablesStepdefs {
 
     @When("alias domain mapping \"([^\"]*)\" for \"([^\"]*)\" domain is removed")
     public void removeAliasDomainMappingForDomain(String aliasdomain, String domain) throws Throwable {
-        rewriteTable.removeAliasDomainMapping(Domain.of(aliasdomain), Domain.of(domain));
+        rewriteTable.removeAliasDomainMapping(MappingSource.fromDomain(Domain.of(aliasdomain)), Domain.of(domain));
     }
 
     @Then("mappings should be empty")

http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/server/data/data-memory/src/main/java/org/apache/james/rrt/memory/MemoryRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-memory/src/main/java/org/apache/james/rrt/memory/MemoryRecipientRewriteTable.java b/server/data/data-memory/src/main/java/org/apache/james/rrt/memory/MemoryRecipientRewriteTable.java
index b45e4ed..fca798c 100644
--- a/server/data/data-memory/src/main/java/org/apache/james/rrt/memory/MemoryRecipientRewriteTable.java
+++ b/server/data/data-memory/src/main/java/org/apache/james/rrt/memory/MemoryRecipientRewriteTable.java
@@ -28,8 +28,10 @@ import java.util.stream.Stream;
 
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.james.core.Domain;
+import org.apache.james.core.User;
 import org.apache.james.rrt.lib.AbstractRecipientRewriteTable;
 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 org.apache.james.util.OptionalUtils;
@@ -41,32 +43,22 @@ import com.google.common.collect.Multimaps;
 public class MemoryRecipientRewriteTable extends AbstractRecipientRewriteTable {
 
     private static class InMemoryMappingEntry {
-        private final String user;
-        private final Domain domain;
+        private final MappingSource source;
         private final Mapping mapping;
 
-        public InMemoryMappingEntry(String user, Domain domain, Mapping mapping) {
-            this.user = user;
-            this.domain = domain;
+        public InMemoryMappingEntry(MappingSource source, Mapping mapping) {
+            this.source = source;
             this.mapping = mapping;
         }
 
-        public String getUser() {
-            return user;
-        }
-
-        public Domain getDomain() {
-            return domain;
+        public MappingSource getSource() {
+            return source;
         }
 
         public Mapping getMapping() {
             return mapping;
         }
 
-        public String asKey() {
-            return getUser() + "@" + getDomain().asString();
-        }
-
         @Override
         public boolean equals(Object o) {
             if (o == null || this.getClass() != o.getClass()) {
@@ -75,14 +67,13 @@ public class MemoryRecipientRewriteTable extends AbstractRecipientRewriteTable {
 
             InMemoryMappingEntry that = (InMemoryMappingEntry) o;
 
-            return Objects.equal(this.user, that.user)
-                && Objects.equal(this.domain, that.domain)
+            return Objects.equal(this.source, that.source)
                 && Objects.equal(this.mapping, that.mapping);
         }
 
         @Override
         public int hashCode() {
-            return Objects.hashCode(user, domain, mapping);
+            return Objects.hashCode(source, mapping);
         }
     }
 
@@ -93,32 +84,32 @@ public class MemoryRecipientRewriteTable extends AbstractRecipientRewriteTable {
     }
 
     @Override
-    public void addMapping(String user, Domain domain, Mapping mapping) {
-        mappingEntries.add(new InMemoryMappingEntry(getFixedUser(user), getFixedDomain(domain), mapping));
+    public void addMapping(MappingSource source, Mapping mapping) {
+        mappingEntries.add(new InMemoryMappingEntry(source, mapping));
     }
 
     @Override
-    public void removeMapping(String user, Domain domain, Mapping mapping) {
-        mappingEntries.remove(new InMemoryMappingEntry(getFixedUser(user), getFixedDomain(domain), mapping));
+    public void removeMapping(MappingSource source, Mapping mapping) {
+        mappingEntries.remove(new InMemoryMappingEntry(source, mapping));
     }
 
     @Override
-    public Mappings getUserDomainMappings(String user, Domain domain) {
-        return retrieveMappings(user, domain)
+    public Mappings getUserDomainMappings(MappingSource mappingSource) {
+        return retrieveMappings(mappingSource)
             .orElse(null);
     }
 
     @Override
     protected Mappings mapAddress(String user, Domain domain) {
         return OptionalUtils.orSuppliers(
-            () -> retrieveMappings(user, domain),
-            () -> retrieveMappings(WILDCARD, domain))
+            () -> retrieveMappings(MappingSource.fromUser(User.fromLocalPartWithDomain(user, domain))),
+            () -> retrieveMappings(MappingSource.fromDomain(domain)))
             .orElse(MappingsImpl.empty());
     }
 
     @Override
-    public Map<String, Mappings> getAllMappings() {
-        return Multimaps.index(mappingEntries, InMemoryMappingEntry::asKey)
+    public Map<MappingSource, Mappings> getAllMappings() {
+        return Multimaps.index(mappingEntries, InMemoryMappingEntry::getSource)
             .asMap()
             .entrySet()
             .stream()
@@ -132,9 +123,9 @@ public class MemoryRecipientRewriteTable extends AbstractRecipientRewriteTable {
             .map(InMemoryMappingEntry::getMapping));
     }
 
-    private Optional<Mappings> retrieveMappings(String user, Domain domain) {
+    private Optional<Mappings> retrieveMappings(MappingSource mappingSource) {
         Stream<Mapping> userEntries = mappingEntries.stream()
-            .filter(mappingEntry -> user.equals(mappingEntry.getUser()) && domain.equals(mappingEntry.getDomain()))
+            .filter(mappingEntry -> mappingEntry.source.equals(mappingSource))
             .map(InMemoryMappingEntry::getMapping);
         return MappingsImpl.fromMappings(userEntries).toOptional();
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/XMLRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/XMLRecipientRewriteTable.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/XMLRecipientRewriteTable.java
index 9fea7da..bdb8dbc 100755
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/XMLRecipientRewriteTable.java
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/XMLRecipientRewriteTable.java
@@ -28,6 +28,7 @@ import javax.mail.MessagingException;
 
 import org.apache.james.core.Domain;
 import org.apache.james.core.MailAddress;
+import org.apache.james.rrt.lib.MappingSource;
 import org.apache.james.rrt.lib.RecipientRewriteTableUtil;
 import org.apache.mailet.Experimental;
 
@@ -80,7 +81,7 @@ public class XMLRecipientRewriteTable extends AbstractRecipientRewriteTable {
     /**
      * Holds the configured mappings
      */
-    private Map<String, String> mappings = new HashMap<>();
+    private Map<MappingSource, String> mappings = new HashMap<>();
 
     @Override
     public void init() throws MessagingException {
@@ -99,7 +100,7 @@ public class XMLRecipientRewriteTable extends AbstractRecipientRewriteTable {
      *            the mapping of virtual to real recipients
      */
     @Override
-    protected void mapRecipients(Map<MailAddress, String> recipientsMap) throws MessagingException {
+    protected void mapRecipients(Map<MailAddress, String> recipientsMap) {
         Collection<MailAddress> recipients = recipientsMap.keySet();
 
         for (MailAddress source : recipients) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptHandlerTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptHandlerTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptHandlerTest.java
index c9db765..2e8e892 100644
--- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptHandlerTest.java
+++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptHandlerTest.java
@@ -38,6 +38,7 @@ import org.apache.james.protocols.smtp.hook.HookReturnCode;
 import org.apache.james.protocols.smtp.utils.BaseFakeSMTPSession;
 import org.apache.james.rrt.api.RecipientRewriteTable;
 import org.apache.james.rrt.api.RecipientRewriteTableException;
+import org.apache.james.rrt.lib.MappingSource;
 import org.apache.james.rrt.memory.MemoryRecipientRewriteTable;
 import org.apache.james.smtpserver.fastfail.ValidRcptHandler;
 import org.apache.james.user.api.UsersRepository;
@@ -116,8 +117,8 @@ public class ValidRcptHandlerTest {
     private RecipientRewriteTable setUpRecipientRewriteTable(DomainList domainList) throws RecipientRewriteTableException {
         MemoryRecipientRewriteTable memoryRecipientRewriteTable = new MemoryRecipientRewriteTable();
         memoryRecipientRewriteTable.setDomainList(domainList);
-        memoryRecipientRewriteTable.addAddressMapping(USER1, Domain.LOCALHOST, "address");
-        memoryRecipientRewriteTable.addErrorMapping(USER2, Domain.LOCALHOST, "554 BOUNCE");
+        memoryRecipientRewriteTable.addAddressMapping(MappingSource.fromUser(USER1, Domain.LOCALHOST), "address");
+        memoryRecipientRewriteTable.addErrorMapping(MappingSource.fromUser(USER2, Domain.LOCALHOST), "554 BOUNCE");
         return memoryRecipientRewriteTable;
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/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 2145d40..935f88a 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
@@ -39,13 +39,16 @@ import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.User;
 import org.apache.james.domainlist.api.DomainListException;
 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.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;
@@ -134,6 +137,8 @@ public class ForwardRoutes implements Routes {
                 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());
     }
@@ -161,7 +166,8 @@ public class ForwardRoutes implements Routes {
         MailAddress forwardBaseAddress = parseMailAddress(request.params(FORWARD_BASE_ADDRESS));
         ensureUserExist(forwardBaseAddress);
         MailAddress destinationAddress = parseMailAddress(request.params(FORWARD_DESTINATION_ADDRESS));
-        recipientRewriteTable.addForwardMapping(forwardBaseAddress.getLocalPart(), forwardBaseAddress.getDomain(), destinationAddress.asString());
+        MappingSource source = MappingSource.fromUser(User.fromLocalPartWithDomain(forwardBaseAddress.getLocalPart(), forwardBaseAddress.getDomain()));
+        recipientRewriteTable.addForwardMapping(source, destinationAddress.asString());
         return halt(HttpStatus.CREATED_201);
     }
 
@@ -193,10 +199,8 @@ public class ForwardRoutes implements Routes {
     public HaltException removeFromForwardDestination(Request request, Response response) throws JsonExtractException, AddressException, RecipientRewriteTableException {
         MailAddress baseAddress = parseMailAddress(request.params(FORWARD_BASE_ADDRESS));
         MailAddress destinationAddressToBeRemoved = parseMailAddress(request.params(FORWARD_DESTINATION_ADDRESS));
-        recipientRewriteTable.removeForwardMapping(
-            baseAddress.getLocalPart(),
-            baseAddress.getDomain(),
-            destinationAddressToBeRemoved.asString());
+        MappingSource source = MappingSource.fromUser(User.fromLocalPartWithDomain(baseAddress.getLocalPart(), baseAddress.getDomain()));
+        recipientRewriteTable.removeForwardMapping(source, destinationAddressToBeRemoved.asString());
         return halt(HttpStatus.OK_200);
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/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 1f5cd39..2625a46 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
@@ -40,11 +40,13 @@ import javax.ws.rs.Produces;
 
 import org.apache.james.core.Domain;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.User;
 import org.apache.james.domainlist.api.DomainList;
 import org.apache.james.domainlist.api.DomainListException;
 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.lib.Mappings;
 import org.apache.james.user.api.UsersRepository;
 import org.apache.james.user.api.UsersRepositoryException;
@@ -62,7 +64,6 @@ import org.slf4j.LoggerFactory;
 import com.github.steveash.guavate.Guavate;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableSortedSet;
-
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
@@ -129,6 +130,8 @@ public class GroupsRoutes implements Routes {
                 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());
     }
@@ -159,7 +162,8 @@ public class GroupsRoutes implements Routes {
         ensureRegisteredDomain(domain);
         ensureNotShadowingAnotherAddress(groupAddress);
         MailAddress userAddress = parseMailAddress(request.params(USER_ADDRESS));
-        recipientRewriteTable.addGroupMapping(groupAddress.getLocalPart(), domain, userAddress.asString());
+        MappingSource source = MappingSource.fromUser(User.fromLocalPartWithDomain(groupAddress.getLocalPart(), domain));
+        recipientRewriteTable.addGroupMapping(source, userAddress.asString());
         return halt(HttpStatus.CREATED_201);
     }
 
@@ -201,10 +205,10 @@ public class GroupsRoutes implements Routes {
     public HaltException removeFromGroup(Request request, Response response) throws JsonExtractException, AddressException, RecipientRewriteTableException {
         MailAddress groupAddress = parseMailAddress(request.params(GROUP_ADDRESS));
         MailAddress userAddress = parseMailAddress(request.params(USER_ADDRESS));
-        recipientRewriteTable.removeGroupMapping(
-            groupAddress.getLocalPart(),
-            groupAddress.getDomain(),
-            userAddress.asString());
+        MappingSource source = MappingSource
+            .fromUser(
+                User.fromLocalPartWithDomain(groupAddress.getLocalPart(), groupAddress.getDomain()));
+        recipientRewriteTable.removeGroupMapping(source, userAddress.asString());
         return halt(HttpStatus.OK_200);
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/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 08306a5..ea00515 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
@@ -44,6 +44,7 @@ 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.MappingSource;
 import org.apache.james.rrt.memory.MemoryRecipientRewriteTable;
 import org.apache.james.user.api.UsersRepository;
 import org.apache.james.user.memory.MemoryUsersRepository;
@@ -363,9 +364,9 @@ class ForwardRoutesTest {
         @BeforeEach
         void setup() throws Exception {
             super.setUp();
-            memoryRecipientRewriteTable.addErrorMapping("error", DOMAIN, "disabled");
-            memoryRecipientRewriteTable.addRegexMapping("regex", DOMAIN, ".*@b\\.com");
-            memoryRecipientRewriteTable.addAliasDomainMapping(Domain.of("alias"), DOMAIN);
+            memoryRecipientRewriteTable.addErrorMapping(MappingSource.fromUser("error", DOMAIN), "disabled");
+            memoryRecipientRewriteTable.addRegexMapping(MappingSource.fromUser("regex", DOMAIN), ".*@b\\.com");
+            memoryRecipientRewriteTable.addAliasDomainMapping(MappingSource.fromDomain(Domain.of("alias")), DOMAIN);
         }
 
     }
@@ -524,7 +525,7 @@ class ForwardRoutesTest {
         void putShouldReturnErrorWhenRecipientRewriteTableExceptionIsThrown() throws Exception {
             doThrow(RecipientRewriteTableException.class)
                 .when(memoryRecipientRewriteTable)
-                .addForwardMapping(anyString(), any(), anyString());
+                .addForwardMapping(any(), anyString());
 
             when()
                 .put(ALICE + SEPARATOR + "targets" + SEPARATOR + BOB)
@@ -537,7 +538,7 @@ class ForwardRoutesTest {
         void putShouldReturnErrorWhenErrorMappingExceptionIsThrown() throws Exception {
             doThrow(RecipientRewriteTable.ErrorMappingException.class)
                 .when(memoryRecipientRewriteTable)
-                .addForwardMapping(anyString(), any(), anyString());
+                .addForwardMapping(any(), anyString());
 
             when()
                 .put(ALICE + SEPARATOR + "targets" + SEPARATOR + BOB)
@@ -550,7 +551,7 @@ class ForwardRoutesTest {
         void putShouldReturnErrorWhenRuntimeExceptionIsThrown() throws Exception {
             doThrow(RuntimeException.class)
                 .when(memoryRecipientRewriteTable)
-                .addForwardMapping(anyString(), any(), anyString());
+                .addForwardMapping(any(), anyString());
 
             when()
                 .put(ALICE + SEPARATOR + "targets" + SEPARATOR + BOB)
@@ -602,7 +603,7 @@ class ForwardRoutesTest {
         void deleteShouldReturnErrorWhenRecipientRewriteTableExceptionIsThrown() throws Exception {
             doThrow(RecipientRewriteTableException.class)
                 .when(memoryRecipientRewriteTable)
-                .removeForwardMapping(anyString(), any(), anyString());
+                .removeForwardMapping(any(), anyString());
 
             when()
                 .delete(ALICE + SEPARATOR + "targets" + SEPARATOR + BOB)
@@ -615,7 +616,7 @@ class ForwardRoutesTest {
         void deleteShouldReturnErrorWhenErrorMappingExceptionIsThrown() throws Exception {
             doThrow(RecipientRewriteTable.ErrorMappingException.class)
                 .when(memoryRecipientRewriteTable)
-                .removeForwardMapping(anyString(), any(), anyString());
+                .removeForwardMapping(any(), anyString());
 
             when()
                 .delete(ALICE + SEPARATOR + "targets" + SEPARATOR + BOB)
@@ -628,7 +629,7 @@ class ForwardRoutesTest {
         void deleteShouldReturnErrorWhenRuntimeExceptionIsThrown() throws Exception {
             doThrow(RuntimeException.class)
                 .when(memoryRecipientRewriteTable)
-                .removeForwardMapping(anyString(), any(), anyString());
+                .removeForwardMapping(any(), anyString());
 
             when()
                 .delete(ALICE + SEPARATOR + "targets" + SEPARATOR + BOB)

http://git-wip-us.apache.org/repos/asf/james-project/blob/ff8107ef/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 1dd9c6c..8011720 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
@@ -41,6 +41,7 @@ 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.MappingSource;
 import org.apache.james.rrt.memory.MemoryRecipientRewriteTable;
 import org.apache.james.user.api.UsersRepository;
 import org.apache.james.user.api.UsersRepositoryException;
@@ -370,9 +371,9 @@ class GroupsRoutesTest {
         @BeforeEach
         void setup() throws Exception {
             super.setUp();
-            memoryRecipientRewriteTable.addErrorMapping("error", DOMAIN, "disabled");
-            memoryRecipientRewriteTable.addRegexMapping("regex", DOMAIN, ".*@b\\.com");
-            memoryRecipientRewriteTable.addAliasDomainMapping(Domain.of("alias"), DOMAIN);
+            memoryRecipientRewriteTable.addErrorMapping(MappingSource.fromUser("error", DOMAIN), "disabled");
+            memoryRecipientRewriteTable.addRegexMapping(MappingSource.fromUser("regex", DOMAIN), ".*@b\\.com");
+            memoryRecipientRewriteTable.addAliasDomainMapping(MappingSource.fromDomain(Domain.of("alias")), DOMAIN);
 
         }
 
@@ -527,7 +528,7 @@ class GroupsRoutesTest {
         void putShouldReturnErrorWhenRecipientRewriteTableExceptionIsThrown() throws Exception {
             doThrow(RecipientRewriteTableException.class)
                 .when(memoryRecipientRewriteTable)
-                .addGroupMapping(anyString(), any(), anyString());
+                .addGroupMapping(any(), anyString());
 
             when()
                 .put(GROUP1 + SEPARATOR + GROUP2)
@@ -540,7 +541,7 @@ class GroupsRoutesTest {
         void putShouldReturnErrorWhenErrorMappingExceptionIsThrown() throws Exception {
             doThrow(RecipientRewriteTable.ErrorMappingException.class)
                 .when(memoryRecipientRewriteTable)
-                .addGroupMapping(anyString(), any(), anyString());
+                .addGroupMapping(any(), anyString());
 
             when()
                 .put(GROUP1 + SEPARATOR + GROUP2)
@@ -553,7 +554,7 @@ class GroupsRoutesTest {
         void putShouldReturnErrorWhenRuntimeExceptionIsThrown() throws Exception {
             doThrow(RuntimeException.class)
                 .when(memoryRecipientRewriteTable)
-                .addGroupMapping(anyString(), any(), anyString());
+                .addGroupMapping(any(), anyString());
 
             when()
                 .put(GROUP1 + SEPARATOR + GROUP2)
@@ -605,7 +606,7 @@ class GroupsRoutesTest {
         void deleteShouldReturnErrorWhenRecipientRewriteTableExceptionIsThrown() throws Exception {
             doThrow(RecipientRewriteTableException.class)
                 .when(memoryRecipientRewriteTable)
-                .removeGroupMapping(anyString(), any(), anyString());
+                .removeGroupMapping(any(), anyString());
 
             when()
                 .delete(GROUP1 + SEPARATOR + GROUP2)
@@ -618,7 +619,7 @@ class GroupsRoutesTest {
         void deleteShouldReturnErrorWhenErrorMappingExceptionIsThrown() throws Exception {
             doThrow(RecipientRewriteTable.ErrorMappingException.class)
                 .when(memoryRecipientRewriteTable)
-                .removeGroupMapping(anyString(), any(), anyString());
+                .removeGroupMapping(any(), anyString());
 
             when()
                 .delete(GROUP1 + SEPARATOR + GROUP2)
@@ -631,7 +632,7 @@ class GroupsRoutesTest {
         void deleteShouldReturnErrorWhenRuntimeExceptionIsThrown() throws Exception {
             doThrow(RuntimeException.class)
                 .when(memoryRecipientRewriteTable)
-                .removeGroupMapping(anyString(), any(), anyString());
+                .removeGroupMapping(any(), anyString());
 
             when()
                 .delete(GROUP1 + SEPARATOR + GROUP2)


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


[20/27] james-project git commit: JAMES-2366 create MailAddressConversionPolicy to handle mapping to MailAddress conversion

Posted by ma...@apache.org.
JAMES-2366 create MailAddressConversionPolicy to handle mapping to MailAddress conversion


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

Branch: refs/heads/master
Commit: ef5ff3f6fce8934410cdd469e6e2d93792ed9f32
Parents: 1ba2bfc
Author: Matthieu Baechler <ma...@apache.org>
Authored: Wed Apr 18 11:18:33 2018 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:45:26 2018 +0200

----------------------------------------------------------------------
 .../java/org/apache/james/rrt/lib/Mapping.java  | 62 +++++++++++++++-----
 1 file changed, 48 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/ef5ff3f6/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
index e32dc1e..7f0e684 100644
--- a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
@@ -44,7 +44,8 @@ public interface Mapping {
     static Mapping of(Type type, String mapping) {
         UserRewritter.MappingUserRewriter rewriter = selectRewriter(type);
         IdentityMappingPolicy identityMappingPolicy = selectIdentityPolicy(type);
-        return new Impl(type, mapping, rewriter.generateUserRewriter(mapping), identityMappingPolicy);
+        MailAddressConversionPolicy mailAddressConversionPolicy = selectMailAddressConversionPolicy(type);
+        return new Impl(type, mapping, rewriter.generateUserRewriter(mapping), identityMappingPolicy, mailAddressConversionPolicy);
     }
 
     static UserRewritter.MappingUserRewriter selectRewriter(Type type) {
@@ -77,6 +78,40 @@ public interface Mapping {
         throw new IllegalStateException("unhandle enum type");
     }
 
+    enum MailAddressConversionPolicy {
+        ToEmpty {
+            @Override
+            Optional<MailAddress> convert(String mapping) {
+                return Optional.empty();
+            }
+        },
+        ToMailAddress {
+            @Override
+            Optional<MailAddress> convert(String mapping) {
+                try {
+                    return Optional.of(new MailAddress(mapping));
+                } catch (AddressException e) {
+                    return Optional.empty();
+                }
+            }
+        };
+
+        abstract Optional<MailAddress> convert(String mapping);
+    }
+
+    static MailAddressConversionPolicy selectMailAddressConversionPolicy(Type type) {
+        switch (type) {
+            case Regex:
+            case Domain:
+            case Error:
+                return MailAddressConversionPolicy.ToEmpty;
+            case Forward:
+            case Group:
+            case Address:
+                return MailAddressConversionPolicy.ToMailAddress;
+            }
+        throw new IllegalStateException("unhandle enum type");
+    }
 
     static Mapping address(String mapping) {
         return of(Type.Address, mapping);
@@ -181,14 +216,20 @@ public interface Mapping {
         private final String mapping;
         private final UserRewritter rewriter;
         private final IdentityMappingPolicy identityMappingPolicy;
+        private final MailAddressConversionPolicy mailAddressConversionPolicy;
 
-        private Impl(Type type, String mapping, UserRewritter rewriter, IdentityMappingPolicy identityMappingBehaviour) {
+        private Impl(Type type,
+                     String mapping,
+                     UserRewritter rewriter,
+                     IdentityMappingPolicy identityMappingBehaviour,
+                     MailAddressConversionPolicy mailAddressConversionPolicy) {
             Preconditions.checkNotNull(type);
             Preconditions.checkNotNull(mapping);
             this.type = type;
             this.mapping = mapping;
             this.rewriter = rewriter;
             this.identityMappingPolicy = identityMappingBehaviour;
+            this.mailAddressConversionPolicy = mailAddressConversionPolicy;
         }
 
         @Override
@@ -235,18 +276,6 @@ public interface Mapping {
         }
 
         @Override
-        public Optional<MailAddress> asMailAddress() {
-            if (type != Type.Address && type != Type.Forward && type != Type.Group) {
-                return Optional.empty();
-            }
-            try {
-                return Optional.of(new MailAddress(mapping));
-            } catch (AddressException e) {
-                return Optional.empty();
-            }
-        }
-
-        @Override
         public Optional<User> rewriteUser(User user) throws AddressException {
             return rewriter.rewrite(user);
         }
@@ -257,6 +286,11 @@ public interface Mapping {
         }
 
         @Override
+        public Optional<MailAddress> asMailAddress() {
+            return mailAddressConversionPolicy.convert(mapping);
+        }
+
+        @Override
         public final boolean equals(Object other) {
             if (other instanceof Impl) {
                 Impl otherMapping = (Impl) other;


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


[17/27] james-project git commit: JAMES-2366 remove MappingImpl and simulate an Algebric Type with factories and functions

Posted by ma...@apache.org.
JAMES-2366 remove MappingImpl and simulate an Algebric Type with factories and functions


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

Branch: refs/heads/master
Commit: 1ba2bfc3b353bf22498eed22d4c64df6482545e2
Parents: 4683d76
Author: Matthieu Baechler <ma...@apache.org>
Authored: Wed Apr 18 11:08:01 2018 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:45:26 2018 +0200

----------------------------------------------------------------------
 .../james/cli/DataCommandsIntegrationTest.java  |   6 +-
 .../java/org/apache/james/rrt/lib/Mapping.java  | 250 ++++++++++++++-----
 .../org/apache/james/rrt/lib/MappingTest.java   | 166 ++++++++++++
 .../rrt/file/XMLRecipientRewriteTableTest.java  |   8 +-
 .../rrt/lib/AbstractRecipientRewriteTable.java  |  37 ++-
 .../org/apache/james/rrt/lib/MappingImpl.java   | 164 ------------
 .../org/apache/james/rrt/lib/MappingsImpl.java  |   4 +-
 .../lib/RecipientRewriteTableManagement.java    |   4 +-
 .../lib/AbstractRecipientRewriteTableTest.java  |  92 +++----
 .../apache/james/rrt/lib/MappingImplTest.java   | 221 ----------------
 .../apache/james/rrt/lib/MappingsImplTest.java  | 102 ++++----
 11 files changed, 484 insertions(+), 570 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/1ba2bfc3/server/container/cli-integration/src/test/java/org/apache/james/cli/DataCommandsIntegrationTest.java
----------------------------------------------------------------------
diff --git a/server/container/cli-integration/src/test/java/org/apache/james/cli/DataCommandsIntegrationTest.java b/server/container/cli-integration/src/test/java/org/apache/james/cli/DataCommandsIntegrationTest.java
index 03c29c2..b6579d5 100644
--- a/server/container/cli-integration/src/test/java/org/apache/james/cli/DataCommandsIntegrationTest.java
+++ b/server/container/cli-integration/src/test/java/org/apache/james/cli/DataCommandsIntegrationTest.java
@@ -29,7 +29,7 @@ import org.apache.james.MemoryJmapTestRule;
 import org.apache.james.cli.util.OutputCapture;
 import org.apache.james.mailbox.store.search.ListeningMessageSearchIndex;
 import org.apache.james.modules.server.JMXServerModule;
-import org.apache.james.rrt.lib.MappingImpl;
+import org.apache.james.rrt.lib.Mapping;
 import org.apache.james.rrt.lib.Mappings;
 import org.apache.james.rrt.lib.MappingsImpl;
 import org.apache.james.utils.DataProbeImpl;
@@ -141,7 +141,7 @@ public class DataCommandsIntegrationTest {
                 new AbstractMap.SimpleEntry<String, Mappings>(
                     MAIL_ADDRESS,
                     MappingsImpl.builder()
-                        .add(MappingImpl.address(redirectionAddress))
+                        .add(Mapping.address(redirectionAddress))
                         .build()));
     }
 
@@ -190,7 +190,7 @@ public class DataCommandsIntegrationTest {
                 new AbstractMap.SimpleEntry<String, Mappings>(
                     MAIL_ADDRESS,
                     MappingsImpl.builder()
-                        .add(MappingImpl.regex(regex))
+                        .add(Mapping.regex(regex))
                         .build()));
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/1ba2bfc3/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
index 751000d..e32dc1e 100644
--- a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
@@ -26,16 +26,82 @@ import java.util.stream.Stream;
 
 import javax.mail.internet.AddressException;
 
-import org.apache.commons.lang3.NotImplementedException;
 import org.apache.james.core.Domain;
 import org.apache.james.core.MailAddress;
 import org.apache.james.core.User;
 import org.apache.james.rrt.api.RecipientRewriteTableException;
 
+import com.google.common.base.Objects;
 import com.google.common.base.Preconditions;
 
 public interface Mapping {
 
+    static Mapping of(String mapping) {
+        Type type = Mapping.detectType(mapping);
+        return of(type, type.withoutPrefix(mapping));
+    }
+
+    static Mapping of(Type type, String mapping) {
+        UserRewritter.MappingUserRewriter rewriter = selectRewriter(type);
+        IdentityMappingPolicy identityMappingPolicy = selectIdentityPolicy(type);
+        return new Impl(type, mapping, rewriter.generateUserRewriter(mapping), identityMappingPolicy);
+    }
+
+    static UserRewritter.MappingUserRewriter selectRewriter(Type type) {
+        switch (type) {
+            case Regex:
+                return new UserRewritter.RegexRewriter();
+            case Domain:
+                return new UserRewritter.DomainRewriter();
+            case Error:
+                return new UserRewritter.NoneRewriter();
+            case Forward:
+            case Group:
+            case Address:
+                return new UserRewritter.ReplaceRewriter();
+        }
+        throw new IllegalStateException("unhandle enum type");
+    }
+
+    static IdentityMappingPolicy selectIdentityPolicy(Type type) {
+        switch (type) {
+            case Regex:
+            case Domain:
+            case Error:
+            case Group:
+            case Address:
+                return IdentityMappingPolicy.Throw;
+            case Forward:
+                return IdentityMappingPolicy.ReturnIdentity;
+        }
+        throw new IllegalStateException("unhandle enum type");
+    }
+
+
+    static Mapping address(String mapping) {
+        return of(Type.Address, mapping);
+    }
+
+    static Mapping regex(String mapping) {
+        return of(Type.Regex, mapping);
+    }
+
+    static Mapping error(String mapping) {
+        return of(Type.Error, mapping);
+    }
+
+    static Mapping domain(Domain mapping) {
+        return of(Type.Domain, mapping.asString());
+    }
+
+    static Mapping forward(String mapping) {
+        return of(Type.Forward, mapping);
+    }
+
+    static Mapping group(String mapping) {
+        return of(Type.Group, mapping);
+    }
+
     static Type detectType(String input) {
         if (input.startsWith(Type.Regex.asPrefix())) {
             return Type.Regex;
@@ -55,52 +121,18 @@ public interface Mapping {
         return Type.Address;
     }
 
-    Optional<MailAddress> asMailAddress();
-
     enum Type {
-        Regex("regex:", IdentityMappingBehaviour.Throw) {
-            @Override
-            protected UserRewritter rewriter(String mapping) {
-                return new UserRewritter.RegexRewriter().generateUserRewriter(mapping);
-            }
-        },
-        Domain("domain:", IdentityMappingBehaviour.Throw) {
-            @Override
-            protected UserRewritter rewriter(String mapping) {
-                return new UserRewritter.DomainRewriter().generateUserRewriter(mapping);
-            }
-        },
-        Error("error:", IdentityMappingBehaviour.Throw) {
-            @Override
-            protected UserRewritter rewriter(String mapping) {
-                return new UserRewritter.NoneRewriter().generateUserRewriter(mapping);
-            }
-        },
-        Forward("forward:", IdentityMappingBehaviour.ReturnIdentity) {
-            @Override
-            protected UserRewritter rewriter(String mapping) {
-                return new UserRewritter.ReplaceRewriter().generateUserRewriter(mapping);
-            }
-        },
-        Group("group:", IdentityMappingBehaviour.Throw) {
-            @Override
-            protected UserRewritter rewriter(String mapping) {
-                return new UserRewritter.ReplaceRewriter().generateUserRewriter(mapping);
-            }
-        },
-        Address("", IdentityMappingBehaviour.Throw) {
-            @Override
-            protected UserRewritter rewriter(String mapping) {
-                return new UserRewritter.ReplaceRewriter().generateUserRewriter(mapping);
-            }
-        };
+        Regex("regex:"),
+        Domain("domain:"),
+        Error("error:"),
+        Forward("forward:"),
+        Group("group:"),
+        Address("");
 
         private final String asPrefix;
-        private final IdentityMappingBehaviour identityMappingBehaviour;
 
-        Type(String asPrefix, IdentityMappingBehaviour identityMappingBehaviour) {
+        Type(String asPrefix) {
             this.asPrefix = asPrefix;
-            this.identityMappingBehaviour = identityMappingBehaviour;
         }
 
         public String asPrefix() {
@@ -120,28 +152,130 @@ public interface Mapping {
                 || mapping.startsWith(Group.asPrefix());
         }
 
-        public IdentityMappingBehaviour getIdentityMappingBehaviour() {
-            return identityMappingBehaviour;
-        }
+    }
 
-        protected abstract UserRewritter rewriter(String mapping);
+    enum IdentityMappingPolicy {
+        Throw {
+            @Override
+            public Stream<Mapping> handleIdentity(Stream<Mapping> mapping) {
+                throw new SkipMappingProcessingException();
+            }
+        },
+        ReturnIdentity {
+            @Override
+            public Stream<Mapping> handleIdentity(Stream<Mapping> mapping) {
+                return mapping;
+            }
+        };
 
+        public abstract Stream<Mapping> handleIdentity(Stream<Mapping> mapping);
     }
 
-    enum IdentityMappingBehaviour {
-        Throw,
-        ReturnIdentity;
-
-        public Stream<Mapping> handleIdentity(Stream<Mapping> mapping) {
-            switch (this) {
-                case Throw:
-                    throw new SkipMappingProcessingException();
-                case ReturnIdentity:
-                    return mapping;
-                default:
-                    throw new NotImplementedException("Unknown IdentityMappingBehaviour : " + this);
+    Optional<MailAddress> asMailAddress();
+
+    Stream<Mapping> handleIdentity(Stream<Mapping> nonRecursiveResult);
+
+    class Impl implements Mapping {
+
+        private final Type type;
+        private final String mapping;
+        private final UserRewritter rewriter;
+        private final IdentityMappingPolicy identityMappingPolicy;
+
+        private Impl(Type type, String mapping, UserRewritter rewriter, IdentityMappingPolicy identityMappingBehaviour) {
+            Preconditions.checkNotNull(type);
+            Preconditions.checkNotNull(mapping);
+            this.type = type;
+            this.mapping = mapping;
+            this.rewriter = rewriter;
+            this.identityMappingPolicy = identityMappingBehaviour;
+        }
+
+        @Override
+        public String asString() {
+            return type.asPrefix() + mapping;
+        }
+
+        @Override
+        public boolean hasDomain() {
+            return mapping.contains("@");
+        }
+
+        @Override
+        public Mapping appendDomainIfNone(Supplier<Domain> domain) {
+            Preconditions.checkNotNull(domain);
+            if (hasDomain()) {
+                return this;
             }
+            return appendDomain(domain.get());
         }
+
+        @Override
+        public Mapping appendDomainFromThrowingSupplierIfNone(ThrowingDomainSupplier supplier) throws RecipientRewriteTableException {
+            Preconditions.checkNotNull(supplier);
+            if (hasDomain()) {
+                return this;
+            }
+            return appendDomain(supplier.get());
+        }
+
+        private Mapping appendDomain(Domain domain) {
+            return of(type, mapping + "@" + domain.asString());
+        }
+
+        @Override
+        public Type getType() {
+            return type;
+        }
+
+        @Override
+        public String getErrorMessage() {
+            Preconditions.checkState(getType() == Type.Error);
+            return mapping;
+        }
+
+        @Override
+        public Optional<MailAddress> asMailAddress() {
+            if (type != Type.Address && type != Type.Forward && type != Type.Group) {
+                return Optional.empty();
+            }
+            try {
+                return Optional.of(new MailAddress(mapping));
+            } catch (AddressException e) {
+                return Optional.empty();
+            }
+        }
+
+        @Override
+        public Optional<User> rewriteUser(User user) throws AddressException {
+            return rewriter.rewrite(user);
+        }
+
+        @Override
+        public Stream<Mapping> handleIdentity(Stream<Mapping> nonRecursiveResult) {
+            return identityMappingPolicy.handleIdentity(nonRecursiveResult);
+        }
+
+        @Override
+        public final boolean equals(Object other) {
+            if (other instanceof Impl) {
+                Impl otherMapping = (Impl) other;
+                return Objects.equal(type, otherMapping.type)
+                    && Objects.equal(mapping, otherMapping.mapping);
+            }
+            return false;
+        }
+
+        @Override
+        public final int hashCode() {
+            return Objects.hashCode(type, mapping);
+        }
+
+        @Override
+        public String toString() {
+            return "Mapping{type=" + type + " mapping=" + mapping + "}";
+        }
+
     }
 
     Type getType();

http://git-wip-us.apache.org/repos/asf/james-project/blob/1ba2bfc3/server/data/data-api/src/test/java/org/apache/james/rrt/lib/MappingTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/test/java/org/apache/james/rrt/lib/MappingTest.java b/server/data/data-api/src/test/java/org/apache/james/rrt/lib/MappingTest.java
index 8297fca..d14dd6b 100644
--- a/server/data/data-api/src/test/java/org/apache/james/rrt/lib/MappingTest.java
+++ b/server/data/data-api/src/test/java/org/apache/james/rrt/lib/MappingTest.java
@@ -21,9 +21,13 @@ package org.apache.james.rrt.lib;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
+import org.apache.james.core.Domain;
+import org.apache.james.core.MailAddress;
 import org.apache.james.rrt.lib.Mapping.Type;
 import org.junit.jupiter.api.Test;
 
+import nl.jqno.equalsverifier.EqualsVerifier;
+
 public class MappingTest {
 
     @Test
@@ -139,4 +143,166 @@ public class MappingTest {
         assertThatThrownBy(() -> Type.Forward.withoutPrefix("mapping"))
             .isInstanceOf(IllegalArgumentException.class);
     }
+
+    @Test
+    public void beanShouldRespectBeanContract() {
+        EqualsVerifier.forClass(Mapping.Impl.class)
+            .verify();
+    }
+
+    @Test
+    public void addressFactoryMethodShouldThrowOnNull() {
+        assertThatThrownBy(() -> Mapping.address(null))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    public void regexFactoryMethodShouldThrowOnNull() {
+        assertThatThrownBy(() -> Mapping.regex(null))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    public void domainFactoryMethodShouldThrowOnNull() {
+        assertThatThrownBy(() -> Mapping.domain(null))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    public void errorFactoryMethodShouldThrowOnNull() {
+        assertThatThrownBy(() -> Mapping.error(null))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    public void forwardFactoryMethodShouldThrowOnNull() {
+        assertThatThrownBy(() -> Mapping.forward(null))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    public void groupFactoryMethodShouldThrowOnNull() {
+        assertThatThrownBy(() -> Mapping.group(null))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    public void hasDomainShouldReturnTrueWhenMappingContainAtMark() {
+        assertThat(Mapping.address("a@b").hasDomain()).isTrue();
+    }
+
+    @Test
+    public void hasDomainShouldReturnFalseWhenMappingIsEmpty() {
+        assertThat(Mapping.address("").hasDomain()).isFalse();
+    }
+
+    @Test
+    public void hasDomainShouldReturnFalseWhenMappingIsBlank() {
+        assertThat(Mapping.address(" ").hasDomain()).isFalse();
+    }
+
+    @Test
+    public void hasDomainShouldReturnFalseWhenMappingDoesntContainAtMark() {
+        assertThat(Mapping.address("abc").hasDomain()).isFalse();
+    }
+
+    @Test
+    public void appendDefaultDomainShouldWorkOnValidDomain() {
+        assertThat(Mapping.address("abc").appendDomainIfNone(() -> Domain.of("domain"))).isEqualTo(Mapping.address("abc@domain"));
+    }
+
+    @Test
+    public void appendDefaultDomainShouldNotAddDomainWhenMappingAlreadyContainsDomains() {
+        assertThat(Mapping.address("abc@d").appendDomainIfNone(() -> Domain.of("domain"))).isEqualTo(Mapping.address("abc@d"));
+    }
+
+    @Test
+    public void appendDomainShouldThrowWhenNullDomain() {
+        assertThatThrownBy(() -> Mapping.address("abc@d").appendDomainIfNone(null)).isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    public void getTypeShouldReturnAddressWhenNoPrefix() {
+        assertThat(Mapping.address("abc").getType()).isEqualTo(Mapping.Type.Address);
+    }
+
+    @Test
+    public void getTypeShouldReturnAddressWhenEmpty() {
+        assertThat(Mapping.address("").getType()).isEqualTo(Mapping.Type.Address);
+    }
+
+    @Test
+    public void getTypeShouldReturnRegexWhenRegexPrefix() {
+        assertThat(Mapping.regex("abc").getType()).isEqualTo(Mapping.Type.Regex);
+    }
+
+    @Test
+    public void getTypeShouldReturnErrorWhenErrorPrefix() {
+        assertThat(Mapping.error("abc").getType()).isEqualTo(Mapping.Type.Error);
+    }
+
+    @Test
+    public void getTypeShouldReturnDomainWhenDomainPrefix() {
+        assertThat(Mapping.domain(Domain.of("abc")).getType()).isEqualTo(Mapping.Type.Domain);
+    }
+
+    @Test
+    public void getTypeShouldReturnForwardWhenForwardPrefix() {
+        assertThat(Mapping.forward("abc").getType()).isEqualTo(Mapping.Type.Forward);
+    }
+
+    @Test
+    public void getTypeShouldReturnGroupWhenGroupPrefix() {
+        assertThat(Mapping.group("abc").getType()).isEqualTo(Mapping.Type.Group);
+    }
+
+    @Test
+    public void getErrorMessageShouldThrowWhenMappingIsNotAnError() {
+        assertThatThrownBy(() -> Mapping.domain(Domain.of("toto")).getErrorMessage())
+            .isInstanceOf(IllegalStateException.class);
+    }
+
+    @Test
+    public void getErrorMessageShouldReturnMessageWhenErrorWithMessage() {
+        assertThat(Mapping.error("toto").getErrorMessage()).isEqualTo("toto");
+    }
+
+    @Test
+    public void getErrorMessageShouldReturnWhenErrorWithoutMessage() {
+        assertThat(Mapping.error("").getErrorMessage()).isEqualTo("");
+    }
+
+    @Test
+    public void asMailAddressShouldReturnMappingValueForAddress() throws Exception {
+        assertThat(Mapping.address("value@domain").asMailAddress())
+            .contains(new MailAddress("value@domain"));
+    }
+
+    @Test
+    public void asMailAddressShouldReturnEmptyOnInvalidAddress() {
+        assertThat(Mapping.address("value").asMailAddress())
+            .isEmpty();
+    }
+
+    @Test
+    public void asMailAddressShouldReturnEmptyForError() {
+        assertThat(Mapping.error("value").asMailAddress()).isEmpty();
+    }
+
+    @Test
+    public void asMailAddressShouldReturnEmptyForRegex() {
+        assertThat(Mapping.regex("value").asMailAddress()).isEmpty();
+    }
+
+    @Test
+    public void asMailAddressShouldReturnEmptyForDomain() {
+        assertThat(Mapping.domain(Domain.of("value")).asMailAddress()).isEmpty();
+    }
+
+    @Test
+    public void asMailAddressShouldReturnMappingValueForForward() throws Exception {
+        assertThat(Mapping.forward("value@domain").asMailAddress())
+            .contains(new MailAddress("value@domain"));
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/1ba2bfc3/server/data/data-file/src/test/java/org/apache/james/rrt/file/XMLRecipientRewriteTableTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-file/src/test/java/org/apache/james/rrt/file/XMLRecipientRewriteTableTest.java b/server/data/data-file/src/test/java/org/apache/james/rrt/file/XMLRecipientRewriteTableTest.java
index 9287842..25defc6 100644
--- a/server/data/data-file/src/test/java/org/apache/james/rrt/file/XMLRecipientRewriteTableTest.java
+++ b/server/data/data-file/src/test/java/org/apache/james/rrt/file/XMLRecipientRewriteTableTest.java
@@ -29,7 +29,7 @@ import org.apache.james.rrt.lib.AbstractRecipientRewriteTable;
 import org.apache.james.rrt.lib.AbstractRecipientRewriteTableTest;
 import org.apache.james.rrt.lib.Mapping;
 import org.apache.james.rrt.lib.Mapping.Type;
-import org.apache.james.rrt.lib.MappingImpl;
+import org.apache.james.rrt.lib.Mapping;
 import org.apache.james.rrt.lib.Mappings;
 import org.apache.james.rrt.lib.MappingsImpl;
 import org.junit.After;
@@ -69,7 +69,7 @@ public class XMLRecipientRewriteTableTest extends AbstractRecipientRewriteTableT
 
             @Override
             public void addAddressMapping(String user, Domain domain, String address) throws RecipientRewriteTableException {
-                addMapping(user, domain, MappingImpl.address(address));
+                addMapping(user, domain, Mapping.address(address));
             }
         };
     }
@@ -85,7 +85,7 @@ public class XMLRecipientRewriteTableTest extends AbstractRecipientRewriteTableT
             .orElse(MappingsImpl.empty());
 
         Mappings updatedMappings = MappingsImpl.from(mappings)
-            .add(MappingImpl.of(type, mapping))
+            .add(Mapping.of(type, mapping))
             .build();
 
         updateConfiguration(user, domain, mappings, updatedMappings);
@@ -95,7 +95,7 @@ public class XMLRecipientRewriteTableTest extends AbstractRecipientRewriteTableT
         Mappings oldMappings = Optional.ofNullable(virtualUserTable.getUserDomainMappings(user, domain))
             .orElseThrow(() -> new RecipientRewriteTableException("Cannot remove from null mappings"));
 
-        Mappings updatedMappings = oldMappings.remove(MappingImpl.of(type, mapping));
+        Mappings updatedMappings = oldMappings.remove(Mapping.of(type, mapping));
 
         updateConfiguration(user, domain, oldMappings, updatedMappings);
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/1ba2bfc3/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
index 08e4c5b..4a22f4b 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
@@ -127,7 +127,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
 
         Function<User, Stream<Mapping>> convertAndRecurseMapping =
             Throwing
-                .function((User rewrittenUser) -> convertAndRecurseMapping(associatedMapping.getType(), originalUser, rewrittenUser, remainingLoops))
+                .function((User rewrittenUser) -> convertAndRecurseMapping(associatedMapping, originalUser, rewrittenUser, remainingLoops))
                 .sneakyThrow();
 
         return associatedMapping.rewriteUser(originalUser)
@@ -136,18 +136,17 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
             .orElse(Stream.empty());
     }
 
-    private Stream<Mapping> convertAndRecurseMapping(Type mappingType, User originalUser, User rewrittenUser, int remainingLoops) throws ErrorMappingException, RecipientRewriteTableException {
+    private Stream<Mapping> convertAndRecurseMapping(Mapping mapping, User originalUser, User rewrittenUser, int remainingLoops) throws ErrorMappingException, RecipientRewriteTableException {
         LOGGER.debug("Valid virtual user mapping {} to {}", originalUser, rewrittenUser);
 
-        Stream<Mapping> nonRecursiveResult = Stream.of(toMapping(rewrittenUser, mappingType));
+        Stream<Mapping> nonRecursiveResult = Stream.of(toMapping(rewrittenUser, mapping.getType()));
         if (!recursive) {
             return nonRecursiveResult;
         }
 
         // Check if the returned mapping is the same as the input. If so we need to handle identity to avoid loops.
         if (originalUser.equals(rewrittenUser)) {
-            return mappingType.getIdentityMappingBehaviour()
-                .handleIdentity(nonRecursiveResult);
+            return mapping.handleIdentity(nonRecursiveResult);
         } else {
             return recurseMapping(nonRecursiveResult, rewrittenUser, remainingLoops);
         }
@@ -167,12 +166,12 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
         switch (type) {
             case Forward:
             case Group:
-                return MappingImpl.of(type, rewrittenUser.asString());
+                return Mapping.of(type, rewrittenUser.asString());
             case Regex:
             case Domain:
             case Error:
             case Address:
-                return MappingImpl.address(rewrittenUser.asString());
+                return Mapping.address(rewrittenUser.asString());
         }
         throw new IllegalArgumentException("unhandled enum type");
     }
@@ -185,7 +184,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
             throw new RecipientRewriteTableException("Invalid regex: " + regex, e);
         }
 
-        MappingImpl mapping = MappingImpl.regex(regex);
+        Mapping mapping = Mapping.regex(regex);
         checkMapping(user, domain, mapping);
         LOGGER.info("Add regex mapping => {} for user: {} domain: {}", regex, user, domain.name());
         addMapping(user, domain, mapping);
@@ -195,12 +194,12 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
     @Override
     public void removeRegexMapping(String user, Domain domain, String regex) throws RecipientRewriteTableException {
         LOGGER.info("Remove regex mapping => {} for user: {} domain: {}", regex, user, domain.name());
-        removeMapping(user, domain, MappingImpl.regex(regex));
+        removeMapping(user, domain, Mapping.regex(regex));
     }
 
     @Override
     public void addAddressMapping(String user, Domain domain, String address) throws RecipientRewriteTableException {
-        Mapping mapping = MappingImpl.address(address)
+        Mapping mapping = Mapping.address(address)
             .appendDomainFromThrowingSupplierIfNone(this::defaultDomain);
 
         checkHasValidAddress(mapping);
@@ -226,7 +225,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
 
     @Override
     public void removeAddressMapping(String user, Domain domain, String address) throws RecipientRewriteTableException {
-        Mapping mapping = MappingImpl.address(address)
+        Mapping mapping = Mapping.address(address)
             .appendDomainFromThrowingSupplierIfNone(this::defaultDomain);
 
         LOGGER.info("Remove address mapping => {} for user: {} domain: {}", mapping, user, domain.name());
@@ -235,7 +234,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
 
     @Override
     public void addErrorMapping(String user, Domain domain, String error) throws RecipientRewriteTableException {
-        MappingImpl mapping = MappingImpl.error(error);
+        Mapping mapping = Mapping.error(error);
 
         checkMapping(user, domain, mapping);
         LOGGER.info("Add error mapping => {} for user: {} domain: {}", error, user, domain.name());
@@ -246,7 +245,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
     @Override
     public void removeErrorMapping(String user, Domain domain, String error) throws RecipientRewriteTableException {
         LOGGER.info("Remove error mapping => {} for user: {} domain: {}", error, user, domain.name());
-        removeMapping(user, domain, MappingImpl.error(error));
+        removeMapping(user, domain, Mapping.error(error));
     }
 
     @Override
@@ -260,18 +259,18 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
     @Override
     public void addAliasDomainMapping(Domain aliasDomain, Domain realDomain) throws RecipientRewriteTableException {
         LOGGER.info("Add domain mapping: {} => {}", aliasDomain, realDomain);
-        addMapping(null, aliasDomain, MappingImpl.domain(realDomain));
+        addMapping(null, aliasDomain, Mapping.domain(realDomain));
     }
 
     @Override
     public void removeAliasDomainMapping(Domain aliasDomain, Domain realDomain) throws RecipientRewriteTableException {
         LOGGER.info("Remove domain mapping: {} => {}", aliasDomain, realDomain);
-        removeMapping(null, aliasDomain, MappingImpl.domain(realDomain));
+        removeMapping(null, aliasDomain, Mapping.domain(realDomain));
     }
 
     @Override
     public void addForwardMapping(String user, Domain domain, String address) throws RecipientRewriteTableException {
-        Mapping mapping = MappingImpl.forward(address)
+        Mapping mapping = Mapping.forward(address)
             .appendDomainFromThrowingSupplierIfNone(this::defaultDomain);
 
         checkHasValidAddress(mapping);
@@ -283,7 +282,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
 
     @Override
     public void removeForwardMapping(String user, Domain domain, String address) throws RecipientRewriteTableException {
-        Mapping mapping = MappingImpl.forward(address)
+        Mapping mapping = Mapping.forward(address)
             .appendDomainFromThrowingSupplierIfNone(this::defaultDomain);
 
         LOGGER.info("Remove forward mapping => {} for user: {} domain: {}", mapping, user, domain.name());
@@ -292,7 +291,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
 
     @Override
     public void addGroupMapping(String user, Domain domain, String address) throws RecipientRewriteTableException {
-        Mapping mapping = MappingImpl.group(address)
+        Mapping mapping = Mapping.group(address)
             .appendDomainFromThrowingSupplierIfNone(this::defaultDomain);
 
         checkHasValidAddress(mapping);
@@ -304,7 +303,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
 
     @Override
     public void removeGroupMapping(String user, Domain domain, String address) throws RecipientRewriteTableException {
-        Mapping mapping = MappingImpl.group(address)
+        Mapping mapping = Mapping.group(address)
             .appendDomainFromThrowingSupplierIfNone(this::defaultDomain);
 
         LOGGER.info("Remove forward mapping => {} for user: {} domain: {}", mapping, user, domain.name());

http://git-wip-us.apache.org/repos/asf/james-project/blob/1ba2bfc3/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingImpl.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingImpl.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingImpl.java
deleted file mode 100644
index 87a2f8b..0000000
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingImpl.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- *   Licensed to the Apache Software Foundation (ASF) under one
- *   or more contributor license agreements.  See the NOTICE file
- *   distributed with this work for additional information
- *   regarding copyright ownership.  The ASF licenses this file
- *   to you under the Apache License, Version 2.0 (the
- *   "License"); you may not use this file except in compliance
- *   with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *   Unless required by applicable law or agreed to in writing,
- *   software distributed under the License is distributed on an
- *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *   KIND, either express or implied.  See the License for the
- *   specific language governing permissions and limitations
- *   under the License.
- *
- */
-
-package org.apache.james.rrt.lib;
-
-import java.io.Serializable;
-import java.util.Optional;
-import java.util.function.Supplier;
-
-import javax.mail.internet.AddressException;
-
-import org.apache.james.core.Domain;
-import org.apache.james.core.MailAddress;
-import org.apache.james.core.User;
-import org.apache.james.rrt.api.RecipientRewriteTableException;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-
-public class MappingImpl implements Mapping, Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    public static MappingImpl of(String mapping) {
-        Type type = Mapping.detectType(mapping);
-        return new MappingImpl(type, type.withoutPrefix(mapping));
-    }
-
-    public static MappingImpl of(Type type, String mapping) {
-        return new MappingImpl(type, mapping);
-    }
-    
-    public static MappingImpl address(String mapping) {
-        return new MappingImpl(Type.Address, mapping);
-    }
-
-    public static MappingImpl regex(String mapping) {
-        return new MappingImpl(Type.Regex, mapping);
-    }
-
-    public static MappingImpl error(String mapping) {
-        return new MappingImpl(Type.Error, mapping);
-    }
-
-    public static MappingImpl domain(Domain mapping) {
-        return new MappingImpl(Type.Domain, mapping.asString());
-    }
-
-    public static MappingImpl forward(String mapping) {
-        return new MappingImpl(Type.Forward, mapping);
-    }
-
-    public static MappingImpl group(String mapping) {
-        return new MappingImpl(Type.Group, mapping);
-    }
-    
-    private final Type type;
-    private final String mapping;
-
-    private MappingImpl(Type type, String mapping) {
-        Preconditions.checkNotNull(type);
-        Preconditions.checkNotNull(mapping);
-        this.type = type;
-        this.mapping = mapping;
-    }
-    
-    @Override
-    public String asString() {
-        return type.asPrefix() + mapping;
-    }
-    
-    @Override
-    public boolean hasDomain() {
-        return mapping.contains("@");
-    }
-
-    @Override
-    public Mapping appendDomainFromThrowingSupplierIfNone(ThrowingDomainSupplier supplier) throws RecipientRewriteTableException {
-        Preconditions.checkNotNull(supplier);
-        if (hasDomain()) {
-            return this;
-        }
-        return appendDomain(supplier.get());
-    }
-
-    @Override
-    public Mapping appendDomainIfNone(Supplier<Domain> domain) {
-        Preconditions.checkNotNull(domain);
-        if (hasDomain()) {
-            return this;
-        }
-        return appendDomain(domain.get());
-    }
-
-    private MappingImpl appendDomain(Domain domain) {
-        return new MappingImpl(type, mapping + "@" + domain.asString());
-    }
-
-    @Override
-    public Type getType() {
-        return type;
-    }
-    
-    @Override
-    public String getErrorMessage() {
-        Preconditions.checkState(getType() == Type.Error);
-        return mapping;
-    }
-
-    @Override
-    public Optional<MailAddress> asMailAddress() {
-        if (type != Type.Address && type != Type.Forward && type != Type.Group) {
-            return Optional.empty();
-        }
-        try {
-            return Optional.of(new MailAddress(mapping));
-        } catch (AddressException e) {
-            return Optional.empty();
-        }
-    }
-
-    @Override
-    public Optional<User> rewriteUser(User user) throws AddressException {
-        return type.rewriter(mapping)
-            .rewrite(user);
-    }
-
-    @Override
-    public final boolean equals(Object other) {
-        if (other instanceof MappingImpl) {
-            MappingImpl otherMapping = (MappingImpl) other;
-            return Objects.equal(type, otherMapping.type)
-                && Objects.equal(mapping, otherMapping.mapping);
-        }
-        return false;
-    }
-
-    @Override
-    public final int hashCode() {
-        return Objects.hashCode(type, mapping);
-    }
-
-    @Override
-    public String toString() {
-        return "MappingImpl{type=" + type + " mapping=" + mapping + "}";
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/1ba2bfc3/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingsImpl.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingsImpl.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingsImpl.java
index 3b56c9e..6c042ff 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingsImpl.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingsImpl.java
@@ -99,7 +99,7 @@ public class MappingsImpl implements Mappings, Serializable {
     
     public static MappingsImpl fromCollection(Collection<String> mappings) {
         return fromMappings(mappings.stream()
-            .map(MappingImpl::of));
+            .map(Mapping::of));
     }
     
     public static MappingsImpl fromMappings(Stream<Mapping> mappings) {
@@ -131,7 +131,7 @@ public class MappingsImpl implements Mappings, Serializable {
         }
 
         public Builder add(String mapping) {
-            return add(MappingImpl.of(mapping));
+            return add(Mapping.of(mapping));
         }
 
         public Builder add(Mapping mapping) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/1ba2bfc3/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableManagement.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableManagement.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableManagement.java
index 3da96e3..14aa1c8 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableManagement.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableManagement.java
@@ -91,12 +91,12 @@ public class RecipientRewriteTableManagement extends StandardMBean implements Re
 
     @Override
     public void addMapping(String user, String domain, String mapping) throws RecipientRewriteTableException {
-        rrt.addMapping(user, Domain.of(domain), MappingImpl.of(mapping));
+        rrt.addMapping(user, Domain.of(domain), Mapping.of(mapping));
     }
 
     @Override
     public void removeMapping(String user, String domain, String mapping) throws RecipientRewriteTableException {
-        rrt.removeMapping(user, Domain.of(domain), MappingImpl.of(mapping));
+        rrt.removeMapping(user, Domain.of(domain), Mapping.of(mapping));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/james-project/blob/1ba2bfc3/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 84f204d..2873feb 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
@@ -73,7 +73,7 @@ public abstract class AbstractRecipientRewriteTableTest {
     public void testStoreAndGetMappings() throws ErrorMappingException, RecipientRewriteTableException {
         String user = "*";
         Domain domain = Domain.of("test");
-        virtualUserTable.addMapping(user, domain, MappingImpl.regex("prefix_.*:admin@test"));
+        virtualUserTable.addMapping(user, domain, Mapping.regex("prefix_.*:admin@test"));
         assertThat(virtualUserTable.getMappings("prefix_abc", domain)).isNotEmpty();
     }
 
@@ -90,18 +90,18 @@ public abstract class AbstractRecipientRewriteTableTest {
         assertThat(virtualUserTable.getMappings(user, domain)).describedAs("No mapping")
             .isEqualTo(MappingsImpl.empty());
 
-        virtualUserTable.addMapping(user, domain, MappingImpl.regex(regex));
-        virtualUserTable.addMapping(user, domain, MappingImpl.regex(regex2));
+        virtualUserTable.addMapping(user, domain, Mapping.regex(regex));
+        virtualUserTable.addMapping(user, domain, Mapping.regex(regex2));
         assertThat(virtualUserTable.getMappings(user, domain)).describedAs("Two mappings").hasSize(2);
         assertThat(virtualUserTable.getAllMappings()).describedAs("One mappingline").hasSize(1);
-        virtualUserTable.removeMapping(user, domain, MappingImpl.regex(regex));
+        virtualUserTable.removeMapping(user, domain, Mapping.regex(regex));
 
         assertThatThrownBy(() -> virtualUserTable.addRegexMapping(user, domain, invalidRegex))
             .describedAs("Invalid Mapping throw exception")
             .isInstanceOf(RecipientRewriteTableException.class);
 
 
-        virtualUserTable.removeMapping(user, domain, MappingImpl.regex(regex2));
+        virtualUserTable.removeMapping(user, domain, Mapping.regex(regex2));
 
 
         assertThat(virtualUserTable.getMappings(user, domain)).describedAs("No mapping")
@@ -116,19 +116,19 @@ public abstract class AbstractRecipientRewriteTableTest {
         String regex = "(.*)@localhost";
         String regex2 = "(.+)@test";
 
-        virtualUserTable.addMapping(user, Domain.LOCALHOST, MappingImpl.regex(regex));
-        virtualUserTable.addMapping(user, Domain.LOCALHOST, MappingImpl.regex(regex2));
-        virtualUserTable.addMapping(user2, Domain.LOCALHOST, MappingImpl.address(user + "@" + Domain.LOCALHOST.asString()));
+        virtualUserTable.addMapping(user, Domain.LOCALHOST, Mapping.regex(regex));
+        virtualUserTable.addMapping(user, Domain.LOCALHOST, Mapping.regex(regex2));
+        virtualUserTable.addMapping(user2, Domain.LOCALHOST, Mapping.address(user + "@" + Domain.LOCALHOST.asString()));
 
         assertThat(virtualUserTable.getAllMappings())
             .describedAs("One mappingline")
             .containsOnly(
                 Pair.of(user + "@" + Domain.LOCALHOST.asString(), MappingsImpl.builder()
-                    .add(MappingImpl.regex(regex))
-                    .add(MappingImpl.regex(regex2))
+                    .add(Mapping.regex(regex))
+                    .add(Mapping.regex(regex2))
                     .build()),
                 Pair.of(user2 + "@" + Domain.LOCALHOST.asString(), MappingsImpl.builder()
-                    .add(MappingImpl.address(user + "@" + Domain.LOCALHOST.asString()))
+                    .add(Mapping.address(user + "@" + Domain.LOCALHOST.asString()))
                     .build()));
     }
 
@@ -143,14 +143,14 @@ public abstract class AbstractRecipientRewriteTableTest {
         assertThat(virtualUserTable.getMappings(user, domain)).describedAs("No mapping")
             .isEqualTo(MappingsImpl.empty());
 
-        virtualUserTable.addMapping(user, domain, MappingImpl.address(address));
-        virtualUserTable.addMapping(user, domain, MappingImpl.address(address2));
+        virtualUserTable.addMapping(user, domain, Mapping.address(address));
+        virtualUserTable.addMapping(user, domain, Mapping.address(address2));
 
         assertThat(virtualUserTable.getMappings(user, domain)).describedAs("Two mappings").hasSize(2);
         assertThat(virtualUserTable.getAllMappings()).describedAs("One mappingline").hasSize(1);
 
-        virtualUserTable.removeMapping(user, domain, MappingImpl.address(address));
-        virtualUserTable.removeMapping(user, domain, MappingImpl.address(address2));
+        virtualUserTable.removeMapping(user, domain, Mapping.address(address));
+        virtualUserTable.removeMapping(user, domain, Mapping.address(address2));
 
         assertThat(virtualUserTable.getMappings(user, domain)).describedAs("No mapping")
             .isEqualTo(MappingsImpl.empty());
@@ -166,7 +166,7 @@ public abstract class AbstractRecipientRewriteTableTest {
         assertThat(virtualUserTable.getMappings(user, domain)).describedAs("No mapping")
             .isEqualTo(MappingsImpl.empty());
 
-        virtualUserTable.addMapping(user, domain, MappingImpl.error(error));
+        virtualUserTable.addMapping(user, domain, Mapping.error(error));
         assertThat(virtualUserTable.getAllMappings()).describedAs("One mappingline").hasSize(1);
 
         assertThatThrownBy(() ->
@@ -174,7 +174,7 @@ public abstract class AbstractRecipientRewriteTableTest {
             .describedAs("Exception thrown on to many mappings")
             .isInstanceOf(ErrorMappingException.class);
 
-        virtualUserTable.removeMapping(user, domain, MappingImpl.error(error));
+        virtualUserTable.removeMapping(user, domain, Mapping.error(error));
 
         assertThat(virtualUserTable.getMappings(user, domain)).describedAs("No mapping")
             .isEqualTo(MappingsImpl.empty());
@@ -192,14 +192,14 @@ public abstract class AbstractRecipientRewriteTableTest {
         assertThat(virtualUserTable.getMappings(user, domain)).describedAs("No mapping")
             .isEqualTo(MappingsImpl.empty());
 
-        virtualUserTable.addMapping(RecipientRewriteTable.WILDCARD, domain, MappingImpl.address(address));
-        virtualUserTable.addMapping(user, domain, MappingImpl.address(address2));
+        virtualUserTable.addMapping(RecipientRewriteTable.WILDCARD, domain, Mapping.address(address));
+        virtualUserTable.addMapping(user, domain, Mapping.address(address2));
 
         assertThat(virtualUserTable.getMappings(user, domain)).describedAs("One mappings").hasSize(1);
         assertThat(virtualUserTable.getMappings(user2, domain)).describedAs("One mappings").hasSize(1);
 
-        virtualUserTable.removeMapping(user, domain, MappingImpl.address(address2));
-        virtualUserTable.removeMapping(RecipientRewriteTable.WILDCARD, domain, MappingImpl.address(address));
+        virtualUserTable.removeMapping(user, domain, Mapping.address(address2));
+        virtualUserTable.removeMapping(RecipientRewriteTable.WILDCARD, domain, Mapping.address(address));
 
         assertThat(virtualUserTable.getMappings(user, domain)).describedAs("No mapping")
             .isEqualTo(MappingsImpl.empty());
@@ -220,10 +220,10 @@ public abstract class AbstractRecipientRewriteTableTest {
 
         assertThat(virtualUserTable.getAllMappings()).describedAs("No mapping").isEmpty();
 
-        virtualUserTable.addMapping(user1, domain1, MappingImpl.address(user2 + "@" + domain2.asString()));
-        virtualUserTable.addMapping(user2, domain2, MappingImpl.address(user3 + "@" + domain3.asString()));
-        assertThat(virtualUserTable.getMappings(user1, domain1)).containsOnly(MappingImpl.address(user3 + "@" + domain3.asString()));
-        virtualUserTable.addMapping(user3, domain3, MappingImpl.address(user1 + "@" + domain1.asString()));
+        virtualUserTable.addMapping(user1, domain1, Mapping.address(user2 + "@" + domain2.asString()));
+        virtualUserTable.addMapping(user2, domain2, Mapping.address(user3 + "@" + domain3.asString()));
+        assertThat(virtualUserTable.getMappings(user1, domain1)).containsOnly(Mapping.address(user3 + "@" + domain3.asString()));
+        virtualUserTable.addMapping(user3, domain3, Mapping.address(user1 + "@" + domain1.asString()));
 
         assertThatThrownBy(() ->
             virtualUserTable.getMappings(user1, domain1))
@@ -232,7 +232,7 @@ public abstract class AbstractRecipientRewriteTableTest {
 
         // disable recursive mapping
         virtualUserTable.setRecursiveMapping(false);
-        assertThat(virtualUserTable.getMappings(user1, domain1)).describedAs("Not recursive mapped").containsExactly(MappingImpl.address(user2 + "@" + domain2.asString()));
+        assertThat(virtualUserTable.getMappings(user1, domain1)).describedAs("Not recursive mapped").containsExactly(Mapping.address(user2 + "@" + domain2.asString()));
     }
 
     @Test
@@ -244,18 +244,18 @@ public abstract class AbstractRecipientRewriteTableTest {
 
         assertThat(virtualUserTable.getAllMappings()).describedAs("No mappings").isEmpty();
 
-        virtualUserTable.addMapping(RecipientRewriteTable.WILDCARD, aliasDomain, MappingImpl.address(user2 + "@" + domain));
-        virtualUserTable.addMapping(RecipientRewriteTable.WILDCARD, aliasDomain, MappingImpl.domain(Domain.of(domain)));
+        virtualUserTable.addMapping(RecipientRewriteTable.WILDCARD, aliasDomain, Mapping.address(user2 + "@" + domain));
+        virtualUserTable.addMapping(RecipientRewriteTable.WILDCARD, aliasDomain, Mapping.domain(Domain.of(domain)));
 
         assertThat(virtualUserTable.getMappings(user, aliasDomain))
             .describedAs("Domain mapped as first, Address mapped as second")
             .isEqualTo(MappingsImpl.builder()
-                .add(MappingImpl.address(user + "@" + domain))
-                .add(MappingImpl.address(user2 + "@" + domain))
+                .add(Mapping.address(user + "@" + domain))
+                .add(Mapping.address(user2 + "@" + domain))
                 .build());
 
-        virtualUserTable.removeMapping(RecipientRewriteTable.WILDCARD, aliasDomain, MappingImpl.address(user2 + "@" + domain));
-        virtualUserTable.removeMapping(RecipientRewriteTable.WILDCARD, aliasDomain, MappingImpl.domain(Domain.of(domain)));
+        virtualUserTable.removeMapping(RecipientRewriteTable.WILDCARD, aliasDomain, Mapping.address(user2 + "@" + domain));
+        virtualUserTable.removeMapping(RecipientRewriteTable.WILDCARD, aliasDomain, Mapping.domain(Domain.of(domain)));
     }
 
     @Test
@@ -276,8 +276,8 @@ public abstract class AbstractRecipientRewriteTableTest {
         Domain domain = Domain.LOCALHOST;
         String address = "test@localhost2";
 
-        virtualUserTable.addMapping(user, domain, MappingImpl.address(address));
-        virtualUserTable.addMapping(user, domain, MappingImpl.regex(address));
+        virtualUserTable.addMapping(user, domain, Mapping.address(address));
+        virtualUserTable.addMapping(user, domain, Mapping.regex(address));
 
         assertThat(virtualUserTable.getMappings(user, domain)).hasSize(2);
     }
@@ -289,8 +289,8 @@ public abstract class AbstractRecipientRewriteTableTest {
         String address = "test@localhost2";
         String address2 = "test@james";
 
-        virtualUserTable.addMapping(user, domain, MappingImpl.forward(address));
-        virtualUserTable.addMapping(user, domain, MappingImpl.forward(address2));
+        virtualUserTable.addMapping(user, domain, Mapping.forward(address));
+        virtualUserTable.addMapping(user, domain, Mapping.forward(address2));
 
         assertThat(virtualUserTable.getMappings(user, domain)).hasSize(2);
     }
@@ -302,11 +302,11 @@ public abstract class AbstractRecipientRewriteTableTest {
         String address = "test@localhost2";
         String address2 = "test@james";
 
-        virtualUserTable.addMapping(user, domain, MappingImpl.forward(address));
-        virtualUserTable.addMapping(user, domain, MappingImpl.forward(address2));
+        virtualUserTable.addMapping(user, domain, Mapping.forward(address));
+        virtualUserTable.addMapping(user, domain, Mapping.forward(address2));
 
-        virtualUserTable.removeMapping(user, domain, MappingImpl.forward(address));
-        virtualUserTable.removeMapping(user, domain, MappingImpl.forward(address2));
+        virtualUserTable.removeMapping(user, domain, Mapping.forward(address));
+        virtualUserTable.removeMapping(user, domain, Mapping.forward(address2));
 
         assertThat(virtualUserTable.getMappings(user, domain))
             .isEqualTo(MappingsImpl.empty());
@@ -319,8 +319,8 @@ public abstract class AbstractRecipientRewriteTableTest {
         String address = "test@localhost2";
         String address2 = "test@james";
 
-        virtualUserTable.addMapping(user, domain, MappingImpl.group(address));
-        virtualUserTable.addMapping(user, domain, MappingImpl.group(address2));
+        virtualUserTable.addMapping(user, domain, Mapping.group(address));
+        virtualUserTable.addMapping(user, domain, Mapping.group(address2));
 
         assertThat(virtualUserTable.getMappings(user, domain)).hasSize(2);
     }
@@ -332,11 +332,11 @@ public abstract class AbstractRecipientRewriteTableTest {
         String address = "test@localhost2";
         String address2 = "test@james";
 
-        virtualUserTable.addMapping(user, domain, MappingImpl.group(address));
-        virtualUserTable.addMapping(user, domain, MappingImpl.group(address2));
+        virtualUserTable.addMapping(user, domain, Mapping.group(address));
+        virtualUserTable.addMapping(user, domain, Mapping.group(address2));
 
-        virtualUserTable.removeMapping(user, domain, MappingImpl.group(address));
-        virtualUserTable.removeMapping(user, domain, MappingImpl.group(address2));
+        virtualUserTable.removeMapping(user, domain, Mapping.group(address));
+        virtualUserTable.removeMapping(user, domain, Mapping.group(address2));
 
         assertThat(virtualUserTable.getMappings(user, domain))
             .isEqualTo(MappingsImpl.empty());

http://git-wip-us.apache.org/repos/asf/james-project/blob/1ba2bfc3/server/data/data-library/src/test/java/org/apache/james/rrt/lib/MappingImplTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/test/java/org/apache/james/rrt/lib/MappingImplTest.java b/server/data/data-library/src/test/java/org/apache/james/rrt/lib/MappingImplTest.java
deleted file mode 100644
index 8b16443..0000000
--- a/server/data/data-library/src/test/java/org/apache/james/rrt/lib/MappingImplTest.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- *   Licensed to the Apache Software Foundation (ASF) under one
- *   or more contributor license agreements.  See the NOTICE file
- *   distributed with this work for additional information
- *   regarding copyright ownership.  The ASF licenses this file
- *   to you under the Apache License, Version 2.0 (the
- *   "License"); you may not use this file except in compliance
- *   with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *   Unless required by applicable law or agreed to in writing,
- *   software distributed under the License is distributed on an
- *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *   KIND, either express or implied.  See the License for the
- *   specific language governing permissions and limitations
- *   under the License.
- *
- */
-
-package org.apache.james.rrt.lib;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-import org.apache.james.core.Domain;
-import org.apache.james.core.MailAddress;
-import org.apache.james.rrt.api.RecipientRewriteTableException;
-import org.junit.Test;
-
-import nl.jqno.equalsverifier.EqualsVerifier;
-
-public class MappingImplTest {
-
-    @Test
-    public void beanShouldRespectBeanContract() {
-        EqualsVerifier.forClass(MappingImpl.class)
-            .verify();
-    }
-
-    @Test
-    public void addressFactoryMethodShouldThrowOnNull() {
-        assertThatThrownBy(() -> MappingImpl.address(null))
-            .isInstanceOf(NullPointerException.class);
-    }
-    
-    @Test
-    public void regexFactoryMethodShouldThrowOnNull() {
-        assertThatThrownBy(() -> MappingImpl.regex(null))
-            .isInstanceOf(NullPointerException.class);
-    }
-    
-    @Test
-    public void domainFactoryMethodShouldThrowOnNull() {
-        assertThatThrownBy(() -> MappingImpl.domain(null))
-            .isInstanceOf(NullPointerException.class);
-    }
-
-    @Test
-    public void errorFactoryMethodShouldThrowOnNull() {
-        assertThatThrownBy(() -> MappingImpl.error(null))
-            .isInstanceOf(NullPointerException.class);
-    }
-    
-    @Test
-    public void forwardFactoryMethodShouldThrowOnNull() {
-        assertThatThrownBy(() -> MappingImpl.forward(null))
-            .isInstanceOf(NullPointerException.class);
-    }
-
-    @Test
-    public void groupFactoryMethodShouldThrowOnNull() {
-        assertThatThrownBy(() -> MappingImpl.group(null))
-            .isInstanceOf(NullPointerException.class);
-    }
-    
-    @Test
-    public void hasDomainShouldReturnTrueWhenMappingContainAtMark() {
-        assertThat(MappingImpl.address("a@b").hasDomain()).isTrue();
-    }
-    
-    @Test
-    public void hasDomainShouldReturnFalseWhenMappingIsEmpty() {
-        assertThat(MappingImpl.address("").hasDomain()).isFalse();
-    }
-
-    @Test
-    public void hasDomainShouldReturnFalseWhenMappingIsBlank() {
-        assertThat(MappingImpl.address(" ").hasDomain()).isFalse();
-    }
-
-    @Test
-    public void hasDomainShouldReturnFalseWhenMappingDoesntContainAtMark() {
-        assertThat(MappingImpl.address("abc").hasDomain()).isFalse();
-    }
-    
-    @Test
-    public void appendDefaultDomainShouldWorkOnValidDomain() {
-        assertThat(MappingImpl.address("abc").appendDomainIfNone(() -> Domain.of("domain"))).isEqualTo(MappingImpl.address("abc@domain"));
-    }
-    
-    @Test
-    public void appendDefaultDomainShouldNotAddDomainWhenMappingAlreadyContainsDomains() {
-        assertThat(MappingImpl.address("abc@d").appendDomainIfNone(() -> Domain.of("domain"))).isEqualTo(MappingImpl.address("abc@d"));
-    }
-    
-    @Test
-    public void appendDomainShouldThrowWhenNullDomain() {
-        assertThatThrownBy(() -> MappingImpl.address("abc@d").appendDomainIfNone(null)).isInstanceOf(NullPointerException.class);
-    }
-
-    @Test
-    public void appendDomainFromThrowingSupplierIfNoneShouldWorkOnValidDomain() throws RecipientRewriteTableException {
-        assertThat(MappingImpl.address("abc").appendDomainFromThrowingSupplierIfNone(() -> Domain.of("domain")))
-            .isEqualTo(MappingImpl.address("abc@domain"));
-    }
-
-    @Test
-    public void appendDomainFromThrowingSupplierIfNoneShouldNotAddDomainWhenMappingAlreadyContainsDomains() throws RecipientRewriteTableException {
-        assertThat(MappingImpl.address("abc@d").appendDomainFromThrowingSupplierIfNone(() -> Domain.of("domain")))
-            .isEqualTo(MappingImpl.address("abc@d"));
-    }
-
-    @Test
-    public void appendDomainFromThrowingSupplierIfNoneShouldThrowWhenNullDomain() {
-        assertThatThrownBy(() -> MappingImpl.address("abc@d").appendDomainFromThrowingSupplierIfNone(null))
-            .isInstanceOf(NullPointerException.class);
-    }
-
-    @Test
-    public void appendDomainFromThrowingSupplierIfNoneShouldNotCatchRecipientRewriteTableException() {
-        Mapping.ThrowingDomainSupplier supplier = () -> {
-            throw new RecipientRewriteTableException("message");
-        };
-        assertThatThrownBy(() -> MappingImpl.address("abc").appendDomainFromThrowingSupplierIfNone(supplier))
-            .isInstanceOf(RecipientRewriteTableException.class);
-    }
-
-    @Test
-    public void getTypeShouldReturnAddressWhenNoPrefix() {
-        assertThat(MappingImpl.address("abc").getType()).isEqualTo(Mapping.Type.Address);
-    }
-
-    @Test
-    public void getTypeShouldReturnAddressWhenEmpty() {
-        assertThat(MappingImpl.address("").getType()).isEqualTo(Mapping.Type.Address);
-    }
-    
-    @Test
-    public void getTypeShouldReturnRegexWhenRegexPrefix() {
-        assertThat(MappingImpl.regex("abc").getType()).isEqualTo(Mapping.Type.Regex);
-    }
-
-    @Test
-    public void getTypeShouldReturnErrorWhenErrorPrefix() {
-        assertThat(MappingImpl.error("abc").getType()).isEqualTo(Mapping.Type.Error);
-    }
-
-    @Test
-    public void getTypeShouldReturnDomainWhenDomainPrefix() {
-        assertThat(MappingImpl.domain(Domain.of("abc")).getType()).isEqualTo(Mapping.Type.Domain);
-    }
-
-    @Test
-    public void getTypeShouldReturnForwardWhenForwardPrefix() {
-        assertThat(MappingImpl.forward("abc").getType()).isEqualTo(Mapping.Type.Forward);
-    }
-
-    @Test
-    public void getTypeShouldReturnGroupWhenGroupPrefix() {
-        assertThat(MappingImpl.group("abc").getType()).isEqualTo(Mapping.Type.Group);
-    }
-    
-    @Test(expected = IllegalStateException.class)
-    public void getErrorMessageShouldThrowWhenMappingIsNotAnError() {
-        MappingImpl.domain(Domain.of("toto")).getErrorMessage();
-    }
-    
-    @Test
-    public void getErrorMessageShouldReturnMessageWhenErrorWithMessage() {
-        assertThat(MappingImpl.error("toto").getErrorMessage()).isEqualTo("toto");
-    }
-
-    @Test
-    public void getErrorMessageShouldReturnWhenErrorWithoutMessage() {
-        assertThat(MappingImpl.error("").getErrorMessage()).isEqualTo("");
-    }
-
-    @Test
-    public void asMailAddressShouldReturnMappingValueForAddress() throws Exception {
-        assertThat(MappingImpl.address("value@domain").asMailAddress())
-            .contains(new MailAddress("value@domain"));
-    }
-
-    @Test
-    public void asMailAddressShouldReturnEmptyOnInvalidAddress() {
-        assertThat(MappingImpl.address("value").asMailAddress())
-            .isEmpty();
-    }
-
-    @Test
-    public void asMailAddressShouldReturnEmptyForError() {
-        assertThat(MappingImpl.error("value").asMailAddress()).isEmpty();
-    }
-
-    @Test
-    public void asMailAddressShouldReturnEmptyForRegex() {
-        assertThat(MappingImpl.regex("value").asMailAddress()).isEmpty();
-    }
-
-    @Test
-    public void asMailAddressShouldReturnEmptyForDomain() {
-        assertThat(MappingImpl.domain(Domain.of("value")).asMailAddress()).isEmpty();
-    }
-
-    @Test
-    public void asMailAddressShouldReturnMappingValueForForward() throws Exception {
-        assertThat(MappingImpl.forward("value@domain").asMailAddress())
-            .contains(new MailAddress("value@domain"));
-    }
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/1ba2bfc3/server/data/data-library/src/test/java/org/apache/james/rrt/lib/MappingsImplTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/test/java/org/apache/james/rrt/lib/MappingsImplTest.java b/server/data/data-library/src/test/java/org/apache/james/rrt/lib/MappingsImplTest.java
index 213c3d1..afae9e2 100644
--- a/server/data/data-library/src/test/java/org/apache/james/rrt/lib/MappingsImplTest.java
+++ b/server/data/data-library/src/test/java/org/apache/james/rrt/lib/MappingsImplTest.java
@@ -45,82 +45,82 @@ public class MappingsImplTest {
     @Test
     public void fromRawStringShouldReturnSingletonCollectionWhenSingleElementString() {
         MappingsImpl actual = MappingsImpl.fromRawString("value");
-        assertThat(actual).containsOnly(MappingImpl.address("value"));
+        assertThat(actual).containsOnly(Mapping.address("value"));
     }
 
     @Test
     public void fromRawStringShouldReturnCollectionWhenSeveralElementsString() {
         MappingsImpl actual = MappingsImpl.fromRawString("value1;value2");
-        assertThat(actual).containsOnly(MappingImpl.address("value1"), MappingImpl.address("value2"));
+        assertThat(actual).containsOnly(Mapping.address("value1"), Mapping.address("value2"));
     }
     
     @Test
     public void fromRawStringShouldReturnSingleElementCollectionWhenTrailingDelimiterString() {
         MappingsImpl actual = MappingsImpl.fromRawString("value1;");
-        assertThat(actual).containsOnly(MappingImpl.address("value1"));
+        assertThat(actual).containsOnly(Mapping.address("value1"));
     }
 
     @Test
     public void fromRawStringShouldReturnSingleElementCollectionWhenHeadingDelimiterString() {
         MappingsImpl actual = MappingsImpl.fromRawString(";value1");
-        assertThat(actual).containsOnly(MappingImpl.address("value1"));
+        assertThat(actual).containsOnly(Mapping.address("value1"));
     }
     
 
     @Test
     public void fromRawStringShouldTrimValues() {
         MappingsImpl actual = MappingsImpl.fromRawString("value1 ; value2  ");
-        assertThat(actual).containsOnly(MappingImpl.address("value1"), MappingImpl.address("value2"));
+        assertThat(actual).containsOnly(Mapping.address("value1"), Mapping.address("value2"));
     }
     
     @Test
     public void fromRawStringShouldNotSkipEmptyValue() {
         MappingsImpl actual = MappingsImpl.fromRawString("value1; ;value2");
-        assertThat(actual).containsOnly(MappingImpl.address("value1"), MappingImpl.address(""), MappingImpl.address("value2"));
+        assertThat(actual).containsOnly(Mapping.address("value1"), Mapping.address(""), Mapping.address("value2"));
     }
     
     @Test
     public void fromRawStringShouldReturnCollectionWhenValueContainsCommaSeperatedValues() {
         MappingsImpl actual = MappingsImpl.fromRawString("value1,value2");
-        assertThat(actual).containsOnly(MappingImpl.address("value1"),MappingImpl.address("value2"));
+        assertThat(actual).containsOnly(Mapping.address("value1"),Mapping.address("value2"));
     }
 
     @Test
     public void fromRawStringShouldReturnCollectionWhenValueContainsColonSeperatedValues() {
         MappingsImpl actual = MappingsImpl.fromRawString("value1:value2");
-        assertThat(actual).containsOnly(MappingImpl.address("value1"),MappingImpl.address("value2"));
+        assertThat(actual).containsOnly(Mapping.address("value1"),Mapping.address("value2"));
     }
 
     @Test
     public void fromRawStringShouldUseCommaDelimiterBeforeSemicolonWhenValueContainsBoth() {
         MappingsImpl actual = MappingsImpl.fromRawString("value1;value1,value2");
-        assertThat(actual).containsOnly(MappingImpl.address("value1;value1"),MappingImpl.address("value2"));
+        assertThat(actual).containsOnly(Mapping.address("value1;value1"),Mapping.address("value2"));
     }
 
     @Test
     public void fromRawStringShouldUseSemicolonDelimiterBeforeColonWhenValueContainsBoth() {
         MappingsImpl actual = MappingsImpl.fromRawString("value1:value1;value2");
-        assertThat(actual).containsOnly(MappingImpl.address("value1:value1"),MappingImpl.address("value2"));
+        assertThat(actual).containsOnly(Mapping.address("value1:value1"),Mapping.address("value2"));
     }
     
     @Test
     public void fromRawStringShouldNotUseColonDelimiterWhenValueStartsWithError() {
         MappingsImpl actual = MappingsImpl.fromRawString("error:test");
-        assertThat(actual).containsOnly(MappingImpl.error("test"));
+        assertThat(actual).containsOnly(Mapping.error("test"));
     }
     
 
     @Test
     public void fromRawStringShouldNotUseColonDelimiterWhenValueStartsWithDomain() {
         MappingsImpl actual = MappingsImpl.fromRawString("domain:test");
-        assertThat(actual).containsOnly(MappingImpl.domain(Domain.of("test")));
+        assertThat(actual).containsOnly(Mapping.domain(Domain.of("test")));
     }
     
 
     @Test
     public void fromRawStringShouldNotUseColonDelimiterWhenValueStartsWithRegex() {
         MappingsImpl actual = MappingsImpl.fromRawString("regex:test");
-        assertThat(actual).containsOnly(MappingImpl.regex("test"));
+        assertThat(actual).containsOnly(Mapping.regex("test"));
     }
 
     @Test
@@ -142,34 +142,34 @@ public class MappingsImplTest {
 
     @Test
     public void containsShouldReturnTrueWhenMatchingMapping() {
-        MappingsImpl mappings = MappingsImpl.builder().add(MappingImpl.regex("toto")).build();
+        MappingsImpl mappings = MappingsImpl.builder().add(Mapping.regex("toto")).build();
         assertThat(mappings.contains(Mapping.Type.Regex)).isTrue();
     }
     
     @Test
     public void containsShouldReturnFalseWhenNoMatchingMapping() {
-        MappingsImpl mappings = MappingsImpl.builder().add(MappingImpl.regex("toto")).build();
+        MappingsImpl mappings = MappingsImpl.builder().add(Mapping.regex("toto")).build();
         assertThat(mappings.contains(Mapping.Type.Error)).isFalse();
     }
 
     
     @Test(expected = NullPointerException.class)
     public void containsShouldThrowWhenNull() {
-        MappingsImpl mappings = MappingsImpl.builder().add(MappingImpl.regex("toto")).build();
+        MappingsImpl mappings = MappingsImpl.builder().add(Mapping.regex("toto")).build();
         assertThat(mappings.contains((Mapping.Type)null));
     }
     
     @Test
     public void selectShouldReturnMatchingElementsInOrderWhenMatchingMapping() {
         MappingsImpl mappings = MappingsImpl.builder()
-            .add(MappingImpl.regex("toto"))
-            .add(MappingImpl.address("toto"))
-            .add(MappingImpl.domain(Domain.of("domain")))
-            .add(MappingImpl.regex("tata"))
+            .add(Mapping.regex("toto"))
+            .add(Mapping.address("toto"))
+            .add(Mapping.domain(Domain.of("domain")))
+            .add(Mapping.regex("tata"))
             .build();
         MappingsImpl expected = MappingsImpl.builder()
-                .add(MappingImpl.regex("toto"))
-                .add(MappingImpl.regex("tata"))
+                .add(Mapping.regex("toto"))
+                .add(Mapping.regex("tata"))
                 .build();
         assertThat(mappings.select(Mapping.Type.Regex)).isEqualTo(expected);
     }
@@ -177,9 +177,9 @@ public class MappingsImplTest {
     @Test
     public void selectShouldReturnEmptyCollectionWhenNoMatchingMapping() {
         MappingsImpl mappings = MappingsImpl.builder()
-                .add(MappingImpl.regex("toto"))
-                .add(MappingImpl.address("toto")) 
-                .add(MappingImpl.address("tata"))
+                .add(Mapping.regex("toto"))
+                .add(Mapping.address("toto"))
+                .add(Mapping.address("tata"))
                 .build();
         assertThat(mappings.select(Mapping.Type.Domain)).isEqualTo(MappingsImpl.empty());
     }
@@ -187,21 +187,21 @@ public class MappingsImplTest {
     
     @Test(expected = NullPointerException.class)
     public void selectShouldThrowWhenNull() {
-        MappingsImpl mappings = MappingsImpl.builder().add(MappingImpl.regex("toto")).build();
+        MappingsImpl mappings = MappingsImpl.builder().add(Mapping.regex("toto")).build();
         assertThat(mappings.select((Mapping.Type)null));
     }
 
     @Test
     public void excludeShouldReturnNonMatchingElementsInOrderWhenNonMatchingMapping() {
         MappingsImpl mappings = MappingsImpl.builder()
-            .add(MappingImpl.regex("toto"))
-            .add(MappingImpl.address("toto"))
-            .add(MappingImpl.domain(Domain.of("domain")))
-            .add(MappingImpl.regex("tata"))
+            .add(Mapping.regex("toto"))
+            .add(Mapping.address("toto"))
+            .add(Mapping.domain(Domain.of("domain")))
+            .add(Mapping.regex("tata"))
             .build();
         MappingsImpl expected = MappingsImpl.builder()
-            .add(MappingImpl.address("toto"))
-            .add(MappingImpl.domain(Domain.of("domain")))
+            .add(Mapping.address("toto"))
+            .add(Mapping.domain(Domain.of("domain")))
             .build();
         assertThat(mappings.exclude(Mapping.Type.Regex)).isEqualTo(expected);
     }
@@ -209,8 +209,8 @@ public class MappingsImplTest {
     @Test
     public void excludeShouldReturnEmptyCollectionWhenOnlyMatchingMapping() {
         MappingsImpl mappings = MappingsImpl.builder()
-                .add(MappingImpl.address("toto")) 
-                .add(MappingImpl.address("tata"))
+                .add(Mapping.address("toto"))
+                .add(Mapping.address("tata"))
                 .build();
         assertThat(mappings.exclude(Mapping.Type.Address)).isEqualTo(MappingsImpl.empty());
     }
@@ -218,7 +218,7 @@ public class MappingsImplTest {
     
     @Test(expected = NullPointerException.class)
     public void excludeShouldThrowWhenNull() {
-        MappingsImpl mappings = MappingsImpl.builder().add(MappingImpl.regex("toto")).build();
+        MappingsImpl mappings = MappingsImpl.builder().add(Mapping.regex("toto")).build();
         assertThat(mappings.exclude((Mapping.Type)null));
     }
 
@@ -252,7 +252,7 @@ public class MappingsImplTest {
     @Test
     public void unionShouldReturnMergedWhenBothContainsData() {
         Mappings mappings = MappingsImpl.fromRawString("toto").union(MappingsImpl.fromRawString("tata"));
-        assertThat(mappings).containsOnly(MappingImpl.address("toto"),MappingImpl.address("tata"));
+        assertThat(mappings).containsOnly(Mapping.address("toto"),Mapping.address("tata"));
     }
 
     @Test
@@ -280,7 +280,7 @@ public class MappingsImplTest {
 
     @Test
     public void mergeShouldReturnLeftWhenRightIsEmpty() {
-        MappingImpl expectedMapping = MappingImpl.address("toto");
+        Mapping expectedMapping = Mapping.address("toto");
         MappingsImpl.Builder left = MappingsImpl.builder().add(expectedMapping);
         MappingsImpl.Builder empty = MappingsImpl.builder();
         MappingsImpl mappingsImpl = MappingsImpl.Builder
@@ -291,7 +291,7 @@ public class MappingsImplTest {
 
     @Test
     public void mergeShouldReturnRightWhenLeftIsEmpty() {
-        MappingImpl expectedMapping = MappingImpl.address("toto");
+        Mapping expectedMapping = Mapping.address("toto");
         MappingsImpl.Builder right = MappingsImpl.builder().add(expectedMapping);
         MappingsImpl.Builder empty = MappingsImpl.builder();
         MappingsImpl mappingsImpl = MappingsImpl.Builder
@@ -302,9 +302,9 @@ public class MappingsImplTest {
 
     @Test
     public void mergeShouldReturnBothWhenBothAreNotEmpty() {
-        MappingImpl leftMapping = MappingImpl.address("toto");
+        Mapping leftMapping = Mapping.address("toto");
         MappingsImpl.Builder left = MappingsImpl.builder().add(leftMapping);
-        MappingImpl rightMapping = MappingImpl.address("titi");
+        Mapping rightMapping = Mapping.address("titi");
         MappingsImpl.Builder right = MappingsImpl.builder().add(rightMapping);
         MappingsImpl mappingsImpl = MappingsImpl.Builder
                 .merge(left, right)
@@ -314,10 +314,10 @@ public class MappingsImplTest {
     
     @Test
     public void builderShouldPutDomainAliasFirstWhenVariousMappings() {
-        MappingImpl addressMapping = MappingImpl.address("aaa");
-        MappingImpl errorMapping = MappingImpl.error("error");
-        MappingImpl domainMapping = MappingImpl.domain(Domain.of("domain"));
-        MappingImpl domain2Mapping = MappingImpl.domain(Domain.of("domain2"));
+        Mapping addressMapping = Mapping.address("aaa");
+        Mapping errorMapping = Mapping.error("error");
+        Mapping domainMapping = Mapping.domain(Domain.of("domain"));
+        Mapping domain2Mapping = Mapping.domain(Domain.of("domain2"));
         MappingsImpl mappingsImpl = MappingsImpl.builder()
                 .add(domainMapping)
                 .add(addressMapping)
@@ -329,9 +329,9 @@ public class MappingsImplTest {
     
     @Test
     public void builderShouldPutDomainAliasFirstThenForwardWhenVariousMappings() {
-        MappingImpl regexMapping = MappingImpl.regex("regex");
-        MappingImpl forwardMapping = MappingImpl.forward("forward");
-        MappingImpl domainMapping = MappingImpl.domain(Domain.of("domain"));
+        Mapping regexMapping = Mapping.regex("regex");
+        Mapping forwardMapping = Mapping.forward("forward");
+        Mapping domainMapping = Mapping.domain(Domain.of("domain"));
         MappingsImpl mappingsImpl = MappingsImpl.builder()
                 .add(regexMapping)
                 .add(forwardMapping)
@@ -342,10 +342,10 @@ public class MappingsImplTest {
 
     @Test
     public void builderShouldPutGroupsBetweenDomainAndForward() {
-        MappingImpl regexMapping = MappingImpl.regex("regex");
-        MappingImpl forwardMapping = MappingImpl.forward("forward");
-        MappingImpl domainMapping = MappingImpl.domain(Domain.of("domain"));
-        MappingImpl groupMapping = MappingImpl.group("group");
+        Mapping regexMapping = Mapping.regex("regex");
+        Mapping forwardMapping = Mapping.forward("forward");
+        Mapping domainMapping = Mapping.domain(Domain.of("domain"));
+        Mapping groupMapping = Mapping.group("group");
         MappingsImpl mappingsImpl = MappingsImpl.builder()
                 .add(regexMapping)
                 .add(forwardMapping)


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


[02/27] james-project git commit: JAMES-2366 drop getAllMappings wrapping methods and expose backend implementation

Posted by ma...@apache.org.
JAMES-2366 drop getAllMappings wrapping methods and expose backend implementation


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

Branch: refs/heads/master
Commit: 565c6a23841a5d311502eb63ce35cf36f9853fda
Parents: e2c0bcd
Author: Matthieu Baechler <ma...@apache.org>
Authored: Wed Apr 18 16:14:26 2018 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:45:26 2018 +0200

----------------------------------------------------------------------
 .../rrt/cassandra/CassandraRecipientRewriteTable.java     |  2 +-
 .../apache/james/rrt/file/XMLRecipientRewriteTable.java   |  2 +-
 .../james/rrt/hbase/HBaseRecipientRewriteTable.java       |  2 +-
 .../apache/james/rrt/jdbc/JDBCRecipientRewriteTable.java  |  2 +-
 .../apache/james/rrt/jpa/JPARecipientRewriteTable.java    |  2 +-
 .../james/rrt/lib/AbstractRecipientRewriteTable.java      | 10 +---------
 .../james/rrt/memory/MemoryRecipientRewriteTable.java     |  2 +-
 7 files changed, 7 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/565c6a23/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java b/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java
index b4239d8..6e805a0 100644
--- a/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java
+++ b/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java
@@ -130,7 +130,7 @@ public class CassandraRecipientRewriteTable extends AbstractRecipientRewriteTabl
     }
 
     @Override
-    protected Map<String, Mappings> getAllMappingsInternal() {
+    public Map<String, Mappings> getAllMappings() {
         return executor.execute(retrieveAllMappingsStatement.bind())
             .thenApply(resultSet -> cassandraUtils.convertToStream(resultSet)
                 .map(row -> new UserMapping(row.getString(USER), Domain.of(row.getString(DOMAIN)), row.getString(MAPPING)))

http://git-wip-us.apache.org/repos/asf/james-project/blob/565c6a23/server/data/data-file/src/main/java/org/apache/james/rrt/file/XMLRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-file/src/main/java/org/apache/james/rrt/file/XMLRecipientRewriteTable.java b/server/data/data-file/src/main/java/org/apache/james/rrt/file/XMLRecipientRewriteTable.java
index 08063cc..e6a6f19 100644
--- a/server/data/data-file/src/main/java/org/apache/james/rrt/file/XMLRecipientRewriteTable.java
+++ b/server/data/data-file/src/main/java/org/apache/james/rrt/file/XMLRecipientRewriteTable.java
@@ -81,7 +81,7 @@ public class XMLRecipientRewriteTable extends AbstractRecipientRewriteTable {
     }
 
     @Override
-    protected Map<String, Mappings> getAllMappingsInternal() throws RecipientRewriteTableException {
+    public Map<String, Mappings> getAllMappings() throws RecipientRewriteTableException {
         if (mappings != null && mappings.size() > 0) {
             Map<String, Mappings> mappingsNew = new HashMap<>();
             for (String key : mappings.keySet()) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/565c6a23/server/data/data-hbase/src/main/java/org/apache/james/rrt/hbase/HBaseRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-hbase/src/main/java/org/apache/james/rrt/hbase/HBaseRecipientRewriteTable.java b/server/data/data-hbase/src/main/java/org/apache/james/rrt/hbase/HBaseRecipientRewriteTable.java
index 7fa77ac..7cfb6af 100644
--- a/server/data/data-hbase/src/main/java/org/apache/james/rrt/hbase/HBaseRecipientRewriteTable.java
+++ b/server/data/data-hbase/src/main/java/org/apache/james/rrt/hbase/HBaseRecipientRewriteTable.java
@@ -102,7 +102,7 @@ public class HBaseRecipientRewriteTable extends AbstractRecipientRewriteTable {
     }
 
     @Override
-    protected Map<String, Mappings> getAllMappingsInternal() throws RecipientRewriteTableException {
+    public Map<String, Mappings> getAllMappings() throws RecipientRewriteTableException {
         HTableInterface table = null;
         ResultScanner resultScanner = null;
         Map<String, Mappings> map = new HashMap<>();

http://git-wip-us.apache.org/repos/asf/james-project/blob/565c6a23/server/data/data-jdbc/src/main/java/org/apache/james/rrt/jdbc/JDBCRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-jdbc/src/main/java/org/apache/james/rrt/jdbc/JDBCRecipientRewriteTable.java b/server/data/data-jdbc/src/main/java/org/apache/james/rrt/jdbc/JDBCRecipientRewriteTable.java
index eee32b6..2cae41f 100644
--- a/server/data/data-jdbc/src/main/java/org/apache/james/rrt/jdbc/JDBCRecipientRewriteTable.java
+++ b/server/data/data-jdbc/src/main/java/org/apache/james/rrt/jdbc/JDBCRecipientRewriteTable.java
@@ -257,7 +257,7 @@ public class JDBCRecipientRewriteTable extends AbstractRecipientRewriteTable {
     }
 
     @Override
-    protected Map<String, Mappings> getAllMappingsInternal() throws RecipientRewriteTableException {
+    public Map<String, Mappings> getAllMappings() throws RecipientRewriteTableException {
         Connection conn = null;
         PreparedStatement mappingStmt = null;
         Map<String, Mappings> mapping = new HashMap<>();

http://git-wip-us.apache.org/repos/asf/james-project/blob/565c6a23/server/data/data-jpa/src/main/java/org/apache/james/rrt/jpa/JPARecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-jpa/src/main/java/org/apache/james/rrt/jpa/JPARecipientRewriteTable.java b/server/data/data-jpa/src/main/java/org/apache/james/rrt/jpa/JPARecipientRewriteTable.java
index b046e0d..c0ab2ce 100644
--- a/server/data/data-jpa/src/main/java/org/apache/james/rrt/jpa/JPARecipientRewriteTable.java
+++ b/server/data/data-jpa/src/main/java/org/apache/james/rrt/jpa/JPARecipientRewriteTable.java
@@ -139,7 +139,7 @@ public class JPARecipientRewriteTable extends AbstractRecipientRewriteTable {
     }
 
     @Override
-    protected Map<String, Mappings> getAllMappingsInternal() throws RecipientRewriteTableException {
+    public Map<String, Mappings> getAllMappings() throws RecipientRewriteTableException {
         EntityManager entityManager = entityManagerFactory.createEntityManager();
         final EntityTransaction transaction = entityManager.getTransaction();
         Map<String, Mappings> mapping = new HashMap<>();

http://git-wip-us.apache.org/repos/asf/james-project/blob/565c6a23/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
index 21066af..d028eca 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
@@ -246,14 +246,6 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
     }
 
     @Override
-    public Map<String, Mappings> getAllMappings() throws RecipientRewriteTableException {
-        Map<String, Mappings> mappings = getAllMappingsInternal();
-
-        LOGGER.debug("Retrieve all mappings. Mapping count: {}", mappings.size());
-        return mappings;
-    }
-
-    @Override
     public void addAliasDomainMapping(Domain aliasDomain, Domain realDomain) throws RecipientRewriteTableException {
         LOGGER.info("Add domain mapping: {} => {}", aliasDomain, realDomain);
         addMapping(null, aliasDomain, Mapping.domain(realDomain));
@@ -312,7 +304,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
      * 
      * @return Map
      */
-    protected abstract Map<String, Mappings> getAllMappingsInternal() throws RecipientRewriteTableException;
+    public abstract Map<String, Mappings> getAllMappings() throws RecipientRewriteTableException;
 
     /**
      * This method must return stored Mappings for the given user.

http://git-wip-us.apache.org/repos/asf/james-project/blob/565c6a23/server/data/data-memory/src/main/java/org/apache/james/rrt/memory/MemoryRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-memory/src/main/java/org/apache/james/rrt/memory/MemoryRecipientRewriteTable.java b/server/data/data-memory/src/main/java/org/apache/james/rrt/memory/MemoryRecipientRewriteTable.java
index b871370..b45e4ed 100644
--- a/server/data/data-memory/src/main/java/org/apache/james/rrt/memory/MemoryRecipientRewriteTable.java
+++ b/server/data/data-memory/src/main/java/org/apache/james/rrt/memory/MemoryRecipientRewriteTable.java
@@ -117,7 +117,7 @@ public class MemoryRecipientRewriteTable extends AbstractRecipientRewriteTable {
     }
 
     @Override
-    protected Map<String, Mappings> getAllMappingsInternal() {
+    public Map<String, Mappings> getAllMappings() {
         return Multimaps.index(mappingEntries, InMemoryMappingEntry::asKey)
             .asMap()
             .entrySet()


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


[23/27] james-project git commit: JAMES-2366 add some tests on regex mapping rewriting

Posted by ma...@apache.org.
JAMES-2366 add some tests on regex mapping rewriting


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

Branch: refs/heads/master
Commit: a7a8735e3169e925bf755c8b02d570b186359a04
Parents: ff8107e
Author: Matthieu Baechler <ma...@apache.org>
Authored: Fri Apr 20 15:13:27 2018 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:49:33 2018 +0200

----------------------------------------------------------------------
 .../org/apache/james/rrt/lib/RegexRewriterTest.java  | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/a7a8735e/server/data/data-api/src/test/java/org/apache/james/rrt/lib/RegexRewriterTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/test/java/org/apache/james/rrt/lib/RegexRewriterTest.java b/server/data/data-api/src/test/java/org/apache/james/rrt/lib/RegexRewriterTest.java
index f234dad..b8682a3 100644
--- a/server/data/data-api/src/test/java/org/apache/james/rrt/lib/RegexRewriterTest.java
+++ b/server/data/data-api/src/test/java/org/apache/james/rrt/lib/RegexRewriterTest.java
@@ -74,4 +74,19 @@ public class RegexRewriterTest {
         assertThat(new UserRewritter.RegexRewriter().regexMap(mailAddress, "prefix_(.*)_(.*)@test:admin@${1}.${2}"))
             .contains("admin@abc.def");
     }
+
+    @Test
+    public void regexMapShouldCorrectlyReplaceSeveralOutOfOrderMatchingGroups() throws Exception {
+        MailAddress mailAddress = new MailAddress("prefix_abc_def@test");
+        assertThat(new UserRewritter.RegexRewriter().regexMap(mailAddress, "prefix_(.*)_(.*)@test:admin@${2}.${1}"))
+            .contains("admin@def.abc");
+    }
+
+
+    @Test
+    public void regexMapShouldCorrectlyReplaceRepeatingMatchingGroups() throws Exception {
+        MailAddress mailAddress = new MailAddress("prefix_abc_def@test");
+        assertThat(new UserRewritter.RegexRewriter().regexMap(mailAddress, "prefix_(.*)_(.*)@test:admin@${1}.${1}"))
+            .contains("admin@abc.abc");
+    }
 }


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


[12/27] james-project git commit: JAMES-2366 A mapping should rewrite Users

Posted by ma...@apache.org.
JAMES-2366 A mapping should rewrite Users


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

Branch: refs/heads/master
Commit: 23fb3a00b1988ba07c62370f5ffeff3cfe379409
Parents: f08343d
Author: benwa <bt...@linagora.com>
Authored: Wed Apr 18 10:08:01 2018 +0700
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:45:26 2018 +0200

----------------------------------------------------------------------
 .../main/java/org/apache/james/core/User.java   | 12 +++++--
 .../java/org/apache/james/core/UserTest.java    | 35 ++++++++++++++++++++
 .../java/org/apache/james/rrt/lib/Mapping.java  |  5 ++-
 .../rrt/lib/AbstractRecipientRewriteTable.java  | 28 ++++++++--------
 .../org/apache/james/rrt/lib/MappingImpl.java   | 19 +++++++----
 5 files changed, 74 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/23fb3a00/core/src/main/java/org/apache/james/core/User.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/james/core/User.java b/core/src/main/java/org/apache/james/core/User.java
index a3f07ff..a327da3 100644
--- a/core/src/main/java/org/apache/james/core/User.java
+++ b/core/src/main/java/org/apache/james/core/User.java
@@ -91,11 +91,19 @@ public class User {
         return domainPart.isPresent();
     }
 
-    public User withDefaultDomain(Domain defaultDomain) {
+    public User withDefaultDomain(Optional<Domain> defaultDomain) {
         if (hasDomainPart()) {
             return this;
         }
-        return new User(localPart, Optional.of(defaultDomain));
+        return new User(localPart, defaultDomain);
+    }
+
+    public User withDefaultDomain(Domain defaultDomain) {
+        return withDefaultDomain(Optional.of(defaultDomain));
+    }
+
+    public User withDefaultDomainFromUser(User other) {
+        return withDefaultDomain(other.domainPart);
     }
 
     public String asString() {

http://git-wip-us.apache.org/repos/asf/james-project/blob/23fb3a00/core/src/test/java/org/apache/james/core/UserTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/james/core/UserTest.java b/core/src/test/java/org/apache/james/core/UserTest.java
index cd4e60a..29ae95b 100644
--- a/core/src/test/java/org/apache/james/core/UserTest.java
+++ b/core/src/test/java/org/apache/james/core/UserTest.java
@@ -192,4 +192,39 @@ public class UserTest {
             .withDefaultDomain(Domain.LOCALHOST))
             .isEqualTo(User.fromUsername("user@domain"));
     }
+
+    @Test
+    public void withDefaultDomainShouldNotThrowUponEmptyDomain() {
+        assertThat(User.fromUsername("user")
+            .withDefaultDomain(Optional.empty()))
+            .isEqualTo(User.fromUsername("user"));
+    }
+
+    @Test
+    public void withDefaultDomainShouldNotThrowUponEmptyDomainWhenUsersHadADomain() {
+        assertThat(User.fromUsername("user@domain")
+            .withDefaultDomain(Optional.empty()))
+            .isEqualTo(User.fromUsername("user@domain"));
+    }
+
+    @Test
+    public void withDefaultDomainFromUserShouldPreserveUserWhenAlreadyHasADomain() {
+        assertThat(User.fromUsername("user@domain")
+            .withDefaultDomainFromUser(User.fromUsername("bob@tld")))
+            .isEqualTo(User.fromUsername("user@domain"));
+    }
+
+    @Test
+    public void withDefaultDomainFromUserShouldAppendOtherUserDomainWhenNone() {
+        assertThat(User.fromUsername("user")
+            .withDefaultDomainFromUser(User.fromUsername("bob@tld")))
+            .isEqualTo(User.fromUsername("user@tld"));
+    }
+
+    @Test
+    public void withDefaultDomainFromUserShouldNotThrowUponNoDomain() {
+        assertThat(User.fromUsername("user")
+            .withDefaultDomainFromUser(User.fromUsername("bob")))
+            .isEqualTo(User.fromUsername("user"));
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/23fb3a00/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
index c494d8b..0bd24e1 100644
--- a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
@@ -24,9 +24,12 @@ import java.util.Optional;
 import java.util.function.Supplier;
 import java.util.stream.Stream;
 
+import javax.mail.internet.AddressException;
+
 import org.apache.commons.lang3.NotImplementedException;
 import org.apache.james.core.Domain;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.User;
 import org.apache.james.rrt.api.RecipientRewriteTableException;
 
 import com.google.common.base.Preconditions;
@@ -124,6 +127,6 @@ public interface Mapping {
 
     String getErrorMessage();
 
-    Optional<String> apply(MailAddress input);
+    Optional<User> rewriteUser(User user) throws AddressException;
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/23fb3a00/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
index 1632414..08e4c5b 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
@@ -123,35 +123,33 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
         }
     }
 
-    private Stream<Mapping> convertAndRecurseMapping(User user, Mapping associatedMapping, int remainingLoops) throws ErrorMappingException, RecipientRewriteTableException, SkipMappingProcessingException, AddressException {
+    private Stream<Mapping> convertAndRecurseMapping(User originalUser, Mapping associatedMapping, int remainingLoops) throws ErrorMappingException, RecipientRewriteTableException, SkipMappingProcessingException, AddressException {
 
-        Function<String, Stream<Mapping>> convertAndRecurseMapping =
+        Function<User, Stream<Mapping>> convertAndRecurseMapping =
             Throwing
-                .function((String stringMapping) -> convertAndRecurseMapping(associatedMapping.getType(), user, stringMapping, remainingLoops))
+                .function((User rewrittenUser) -> convertAndRecurseMapping(associatedMapping.getType(), originalUser, rewrittenUser, remainingLoops))
                 .sneakyThrow();
 
-        return associatedMapping.apply(user.asMailAddress())
+        return associatedMapping.rewriteUser(originalUser)
+            .map(rewrittenUser -> rewrittenUser.withDefaultDomainFromUser(originalUser))
             .map(convertAndRecurseMapping)
             .orElse(Stream.empty());
     }
 
-    private Stream<Mapping> convertAndRecurseMapping(Type mappingType, User originalUser, String addressWithMappingApplied, int remainingLoops) throws ErrorMappingException, RecipientRewriteTableException {
-        LOGGER.debug("Valid virtual user mapping {} to {}", originalUser, addressWithMappingApplied);
+    private Stream<Mapping> convertAndRecurseMapping(Type mappingType, User originalUser, User rewrittenUser, int remainingLoops) throws ErrorMappingException, RecipientRewriteTableException {
+        LOGGER.debug("Valid virtual user mapping {} to {}", originalUser, rewrittenUser);
 
-        Stream<Mapping> nonRecursiveResult = Stream.of(toMapping(addressWithMappingApplied, mappingType));
+        Stream<Mapping> nonRecursiveResult = Stream.of(toMapping(rewrittenUser, mappingType));
         if (!recursive) {
             return nonRecursiveResult;
         }
 
-        User targetUser = User.fromUsername(addressWithMappingApplied)
-            .withDefaultDomain(originalUser.getDomainPart().get());
-
         // Check if the returned mapping is the same as the input. If so we need to handle identity to avoid loops.
-        if (originalUser.equals(targetUser)) {
+        if (originalUser.equals(rewrittenUser)) {
             return mappingType.getIdentityMappingBehaviour()
                 .handleIdentity(nonRecursiveResult);
         } else {
-            return recurseMapping(nonRecursiveResult, targetUser, remainingLoops);
+            return recurseMapping(nonRecursiveResult, rewrittenUser, remainingLoops);
         }
     }
 
@@ -165,16 +163,16 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
         }
     }
 
-    private Mapping toMapping(String mappedAddress, Type type) {
+    private Mapping toMapping(User rewrittenUser, Type type) {
         switch (type) {
             case Forward:
             case Group:
-                return MappingImpl.of(type, mappedAddress);
+                return MappingImpl.of(type, rewrittenUser.asString());
             case Regex:
             case Domain:
             case Error:
             case Address:
-                return MappingImpl.address(mappedAddress);
+                return MappingImpl.address(rewrittenUser.asString());
         }
         throw new IllegalArgumentException("unhandled enum type");
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/23fb3a00/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingImpl.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingImpl.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingImpl.java
index 54d265e..1881079 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingImpl.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingImpl.java
@@ -29,6 +29,7 @@ import javax.mail.internet.AddressException;
 
 import org.apache.james.core.Domain;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.User;
 import org.apache.james.rrt.api.RecipientRewriteTableException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -141,23 +142,27 @@ public class MappingImpl implements Mapping, Serializable {
     }
 
     @Override
-    public Optional<String> apply(MailAddress address) {
+    public Optional<User> rewriteUser(User user) throws AddressException {
         switch (getType()) {
             case Regex:
                 try {
-                    return RecipientRewriteTableUtil.regexMap(address, this);
+                    return RecipientRewriteTableUtil.regexMap(user.asMailAddress(), this)
+                        .map(User::fromUsername);
                 } catch (PatternSyntaxException e) {
                     LOGGER.error("Exception during regexMap processing: ", e);
-                    return Optional.of(asString());
+                    return Optional.of(User.fromUsername(asString()));
                 }
             case Domain:
-                return Optional.of(address.getLocalPart() + "@" + mapping);
+                return Optional.of(
+                    User.fromLocalPartWithDomain(
+                        user.getLocalPart(),
+                        Domain.of(mapping)));
             case Forward:
-                return Optional.of(mapping);
+                return Optional.of(User.fromUsername(mapping));
             case Group:
-                return Optional.of(mapping);
+                return Optional.of(User.fromUsername(mapping));
             case Address:
-                return Optional.of(mapping);
+                return Optional.of(User.fromUsername(mapping));
             case Error:
                 return Optional.empty();
         }


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


[08/27] james-project git commit: JAMES-2366 Explicitly allow RRT Forward copy to base recipient

Posted by ma...@apache.org.
JAMES-2366 Explicitly allow RRT Forward copy to base recipient


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

Branch: refs/heads/master
Commit: ed5b9f880d975b34d441ce63ff6520335c837ae9
Parents: 6368cb0
Author: benwa <bt...@linagora.com>
Authored: Mon Apr 16 15:07:59 2018 +0700
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:45:26 2018 +0200

----------------------------------------------------------------------
 .../org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java  | 4 ++++
 1 file changed, 4 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/ed5b9f88/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
index 134f57c..69370c6 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
@@ -142,6 +142,10 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
                         // Check if the returned mapping is the same as the
                         // input. If so return null to avoid loops
                         if (userName.equalsIgnoreCase(user) && targetDomain.equals(domain)) {
+                            if (type.equals(Type.Forward)) {
+                                mappings.add(toMapping(addressWithMappingApplied, type));
+                                continue;
+                            }
                             return MappingsImpl.empty();
                         }
 


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


[09/27] james-project git commit: JAMES-2366 Add some recursive forward tests

Posted by ma...@apache.org.
JAMES-2366 Add some recursive forward 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/9fe1d268
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/9fe1d268
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/9fe1d268

Branch: refs/heads/master
Commit: 9fe1d268de03fe922dbb5ebb8e305e02a9e2cdcf
Parents: ed5b9f8
Author: benwa <bt...@linagora.com>
Authored: Mon Apr 16 15:58:31 2018 +0700
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:45:26 2018 +0200

----------------------------------------------------------------------
 .../integration/ForwardIntegrationTest.java     | 98 ++++++++++++++++++++
 1 file changed, 98 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/9fe1d268/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/ForwardIntegrationTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/ForwardIntegrationTest.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/ForwardIntegrationTest.java
index 71d8d3e..e6bdee2 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/ForwardIntegrationTest.java
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/ForwardIntegrationTest.java
@@ -46,10 +46,12 @@ import org.apache.james.jmap.api.access.AccessToken;
 import org.apache.james.probe.DataProbe;
 import org.apache.james.utils.DataProbeImpl;
 import org.apache.james.utils.JmapGuiceProbe;
+import org.apache.james.utils.SMTPMessageSender;
 import org.apache.james.utils.WebAdminGuiceProbe;
 import org.apache.james.webadmin.WebAdminUtils;
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 
 import com.jayway.restassured.RestAssured;
@@ -57,6 +59,9 @@ import com.jayway.restassured.specification.RequestSpecification;
 
 public abstract class ForwardIntegrationTest {
 
+    @Rule
+    public SMTPMessageSender messageSender = new SMTPMessageSender(DOMAIN);
+
     protected abstract GuiceJamesServer createJmapServer();
 
     private GuiceJamesServer jmapServer;
@@ -192,6 +197,99 @@ public abstract class ForwardIntegrationTest {
     }
 
     @Test
+    public void recursiveForwardShouldWork() {
+        webAdminApi.put(String.format("/address/forwards/%s/targets/%s", ALICE, CEDRIC));
+        webAdminApi.put(String.format("/address/forwards/%s/targets/%s", CEDRIC, BOB));
+
+        AccessToken cedricAccessToken = authenticateJamesUser(baseUri(jmapServer), CEDRIC, CEDRIC_PASSWORD);
+        String messageCreationId = "creationId1337";
+        String requestBody = "[" +
+            "  [" +
+            "    \"setMessages\"," +
+            "    {" +
+            "      \"create\": { \"" + messageCreationId  + "\" : {" +
+            "        \"from\": { \"name\": \"Me\", \"email\": \"" + CEDRIC + "\"}," +
+            "        \"to\": [{ \"name\": \"Alice\", \"email\": \"" + ALICE + "\"}]," +
+            "        \"subject\": \"subject\"," +
+            "        \"isUnread\": true," +
+            "        \"isFlagged\": true," +
+            "        \"isAnswered\": true," +
+            "        \"isDraft\": true," +
+            "        \"isForwarded\": true," +
+            "        \"mailboxIds\": [\"" + getOutboxId(cedricAccessToken) + "\"]" +
+            "      }}" +
+            "    }," +
+            "    \"#0\"" +
+            "  ]" +
+            "]";
+
+        with()
+            .header("Authorization", cedricAccessToken.serialize())
+            .body(requestBody)
+        .post("/jmap");
+
+        AccessToken bobAccessToken = authenticateJamesUser(baseUri(jmapServer), BOB, BOB_PASSWORD);
+        calmlyAwait.atMost(30, TimeUnit.SECONDS).until(() -> isAnyMessageFoundInRecipientsMailboxes(bobAccessToken));
+        given()
+            .header("Authorization", bobAccessToken.serialize())
+            .body("[[\"getMessageList\", {}, \"#0\"]]")
+        .when()
+            .post("/jmap")
+        .then()
+            .log().ifValidationFails()
+            .statusCode(200)
+            .body(NAME, equalTo("messageList"))
+            .body(ARGUMENTS + ".messageIds", hasSize(1));
+    }
+
+    @Test
+    public void recursiveWithRecipientCopyForwardShouldWork() {
+        webAdminApi.put(String.format("/address/forwards/%s/targets/%s", ALICE, ALICE));
+        webAdminApi.put(String.format("/address/forwards/%s/targets/%s", ALICE, BOB));
+        webAdminApi.put(String.format("/address/forwards/%s/targets/%s", BOB, CEDRIC));
+
+        AccessToken cedricAccessToken = authenticateJamesUser(baseUri(jmapServer), CEDRIC, CEDRIC_PASSWORD);
+        AccessToken aliceAccessToken = authenticateJamesUser(baseUri(jmapServer), ALICE, ALICE_PASSWORD);
+        String messageCreationId = "creationId1337";
+        String requestBody = "[" +
+            "  [" +
+            "    \"setMessages\"," +
+            "    {" +
+            "      \"create\": { \"" + messageCreationId  + "\" : {" +
+            "        \"from\": { \"name\": \"Me\", \"email\": \"" + CEDRIC + "\"}," +
+            "        \"to\": [{ \"name\": \"Alice\", \"email\": \"" + ALICE + "\"}]," +
+            "        \"subject\": \"subject\"," +
+            "        \"isUnread\": true," +
+            "        \"isFlagged\": true," +
+            "        \"isAnswered\": true," +
+            "        \"isDraft\": true," +
+            "        \"isForwarded\": true," +
+            "        \"mailboxIds\": [\"" + getOutboxId(cedricAccessToken) + "\"]" +
+            "      }}" +
+            "    }," +
+            "    \"#0\"" +
+            "  ]" +
+            "]";
+
+        with()
+            .header("Authorization", cedricAccessToken.serialize())
+            .body(requestBody)
+        .post("/jmap");
+
+        calmlyAwait.atMost(30, TimeUnit.SECONDS).until(() -> isAnyMessageFoundInRecipientsMailboxes(aliceAccessToken));
+        given()
+            .header("Authorization", aliceAccessToken.serialize())
+            .body("[[\"getMessageList\", {}, \"#0\"]]")
+        .when()
+            .post("/jmap")
+        .then()
+            .log().ifValidationFails()
+            .statusCode(200)
+            .body(NAME, equalTo("messageList"))
+            .body(ARGUMENTS + ".messageIds", hasSize(1));
+    }
+
+    @Test
     public void baseRecipientShouldNotReceiveEmailOnDefaultForward() {
         webAdminApi.put(String.format("/address/forwards/%s/targets/%s", ALICE, BOB));
 


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


[10/27] james-project git commit: JAMES-2366 Mapping ordering is in fact a policy

Posted by ma...@apache.org.
JAMES-2366 Mapping ordering is in fact a policy


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

Branch: refs/heads/master
Commit: f8c43adc6dc916ab25c4f64a7c22b69ae1942b6b
Parents: 9fe1d26
Author: Matthieu Baechler <ma...@apache.org>
Authored: Tue Apr 17 14:37:04 2018 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:45:26 2018 +0200

----------------------------------------------------------------------
 .../java/org/apache/james/rrt/lib/Mapping.java  | 20 ++++------
 .../org/apache/james/rrt/lib/MappingsImpl.java  | 39 ++++++++++++++++++--
 2 files changed, 42 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/f8c43adc/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
index 39be80d..d85a6d2 100644
--- a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
@@ -53,19 +53,17 @@ public interface Mapping {
     Optional<MailAddress> asMailAddress();
 
     enum Type {
-        Regex("regex:", 4),
-        Domain("domain:", 1),
-        Error("error:", 4),
-        Forward("forward:", 3),
-        Group("group:", 2),
-        Address("", 4);
+        Regex("regex:"),
+        Domain("domain:"),
+        Error("error:"),
+        Forward("forward:"),
+        Group("group:"),
+        Address("");
 
         private final String asPrefix;
-        private final int order;
 
-        Type(String asPrefix, Integer order) {
+        Type(String asPrefix) {
             this.asPrefix = asPrefix;
-            this.order = order;
         }
 
         public String asPrefix() {
@@ -84,10 +82,6 @@ public interface Mapping {
                 || mapping.startsWith(Forward.asPrefix())
                 || mapping.startsWith(Group.asPrefix());
         }
-
-        public int getOrder() {
-            return order;
-        }
     }
 
     Type getType();

http://git-wip-us.apache.org/repos/asf/james-project/blob/f8c43adc/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingsImpl.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingsImpl.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingsImpl.java
index ada8ac0..3b56c9e 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingsImpl.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingsImpl.java
@@ -44,9 +44,40 @@ public class MappingsImpl implements Mappings, Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    public static final Comparator<Mapping> MAPPING_COMPARATOR = Comparator
-        .<Mapping, Integer>comparing(mapping -> mapping.getType().getOrder())
-        .thenComparing(Mapping::asString);
+    private static class DefaultMappingOrderingPolicy {
+
+        private static final Comparator<Mapping> MAPPING_COMPARATOR = Comparator
+            .<Mapping, Integer>comparing(DefaultMappingOrderingPolicy::typeOrder)
+            .thenComparing(Mapping::asString);
+
+        private static int typeOrder(Mapping mapping) {
+            return typeOrder(mapping.getType());
+        }
+
+        private static int typeOrder(Mapping.Type type) {
+            switch (type) {
+                case Domain:
+                    return 1;
+                case Group:
+                    return 2;
+                case Forward:
+                    return 3;
+                case Regex:
+                    return 4;
+                case Error:
+                    return 4;
+                case Address:
+                    return 4;
+            }
+            throw new IllegalArgumentException("missing enum handling");
+        }
+
+        public Comparator<Mapping> comparator() {
+            return MAPPING_COMPARATOR;
+        }
+    }
+
+
 
     public static MappingsImpl empty() {
         return builder().build();
@@ -121,7 +152,7 @@ public class MappingsImpl implements Mappings, Serializable {
         public MappingsImpl build() {
             return new MappingsImpl(mappings.build()
                 .stream()
-                .sorted(MAPPING_COMPARATOR)
+                .sorted(new DefaultMappingOrderingPolicy().comparator())
                 .collect(Guavate.toImmutableList()));
         }
 


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


[18/27] james-project git commit: JAMES-2366 Rewriting rule logic should be specified by the mapping type

Posted by ma...@apache.org.
JAMES-2366 Rewriting rule logic should be specified by the mapping type

General mapping class should be a container, and should be logic agnostic.
This makes understanding the overall rewriting easier.


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

Branch: refs/heads/master
Commit: 4683d76cc4c8c67fd99e2864c8c4a470eb00d030
Parents: 23fb3a0
Author: benwa <bt...@linagora.com>
Authored: Wed Apr 18 10:54:50 2018 +0700
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Apr 24 14:45:26 2018 +0200

----------------------------------------------------------------------
 .../java/org/apache/james/rrt/lib/Mapping.java  |  45 ++++++-
 .../org/apache/james/rrt/lib/UserRewritter.java | 131 +++++++++++++++++++
 .../james/rrt/lib/DomainRewriterTest.java       |  45 +++++++
 .../apache/james/rrt/lib/NoneRewiterTest.java   |  36 +++++
 .../apache/james/rrt/lib/RegexRewriterTest.java |  77 +++++++++++
 .../james/rrt/lib/ReplaceRewriterTest.java      |  57 ++++++++
 .../org/apache/james/rrt/lib/MappingImpl.java   |  32 +----
 .../rrt/lib/RecipientRewriteTableUtil.java      |  54 --------
 .../rrt/lib/RecipientRewriteTableUtilTest.java  |  57 --------
 .../mailets/AbstractRecipientRewriteTable.java  |  10 +-
 10 files changed, 394 insertions(+), 150 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/4683d76c/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
index 0bd24e1..751000d 100644
--- a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/Mapping.java
@@ -58,12 +58,42 @@ public interface Mapping {
     Optional<MailAddress> asMailAddress();
 
     enum Type {
-        Regex("regex:", IdentityMappingBehaviour.Throw),
-        Domain("domain:", IdentityMappingBehaviour.Throw),
-        Error("error:", IdentityMappingBehaviour.Throw),
-        Forward("forward:", IdentityMappingBehaviour.ReturnIdentity),
-        Group("group:", IdentityMappingBehaviour.Throw),
-        Address("", IdentityMappingBehaviour.Throw);
+        Regex("regex:", IdentityMappingBehaviour.Throw) {
+            @Override
+            protected UserRewritter rewriter(String mapping) {
+                return new UserRewritter.RegexRewriter().generateUserRewriter(mapping);
+            }
+        },
+        Domain("domain:", IdentityMappingBehaviour.Throw) {
+            @Override
+            protected UserRewritter rewriter(String mapping) {
+                return new UserRewritter.DomainRewriter().generateUserRewriter(mapping);
+            }
+        },
+        Error("error:", IdentityMappingBehaviour.Throw) {
+            @Override
+            protected UserRewritter rewriter(String mapping) {
+                return new UserRewritter.NoneRewriter().generateUserRewriter(mapping);
+            }
+        },
+        Forward("forward:", IdentityMappingBehaviour.ReturnIdentity) {
+            @Override
+            protected UserRewritter rewriter(String mapping) {
+                return new UserRewritter.ReplaceRewriter().generateUserRewriter(mapping);
+            }
+        },
+        Group("group:", IdentityMappingBehaviour.Throw) {
+            @Override
+            protected UserRewritter rewriter(String mapping) {
+                return new UserRewritter.ReplaceRewriter().generateUserRewriter(mapping);
+            }
+        },
+        Address("", IdentityMappingBehaviour.Throw) {
+            @Override
+            protected UserRewritter rewriter(String mapping) {
+                return new UserRewritter.ReplaceRewriter().generateUserRewriter(mapping);
+            }
+        };
 
         private final String asPrefix;
         private final IdentityMappingBehaviour identityMappingBehaviour;
@@ -93,6 +123,9 @@ public interface Mapping {
         public IdentityMappingBehaviour getIdentityMappingBehaviour() {
             return identityMappingBehaviour;
         }
+
+        protected abstract UserRewritter rewriter(String mapping);
+
     }
 
     enum IdentityMappingBehaviour {

http://git-wip-us.apache.org/repos/asf/james-project/blob/4683d76c/server/data/data-api/src/main/java/org/apache/james/rrt/lib/UserRewritter.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/lib/UserRewritter.java b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/UserRewritter.java
new file mode 100644
index 0000000..df97d17
--- /dev/null
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/lib/UserRewritter.java
@@ -0,0 +1,131 @@
+/****************************************************************
+ * 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 java.util.List;
+import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+import java.util.stream.IntStream;
+
+import javax.mail.internet.AddressException;
+
+import org.apache.james.core.Domain;
+import org.apache.james.core.MailAddress;
+import org.apache.james.core.User;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.github.steveash.guavate.Guavate;
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableList;
+
+@FunctionalInterface
+public interface UserRewritter {
+
+    Optional<User> rewrite(User user) throws AddressException;
+
+    interface MappingUserRewriter {
+        UserRewritter generateUserRewriter(String mapping);
+    }
+
+    class DomainRewriter implements MappingUserRewriter {
+        @Override
+        public UserRewritter generateUserRewriter(String mapping) {
+            Domain newDomain = Domain.of(mapping);
+            return oldUser -> Optional.of(
+                User.fromLocalPartWithDomain(
+                    oldUser.getLocalPart(),
+                    newDomain));
+        }
+    }
+
+    class ReplaceRewriter implements MappingUserRewriter {
+        @Override
+        public UserRewritter generateUserRewriter(String mapping) {
+            return oldUser -> Optional.of(User.fromUsername(mapping));
+        }
+    }
+
+    class NoneRewriter implements MappingUserRewriter {
+        @Override
+        public UserRewritter generateUserRewriter(String mapping) {
+            return oldUser -> Optional.empty();
+        }
+    }
+
+    class RegexRewriter implements MappingUserRewriter {
+        private static final Logger LOGGER = LoggerFactory.getLogger(RegexRewriter.class);
+
+        private static final int REGEX = 0;
+        private static final int PARAMETERIZED_STRING = 1;
+
+        @Override
+        public UserRewritter generateUserRewriter(String mapping) {
+            return oldUser -> {
+                try {
+                    return regexMap(oldUser.asMailAddress(), mapping)
+                        .map(User::fromUsername);
+                } catch (PatternSyntaxException e) {
+                    LOGGER.error("Exception during regexMap processing: ", e);
+                    return Optional.of(User.fromUsername(Mapping.Type.Regex.asPrefix() + mapping));
+                }
+            };
+        }
+
+        /**
+         * Processes regex virtual user mapping
+         *
+         * It must be formatted as <regular-expression>:<parameterized-string>, e.g.,
+         * (.*)@(.*):${1}@tld
+         */
+        public Optional<String> regexMap(MailAddress address, String mapping) {
+            List<String> parts = ImmutableList.copyOf(Splitter.on(':').split(mapping));
+            if (parts.size() != 2) {
+                throw new PatternSyntaxException("Regex should be formatted as <regular-expression>:<parameterized-string>", mapping, 0);
+            }
+
+            Pattern pattern = Pattern.compile(parts.get(REGEX));
+            Matcher match = pattern.matcher(address.asString());
+
+            if (match.matches()) {
+                ImmutableList<String> parameters = listMatchingGroups(match);
+                return Optional.of(replaceParameters(parts.get(PARAMETERIZED_STRING), parameters));
+            }
+            return Optional.empty();
+        }
+
+        private ImmutableList<String> listMatchingGroups(Matcher match) {
+            return IntStream
+                .rangeClosed(1, match.groupCount())
+                .mapToObj(match::group)
+                .collect(Guavate.toImmutableList());
+        }
+
+        private String replaceParameters(String input, List<String> parameters) {
+            int i = 1;
+            for (String parameter: parameters) {
+                input = input.replace("${" + i++ + "}", parameter);
+            }
+            return input;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/4683d76c/server/data/data-api/src/test/java/org/apache/james/rrt/lib/DomainRewriterTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/test/java/org/apache/james/rrt/lib/DomainRewriterTest.java b/server/data/data-api/src/test/java/org/apache/james/rrt/lib/DomainRewriterTest.java
new file mode 100644
index 0000000..73300f4
--- /dev/null
+++ b/server/data/data-api/src/test/java/org/apache/james/rrt/lib/DomainRewriterTest.java
@@ -0,0 +1,45 @@
+/****************************************************************
+ * 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 static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.james.core.User;
+import org.junit.jupiter.api.Test;
+
+public class DomainRewriterTest {
+    @Test
+    public void rewriteShouldReplaceDomain() throws Exception {
+        assertThat(
+            new UserRewritter.DomainRewriter()
+                .generateUserRewriter("newdomain.com")
+                .rewrite(User.fromUsername("toto@olddomain.com")))
+            .contains(User.fromUsername("toto@newdomain.com"));
+    }
+
+    @Test
+    public void rewriteShouldAddDomainWhenNone() throws Exception {
+        assertThat(
+            new UserRewritter.DomainRewriter()
+                .generateUserRewriter("newdomain.com")
+                .rewrite(User.fromUsername("toto")))
+            .contains(User.fromUsername("toto@newdomain.com"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/4683d76c/server/data/data-api/src/test/java/org/apache/james/rrt/lib/NoneRewiterTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/test/java/org/apache/james/rrt/lib/NoneRewiterTest.java b/server/data/data-api/src/test/java/org/apache/james/rrt/lib/NoneRewiterTest.java
new file mode 100644
index 0000000..c1cdd8c
--- /dev/null
+++ b/server/data/data-api/src/test/java/org/apache/james/rrt/lib/NoneRewiterTest.java
@@ -0,0 +1,36 @@
+/****************************************************************
+ * 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 static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.james.core.User;
+import org.junit.jupiter.api.Test;
+
+public class NoneRewiterTest {
+    @Test
+    public void rewriteShouldReturnEmpty() throws Exception {
+        assertThat(
+            new UserRewritter.NoneRewriter()
+                .generateUserRewriter("any")
+                .rewrite(User.fromUsername("any")))
+            .isEmpty();
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/4683d76c/server/data/data-api/src/test/java/org/apache/james/rrt/lib/RegexRewriterTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/test/java/org/apache/james/rrt/lib/RegexRewriterTest.java b/server/data/data-api/src/test/java/org/apache/james/rrt/lib/RegexRewriterTest.java
new file mode 100644
index 0000000..f234dad
--- /dev/null
+++ b/server/data/data-api/src/test/java/org/apache/james/rrt/lib/RegexRewriterTest.java
@@ -0,0 +1,77 @@
+/****************************************************************
+ * 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 static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.util.regex.PatternSyntaxException;
+
+import org.apache.james.core.MailAddress;
+import org.junit.jupiter.api.Test;
+
+public class RegexRewriterTest {
+    @Test
+    public void regexMapShouldCorrectlyReplaceMatchingUsername() throws Exception {
+        MailAddress mailAddress = new MailAddress("prefix_abc@test");
+        assertThat(new UserRewritter.RegexRewriter().regexMap(mailAddress,"prefix_.*:admin@test"))
+            .contains("admin@test");
+    }
+
+    @Test
+    public void regexMapShouldThrowOnNullAddress() throws Exception {
+        MailAddress address = null;
+        assertThatThrownBy(() -> new UserRewritter.RegexRewriter().regexMap(address, "prefix_.*:admin@test"))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    public void regexMapShouldThrowOnNullRegexMapping() throws Exception {
+        String regexMapping = null;
+        assertThatThrownBy(() -> new UserRewritter.RegexRewriter().regexMap(new MailAddress("abc@test"), regexMapping))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    public void regexMapShouldThrowOnInvalidSyntax() throws Exception {
+        assertThatThrownBy(() -> new UserRewritter.RegexRewriter().regexMap(new MailAddress("abc@test"), "singlepart"))
+            .isInstanceOf(PatternSyntaxException.class);
+    }
+
+    @Test
+    public void regexMapShouldReturnInputWhenRegexDoesntMatch() throws Exception {
+        assertThat(new UserRewritter.RegexRewriter().regexMap(new MailAddress("abc@test"), "notmatching:notreplaced"))
+            .isEmpty();
+    }
+
+    @Test
+    public void regexMapShouldCorrectlyReplaceMatchingGroups() throws Exception {
+        MailAddress mailAddress = new MailAddress("prefix_abc@test");
+        assertThat(new UserRewritter.RegexRewriter().regexMap(mailAddress, "prefix_(.*)@test:admin@${1}"))
+            .contains("admin@abc");
+    }
+
+    @Test
+    public void regexMapShouldCorrectlyReplaceSeveralMatchingGroups() throws Exception {
+        MailAddress mailAddress = new MailAddress("prefix_abc_def@test");
+        assertThat(new UserRewritter.RegexRewriter().regexMap(mailAddress, "prefix_(.*)_(.*)@test:admin@${1}.${2}"))
+            .contains("admin@abc.def");
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/4683d76c/server/data/data-api/src/test/java/org/apache/james/rrt/lib/ReplaceRewriterTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/test/java/org/apache/james/rrt/lib/ReplaceRewriterTest.java b/server/data/data-api/src/test/java/org/apache/james/rrt/lib/ReplaceRewriterTest.java
new file mode 100644
index 0000000..d231d2c
--- /dev/null
+++ b/server/data/data-api/src/test/java/org/apache/james/rrt/lib/ReplaceRewriterTest.java
@@ -0,0 +1,57 @@
+/****************************************************************
+ * 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 static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.james.core.User;
+import org.junit.jupiter.api.Test;
+
+public class ReplaceRewriterTest {
+    @Test
+    public void rewriteShouldSubstituteAddress() throws Exception {
+        String newAddress = "newaddress@newdomain";
+        assertThat(
+            new UserRewritter.ReplaceRewriter()
+                .generateUserRewriter(newAddress)
+                .rewrite(User.fromUsername("old@passed")))
+            .contains(User.fromUsername(newAddress));
+    }
+    
+    @Test
+    public void rewriteShouldSubstituteAddressWhenNoDomainPart() throws Exception {
+        String newAddress = "newaddress@newdomain";
+        assertThat(
+            new UserRewritter.ReplaceRewriter()
+                .generateUserRewriter(newAddress)
+                .rewrite(User.fromUsername("old")))
+            .contains(User.fromUsername(newAddress));
+    }
+
+    @Test
+    public void rewriteShouldSubstituteAddressWhenNoDomainPartInRewrittenAddress() throws Exception {
+        String newAddress = "newaddress";
+        assertThat(
+            new UserRewritter.ReplaceRewriter()
+                .generateUserRewriter(newAddress)
+                .rewrite(User.fromUsername("old@passed")))
+            .contains(User.fromUsername(newAddress));
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/4683d76c/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingImpl.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingImpl.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingImpl.java
index 1881079..87a2f8b 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingImpl.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingImpl.java
@@ -23,7 +23,6 @@ package org.apache.james.rrt.lib;
 import java.io.Serializable;
 import java.util.Optional;
 import java.util.function.Supplier;
-import java.util.regex.PatternSyntaxException;
 
 import javax.mail.internet.AddressException;
 
@@ -31,16 +30,12 @@ import org.apache.james.core.Domain;
 import org.apache.james.core.MailAddress;
 import org.apache.james.core.User;
 import org.apache.james.rrt.api.RecipientRewriteTableException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Objects;
 import com.google.common.base.Preconditions;
 
 public class MappingImpl implements Mapping, Serializable {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(MappingImpl.class);
-
     private static final long serialVersionUID = 1L;
 
     public static MappingImpl of(String mapping) {
@@ -143,33 +138,10 @@ public class MappingImpl implements Mapping, Serializable {
 
     @Override
     public Optional<User> rewriteUser(User user) throws AddressException {
-        switch (getType()) {
-            case Regex:
-                try {
-                    return RecipientRewriteTableUtil.regexMap(user.asMailAddress(), this)
-                        .map(User::fromUsername);
-                } catch (PatternSyntaxException e) {
-                    LOGGER.error("Exception during regexMap processing: ", e);
-                    return Optional.of(User.fromUsername(asString()));
-                }
-            case Domain:
-                return Optional.of(
-                    User.fromLocalPartWithDomain(
-                        user.getLocalPart(),
-                        Domain.of(mapping)));
-            case Forward:
-                return Optional.of(User.fromUsername(mapping));
-            case Group:
-                return Optional.of(User.fromUsername(mapping));
-            case Address:
-                return Optional.of(User.fromUsername(mapping));
-            case Error:
-                return Optional.empty();
-        }
-        throw new IllegalArgumentException("unhandle enum type: " + getType());
+        return type.rewriter(mapping)
+            .rewrite(user);
     }
 
-
     @Override
     public final boolean equals(Object other) {
         if (other instanceof MappingImpl) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/4683d76c/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableUtil.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableUtil.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableUtil.java
index f711178..1546a84 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableUtil.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableUtil.java
@@ -19,78 +19,24 @@
 package org.apache.james.rrt.lib;
 
 import java.util.HashMap;
-import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Optional;
 import java.util.StringTokenizer;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-import java.util.stream.IntStream;
 
 import org.apache.james.core.Domain;
-import org.apache.james.core.MailAddress;
 import org.apache.james.rrt.lib.Mapping.Type;
 import org.apache.james.util.OptionalUtils;
 
-import com.github.steveash.guavate.Guavate;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Splitter;
-import com.google.common.collect.ImmutableList;
-
 /**
  * This helper class contains methods for the RecipientRewriteTable implementations
  */
 public class RecipientRewriteTableUtil {
 
-    private static final int REGEX = 1;
-    private static final int PARAMETERIZED_STRING = 2;
-
     private RecipientRewriteTableUtil() {
     }
 
     /**
-     * Processes regex virtual user mapping
-     * 
-     * If a mapped target string begins with the prefix regex:, it must be
-     * formatted as regex:<regular-expression>:<parameterized-string>, e.g.,
-     * regex:(.*)@(.*):${1}@tld
-     */
-    public static Optional<String> regexMap(MailAddress address, Mapping mapping) {
-        Preconditions.checkArgument(mapping.getType() == Type.Regex);
-
-        List<String> parts = Splitter.on(':').splitToList(mapping.asString());
-        if (parts.size() != 3) {
-            throw new PatternSyntaxException("Regex should be formatted as regex:<regular-expression>:<parameterized-string>", mapping.asString(), 0);
-        }
-
-        Pattern pattern = Pattern.compile(parts.get(REGEX));
-        Matcher match = pattern.matcher(address.asString());
-
-        if (match.matches()) {
-            ImmutableList<String> parameters = listMatchingGroups(match);
-            return Optional.of(replaceParameters(parts.get(PARAMETERIZED_STRING), parameters));
-        }
-        return Optional.empty();
-    }
-
-    private static ImmutableList<String> listMatchingGroups(Matcher match) {
-        return IntStream
-            .rangeClosed(1, match.groupCount())
-            .mapToObj(match::group)
-            .collect(Guavate.toImmutableList());
-    }
-
-    private static String replaceParameters(String input, List<String> parameters) {
-        int i = 1;
-        for (String parameter: parameters) {
-            input = input.replace("${" + i++ + "}", parameter);
-        }
-        return input;
-    }
-
-    /**
      * Returns the real recipient given a virtual username and domain.
      *
      * @param user

http://git-wip-us.apache.org/repos/asf/james-project/blob/4683d76c/server/data/data-library/src/test/java/org/apache/james/rrt/lib/RecipientRewriteTableUtilTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/test/java/org/apache/james/rrt/lib/RecipientRewriteTableUtilTest.java b/server/data/data-library/src/test/java/org/apache/james/rrt/lib/RecipientRewriteTableUtilTest.java
index f9394a9..2fc8384 100644
--- a/server/data/data-library/src/test/java/org/apache/james/rrt/lib/RecipientRewriteTableUtilTest.java
+++ b/server/data/data-library/src/test/java/org/apache/james/rrt/lib/RecipientRewriteTableUtilTest.java
@@ -19,69 +19,12 @@
 package org.apache.james.rrt.lib;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
-import java.util.regex.PatternSyntaxException;
-
-import org.apache.james.core.MailAddress;
 import org.junit.Test;
 
 public class RecipientRewriteTableUtilTest {
 
     @Test
-    public void regexMapShouldCorrectlyReplaceMatchingUsername() throws Exception {
-        MailAddress mailAddress = new MailAddress("prefix_abc@test");
-        assertThat(RecipientRewriteTableUtil.regexMap(mailAddress, MappingImpl.regex("prefix_.*:admin@test")))
-            .isEqualTo("admin@test");
-    }
-
-    @Test
-    public void regexMapShouldThrowOnNullAddress() throws Exception {
-        MailAddress address = null;
-        assertThatThrownBy(() -> RecipientRewriteTableUtil.regexMap(address, MappingImpl.regex("prefix_.*:admin@test")))
-            .isInstanceOf(NullPointerException.class);
-    }
-
-    @Test
-    public void regexMapShouldThrowOnNullRegexMapping() throws Exception {
-        Mapping regexMapping = null;
-        assertThatThrownBy(() -> RecipientRewriteTableUtil.regexMap(new MailAddress("abc@test"), regexMapping))
-            .isInstanceOf(NullPointerException.class);
-    }
-
-    @Test
-    public void regexMapShouldThrowOnNonRegexMapping() throws Exception {
-        assertThatThrownBy(() -> RecipientRewriteTableUtil.regexMap(new MailAddress("abc@test"), MappingImpl.error("mapping")))
-            .isInstanceOf(IllegalArgumentException.class);
-    }
-
-    @Test
-    public void regexMapShouldThrowOnInvalidSyntax() throws Exception {
-        assertThatThrownBy(() -> RecipientRewriteTableUtil.regexMap(new MailAddress("abc@test"), MappingImpl.regex("singlepart")))
-            .isInstanceOf(PatternSyntaxException.class);
-    }
-
-    @Test
-    public void regexMapShouldReturnInputWhenRegexDoesntMatch() throws Exception {
-        assertThat(RecipientRewriteTableUtil.regexMap(new MailAddress("abc@test"), MappingImpl.regex("notmatching:notreplaced")))
-            .isNull();
-    }
-
-    @Test
-    public void regexMapShouldCorrectlyReplaceMatchingGroups() throws Exception {
-        MailAddress mailAddress = new MailAddress("prefix_abc@test");
-        assertThat(RecipientRewriteTableUtil.regexMap(mailAddress, MappingImpl.regex("prefix_(.*)@test:admin@${1}")))
-            .isEqualTo("admin@abc");
-    }
-
-    @Test
-    public void regexMapShouldCorrectlyReplaceSeveralMatchingGroups() throws Exception {
-        MailAddress mailAddress = new MailAddress("prefix_abc_def@test");
-        assertThat(RecipientRewriteTableUtil.regexMap(mailAddress, MappingImpl.regex("prefix_(.*)_(.*)@test:admin@${1}.${2}")))
-            .isEqualTo("admin@abc.def");
-    }
-
-    @Test
     public void getSeparatorShouldReturnCommaWhenCommaIsPresent() {
         String separator = RecipientRewriteTableUtil.getSeparator("regex:(.*)@localhost, regex:user@test");
         assertThat(separator).isEqualTo(",");

http://git-wip-us.apache.org/repos/asf/james-project/blob/4683d76c/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/AbstractRecipientRewriteTable.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/AbstractRecipientRewriteTable.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/AbstractRecipientRewriteTable.java
index 3d4c9ee..94b9794 100755
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/AbstractRecipientRewriteTable.java
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/AbstractRecipientRewriteTable.java
@@ -34,11 +34,12 @@ import javax.mail.MessagingException;
 import javax.mail.internet.ParseException;
 
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.User;
 import org.apache.james.dnsservice.api.DNSService;
 import org.apache.james.domainlist.api.DomainList;
 import org.apache.james.domainlist.api.DomainListException;
-import org.apache.james.rrt.lib.MappingImpl;
-import org.apache.james.rrt.lib.RecipientRewriteTableUtil;
+import org.apache.james.rrt.lib.Mapping;
+import org.apache.james.rrt.lib.UserRewritter;
 import org.apache.james.server.core.MailImpl;
 import org.apache.mailet.Experimental;
 import org.apache.mailet.Mail;
@@ -118,7 +119,10 @@ public abstract class AbstractRecipientRewriteTable extends GenericMailet {
 
                         if (targetAddress.startsWith("regex:")) {
                             try {
-                                Optional<String> maybeTarget = RecipientRewriteTableUtil.regexMap(source, MappingImpl.of(targetAddress));
+                                Optional<String> maybeTarget = new UserRewritter.RegexRewriter()
+                                    .generateUserRewriter(Mapping.Type.Regex.withoutPrefix(targetAddress))
+                                    .rewrite(User.fromUsername(source.asString()))
+                                    .map(User::asString);
                                 if (!maybeTarget.isPresent()) {
                                     continue;
                                 }


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