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 <btell...@linagora.com>
Authored: Wed Apr 18 10:54:50 2018 +0700
Committer: Matthieu Baechler <matth...@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("t...@olddomain.com")))
+            .contains(User.fromUsername("t...@newdomain.com"));
+    }
+
+    @Test
+    public void rewriteShouldAddDomainWhenNone() throws Exception {
+        assertThat(
+            new UserRewritter.DomainRewriter()
+                .generateUserRewriter("newdomain.com")
+                .rewrite(User.fromUsername("toto")))
+            .contains(User.fromUsername("t...@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("ad...@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("ad...@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-unsubscr...@james.apache.org
For additional commands, e-mail: server-dev-h...@james.apache.org

Reply via email to