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 <matth...@apache.org>
Authored: Wed Apr 18 17:09:34 2018 +0200
Committer: Matthieu Baechler <matth...@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-unsubscr...@james.apache.org
For additional commands, e-mail: server-dev-h...@james.apache.org

Reply via email to