You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by ma...@apache.org on 2018/06/13 14:58:21 UTC

[5/5] james-project git commit: JAMES-2418 Strong typing for repository URLs and keys

JAMES-2418 Strong typing for repository URLs and keys


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

Branch: refs/heads/master
Commit: 946c68bea7d8c6f29ea51566436bf4190fa6480f
Parents: 7dfda86
Author: benwa <bt...@linagora.com>
Authored: Fri Jun 8 11:03:43 2018 +0700
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Wed Jun 13 16:57:07 2018 +0200

----------------------------------------------------------------------
 .../data/CassandraMailRepositoryModule.java     |   3 +-
 .../CassandraMailRepositoryIntegrationTest.java |   5 +-
 .../server/MailStoreRepositoryModule.java       |   3 +-
 .../utils/InMemoryMailRepositoryStore.java      |  72 ++++------
 .../james/utils/MailRepositoryProbeImpl.java    |  13 +-
 .../james/utils/MailRepositoryProvider.java     |   3 +-
 .../utils/InMemoryMailRepositoryStoreTest.java  |  51 +++----
 .../MailRepositoryStoreBeanFactory.java         |  47 +++----
 .../container/spring/tool/James23Importer.java  |   6 +-
 .../mailrepository/api/MailRepositoryStore.java |   8 +-
 .../mailrepository/file/FileMailRepository.java |  25 ++--
 .../mailrepository/file/MBoxMailRepository.java |  27 ++--
 .../mailrepository/MBoxMailRepositoryTest.java  |   3 +-
 .../mailrepository/jcr/JCRMailRepository.java   |  15 +-
 .../mailrepository/jdbc/JDBCMailRepository.java |  23 +--
 .../lib/AbstractMailRepository.java             |  21 +--
 .../mock/MockMailRepositoryStore.java           |  11 +-
 .../apache/james/mailets/MailetErrorsTest.java  |  35 ++---
 .../mailets/NetworkMatcherIntegrationTest.java  |   5 +-
 .../james/mailets/SmtpAuthIntegrationTest.java  |   5 +-
 .../mailets/configuration/CommonProcessors.java |   5 +-
 .../transport/mailets/GroupMappingTest.java     |   5 +-
 .../transport/mailets/ToRepositoryTest.java     |  17 ++-
 .../mailets/ToSenderDomainRepositoryTest.java   |  32 +++--
 .../james/transport/mailets/FromRepository.java |  14 +-
 .../james/transport/mailets/ToRepository.java   |   5 +-
 .../mailets/ToSenderDomainRepository.java       |   7 +-
 .../transport/mailets/ToRepositoryTest.java     |  37 +++--
 .../mailets/ToSenderDomainRepositoryTest.java   |   7 +-
 .../mailrepository/mailrepository-api/pom.xml   |  11 ++
 .../james/mailrepository/api/MailKey.java       |  66 +++++++++
 .../mailrepository/api/MailRepository.java      |  12 +-
 .../mailrepository/api/MailRepositoryUrl.java   |  86 ++++++++++++
 .../james/mailrepository/api/Protocol.java      |  60 ++++++++
 .../mailrepository/MailRepositoryContract.java  | 140 +++++++++----------
 .../james/mailrepository/api/MailKeyTest.java   |  54 +++++++
 .../api/MailRepositoryUrlTest.java              |  71 ++++++++++
 .../james/mailrepository/api/ProtocolTest.java  |  42 ++++++
 .../cassandra/CassandraMailRepository.java      |  28 ++--
 .../CassandraMailRepositoryCountDAO.java        |  13 +-
 .../CassandraMailRepositoryKeysDAO.java         |  20 +--
 .../CassandraMailRepositoryMailDAO.java         |  18 +--
 .../CassandraMailRepositoryCountDAOTest.java    |   5 +-
 .../CassandraMailRepositoryKeysDAOTest.java     |  13 +-
 .../CassandraMailRepositoryMailDAOTest.java     |  16 ++-
 .../cassandra/CassandraMailRepositoryTest.java  |   3 +-
 .../memory/MemoryMailRepository.java            |  23 +--
 .../dto/ExtendedMailRepositoryResponse.java     |   4 +-
 .../org/apache/james/webadmin/dto/MailKey.java  |  50 -------
 .../apache/james/webadmin/dto/MailKeyDTO.java   |  52 +++++++
 .../webadmin/dto/MailRepositoryResponse.java    |  12 +-
 .../webadmin/routes/MailRepositoriesRoutes.java |  46 +++---
 .../service/ClearMailRepositoryTask.java        |   9 +-
 .../service/MailRepositoryStoreService.java     |  26 ++--
 .../service/ReprocessingAllMailsTask.java       |  14 +-
 .../service/ReprocessingOneMailTask.java        |  18 +--
 .../webadmin/service/ReprocessingService.java   |   8 +-
 .../routes/MailRepositoriesRoutesTest.java      |  32 +++--
 .../service/MailRepositoryStoreServiceTest.java |  32 +++--
 59 files changed, 966 insertions(+), 528 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/946c68be/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/data/CassandraMailRepositoryModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/data/CassandraMailRepositoryModule.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/data/CassandraMailRepositoryModule.java
index f307440..dc4a7c5 100644
--- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/data/CassandraMailRepositoryModule.java
+++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/data/CassandraMailRepositoryModule.java
@@ -22,6 +22,7 @@ package org.apache.james.modules.data;
 import org.apache.james.backends.cassandra.components.CassandraModule;
 import org.apache.james.blob.api.ObjectStore;
 import org.apache.james.mailrepository.api.MailRepository;
+import org.apache.james.mailrepository.api.MailRepositoryUrl;
 import org.apache.james.mailrepository.cassandra.CassandraMailRepository;
 import org.apache.james.mailrepository.cassandra.CassandraMailRepositoryCountDAO;
 import org.apache.james.mailrepository.cassandra.CassandraMailRepositoryKeysDAO;
@@ -67,7 +68,7 @@ public class CassandraMailRepositoryModule extends AbstractModule {
         }
 
         @Override
-        public MailRepository provide(String url) {
+        public MailRepository provide(MailRepositoryUrl url) {
             return new CassandraMailRepository(url, keysDAO, countDAO, mailDAO, objectStore);
         }
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/946c68be/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraMailRepositoryIntegrationTest.java
----------------------------------------------------------------------
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraMailRepositoryIntegrationTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraMailRepositoryIntegrationTest.java
index e694ec9..cf2cbdb 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraMailRepositoryIntegrationTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraMailRepositoryIntegrationTest.java
@@ -21,6 +21,7 @@ package org.apache.james;
 
 import static com.jayway.awaitility.Duration.FIVE_HUNDRED_MILLISECONDS;
 
+import org.apache.james.mailrepository.api.MailRepositoryUrl;
 import org.apache.james.utils.DataProbeImpl;
 import org.apache.james.utils.MailRepositoryProbeImpl;
 import org.apache.james.utils.SMTPMessageSender;
@@ -35,6 +36,8 @@ import com.jayway.awaitility.core.ConditionFactory;
 
 public class CassandraMailRepositoryIntegrationTest {
 
+    private static final MailRepositoryUrl SENDER_DENIED_URL = MailRepositoryUrl.from("cassandra://var/mail/sender-denied/");
+
     @ClassRule
     public static DockerCassandraRule cassandra = new DockerCassandraRule();
     
@@ -74,7 +77,7 @@ public class CassandraMailRepositoryIntegrationTest {
             .sendMessage("denied@other.com", "user@domain.com");
 
         MailRepositoryProbeImpl repositoryProbe = server.getProbe(MailRepositoryProbeImpl.class);
-        await.until(() -> repositoryProbe.getRepositoryMailCount("cassandra://var/mail/sender-denied/") == 1);
+        await.until(() -> repositoryProbe.getRepositoryMailCount(SENDER_DENIED_URL) == 1);
     }
 
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/946c68be/server/container/guice/guice-common/src/main/java/org/apache/james/modules/server/MailStoreRepositoryModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/modules/server/MailStoreRepositoryModule.java b/server/container/guice/guice-common/src/main/java/org/apache/james/modules/server/MailStoreRepositoryModule.java
index a7e9eda..0365beb 100644
--- a/server/container/guice/guice-common/src/main/java/org/apache/james/modules/server/MailStoreRepositoryModule.java
+++ b/server/container/guice/guice-common/src/main/java/org/apache/james/modules/server/MailStoreRepositoryModule.java
@@ -25,6 +25,7 @@ import org.apache.james.filesystem.api.FileSystem;
 import org.apache.james.lifecycle.api.Configurable;
 import org.apache.james.mailrepository.api.MailRepository;
 import org.apache.james.mailrepository.api.MailRepositoryStore;
+import org.apache.james.mailrepository.api.MailRepositoryUrl;
 import org.apache.james.mailrepository.file.FileMailRepository;
 import org.apache.james.server.core.configuration.ConfigurationProvider;
 import org.apache.james.utils.ConfigurationPerformer;
@@ -69,7 +70,7 @@ public class MailStoreRepositoryModule extends AbstractModule {
         }
 
         @Override
-        public MailRepository provide(String url) {
+        public MailRepository provide(MailRepositoryUrl url) {
             FileMailRepository fileMailRepository = new FileMailRepository();
             fileMailRepository.setFileSystem(fileSystem);
             return fileMailRepository;

http://git-wip-us.apache.org/repos/asf/james-project/blob/946c68be/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java
----------------------------------------------------------------------
diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java
index 2c4fab7..0d87a8d 100644
--- a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java
+++ b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java
@@ -34,6 +34,8 @@ import org.apache.commons.configuration.HierarchicalConfiguration;
 import org.apache.james.lifecycle.api.Configurable;
 import org.apache.james.mailrepository.api.MailRepository;
 import org.apache.james.mailrepository.api.MailRepositoryStore;
+import org.apache.james.mailrepository.api.MailRepositoryUrl;
+import org.apache.james.mailrepository.api.Protocol;
 import org.apache.james.repository.api.Initializable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -43,36 +45,12 @@ import com.google.common.collect.ImmutableList;
 import com.google.inject.Inject;
 
 public class InMemoryMailRepositoryStore implements MailRepositoryStore, Configurable {
-
-    public static class Destination {
-
-        public static Destination fromUrl(String destinationUrl) throws MailRepositoryStoreException {
-            return new Destination(destinationUrl, retrieveProtocol(destinationUrl));
-        }
-
-        private static String retrieveProtocol(String destination) throws MailRepositoryStoreException {
-            int protocolSeparatorPosition = destination.indexOf(':');
-            if (protocolSeparatorPosition == -1) {
-                throw new MailRepositoryStoreException("Destination is malformed. Must be a valid URL: " + destination);
-            }
-            return destination.substring(0, protocolSeparatorPosition);
-        }
-
-        private final String url;
-        private final String protocol;
-
-        public Destination(String url, String protocol) {
-            this.url = url;
-            this.protocol = protocol;
-        }
-    }
-
     private static final Logger LOGGER = LoggerFactory.getLogger(InMemoryMailRepositoryStore.class);
 
     private final Set<MailRepositoryProvider> mailRepositories;
-    private final ConcurrentMap<String, MailRepository> destinationToRepositoryAssociations;
-    private final Map<String, MailRepositoryProvider> protocolToRepositoryProvider;
-    private final Map<String, HierarchicalConfiguration> perProtocolMailRepositoryDefaultConfiguration;
+    private final ConcurrentMap<MailRepositoryUrl, MailRepository> destinationToRepositoryAssociations;
+    private final Map<Protocol, MailRepositoryProvider> protocolToRepositoryProvider;
+    private final Map<Protocol, HierarchicalConfiguration> perProtocolMailRepositoryDefaultConfiguration;
     private HierarchicalConfiguration configuration;
 
     @Inject
@@ -84,7 +62,7 @@ public class InMemoryMailRepositoryStore implements MailRepositoryStore, Configu
     }
 
     @Override
-    public List<String> getUrls() {
+    public List<MailRepositoryUrl> getUrls() {
         return ImmutableList.copyOf(destinationToRepositoryAssociations.keySet());
     }
 
@@ -111,23 +89,22 @@ public class InMemoryMailRepositoryStore implements MailRepositoryStore, Configu
     }
 
     @Override
-    public Optional<MailRepository> get(String url) {
+    public Optional<MailRepository> get(MailRepositoryUrl url) {
         return Optional.ofNullable(destinationToRepositoryAssociations.get(url));
     }
 
     @Override
-    public MailRepository select(String destinationUrl) throws MailRepositoryStoreException {
-        Destination destination = Destination.fromUrl(destinationUrl);
-        return Optional.ofNullable(destinationToRepositoryAssociations.get(destination.url))
+    public MailRepository select(MailRepositoryUrl mailRepositoryUrl) {
+        return Optional.ofNullable(destinationToRepositoryAssociations.get(mailRepositoryUrl))
             .orElseGet(Throwing.supplier(
-                () -> createNewMailRepository(destination))
+                () -> createNewMailRepository(mailRepositoryUrl))
                 .sneakyThrow());
     }
 
-    private MailRepository createNewMailRepository(Destination destination) throws MailRepositoryStoreException {
-        MailRepository newMailRepository = retrieveMailRepository(destination);
-        newMailRepository = initializeNewRepository(newMailRepository, createRepositoryCombinedConfig(destination));
-        MailRepository previousRepository = destinationToRepositoryAssociations.putIfAbsent(destination.url, newMailRepository);
+    private MailRepository createNewMailRepository(MailRepositoryUrl mailRepositoryUrl) throws MailRepositoryStoreException {
+        MailRepository newMailRepository = retrieveMailRepository(mailRepositoryUrl);
+        newMailRepository = initializeNewRepository(newMailRepository, createRepositoryCombinedConfig(mailRepositoryUrl));
+        MailRepository previousRepository = destinationToRepositoryAssociations.putIfAbsent(mailRepositoryUrl, newMailRepository);
         return Optional.ofNullable(previousRepository)
             .orElse(newMailRepository);
     }
@@ -139,12 +116,12 @@ public class InMemoryMailRepositoryStore implements MailRepositoryStore, Configu
             .findAny()
             .orElseThrow(() -> new ConfigurationException("MailRepository " + className + " has not been registered"));
         for (String protocol : repositoryConfiguration.getStringArray("protocols.protocol")) {
-            protocolToRepositoryProvider.put(protocol, usedMailRepository);
-            registerRepositoryDefaultConfiguration(repositoryConfiguration, protocol);
+            protocolToRepositoryProvider.put(new Protocol(protocol), usedMailRepository);
+            registerRepositoryDefaultConfiguration(repositoryConfiguration, new Protocol(protocol));
         }
     }
 
-    private void registerRepositoryDefaultConfiguration(HierarchicalConfiguration repositoryConfiguration, String protocol) {
+    private void registerRepositoryDefaultConfiguration(HierarchicalConfiguration repositoryConfiguration, Protocol protocol) {
         HierarchicalConfiguration defConf = null;
         if (repositoryConfiguration.getKeys("config").hasNext()) {
             defConf = repositoryConfiguration.configurationAt("config");
@@ -154,14 +131,14 @@ public class InMemoryMailRepositoryStore implements MailRepositoryStore, Configu
         }
     }
 
-    private CombinedConfiguration createRepositoryCombinedConfig(Destination destination) {
+    private CombinedConfiguration createRepositoryCombinedConfig(MailRepositoryUrl mailRepositoryUrl) {
         CombinedConfiguration config = new CombinedConfiguration();
-        HierarchicalConfiguration defaultProtocolConfig = perProtocolMailRepositoryDefaultConfiguration.get(destination.protocol);
+        HierarchicalConfiguration defaultProtocolConfig = perProtocolMailRepositoryDefaultConfiguration.get(mailRepositoryUrl.getProtocol());
         if (defaultProtocolConfig != null) {
             config.addConfiguration(defaultProtocolConfig);
         }
         DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
-        builder.addProperty("[@destinationURL]", destination.url);
+        builder.addProperty("[@destinationURL]", mailRepositoryUrl.asString());
         config.addConfiguration(builder);
         return config;
     }
@@ -180,10 +157,11 @@ public class InMemoryMailRepositoryStore implements MailRepositoryStore, Configu
         }
     }
 
-    private MailRepository retrieveMailRepository(Destination destination) throws MailRepositoryStoreException {
-        return Optional.ofNullable(protocolToRepositoryProvider.get(destination.protocol))
-            .orElseThrow(() -> new MailRepositoryStoreException("No Mail Repository associated with " + destination.protocol))
-            .provide(destination.url);
+    private MailRepository retrieveMailRepository(MailRepositoryUrl mailRepositoryUrl) throws MailRepositoryStoreException {
+        Protocol protocol = mailRepositoryUrl.getProtocol();
+        return Optional.ofNullable(protocolToRepositoryProvider.get(protocol))
+            .orElseThrow(() -> new MailRepositoryStoreException("No Mail Repository associated with " + protocol.getValue()))
+            .provide(mailRepositoryUrl);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/946c68be/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailRepositoryProbeImpl.java
----------------------------------------------------------------------
diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailRepositoryProbeImpl.java b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailRepositoryProbeImpl.java
index f49fedd..71f7dec 100644
--- a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailRepositoryProbeImpl.java
+++ b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailRepositoryProbeImpl.java
@@ -23,7 +23,9 @@ import java.util.List;
 
 import javax.inject.Inject;
 
+import org.apache.james.mailrepository.api.MailKey;
 import org.apache.james.mailrepository.api.MailRepositoryStore;
+import org.apache.james.mailrepository.api.MailRepositoryUrl;
 
 import com.google.common.collect.ImmutableList;
 
@@ -39,23 +41,22 @@ public class MailRepositoryProbeImpl implements GuiceProbe {
     /**
      * Get the count of email currently stored in a given repository
      */
-    public long getRepositoryMailCount(String url) throws Exception {
+    public long getRepositoryMailCount(MailRepositoryUrl url) throws Exception {
         return repositoryStore.select(url).size();
     }
 
-    public void createRepository(String url) throws Exception {
+    public void createRepository(MailRepositoryUrl url) throws Exception {
         repositoryStore.select(url);
     }
 
-    public List<String> listMailKeys(String url) throws Exception {
+    public List<MailKey> listMailKeys(MailRepositoryUrl url) throws Exception {
         return ImmutableList.copyOf(
             repositoryStore.select(url)
                 .list());
     }
 
-    public List<String> listRepositoryUrls() {
-        return ImmutableList.copyOf(
-            repositoryStore.getUrls());
+    public List<MailRepositoryUrl> listRepositoryUrls() {
+        return ImmutableList.copyOf(repositoryStore.getUrls());
     }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/946c68be/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailRepositoryProvider.java
----------------------------------------------------------------------
diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailRepositoryProvider.java b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailRepositoryProvider.java
index e14bb5e..2338616 100644
--- a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailRepositoryProvider.java
+++ b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailRepositoryProvider.java
@@ -20,10 +20,11 @@
 package org.apache.james.utils;
 
 import org.apache.james.mailrepository.api.MailRepository;
+import org.apache.james.mailrepository.api.MailRepositoryUrl;
 
 public interface MailRepositoryProvider {
 
     String canonicalName();
 
-    MailRepository provide(String url);
+    MailRepository provide(MailRepositoryUrl url);
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/946c68be/server/container/guice/guice-common/src/test/java/org/apache/james/utils/InMemoryMailRepositoryStoreTest.java
----------------------------------------------------------------------
diff --git a/server/container/guice/guice-common/src/test/java/org/apache/james/utils/InMemoryMailRepositoryStoreTest.java b/server/container/guice/guice-common/src/test/java/org/apache/james/utils/InMemoryMailRepositoryStoreTest.java
index 3321933..cb1e18a 100644
--- a/server/container/guice/guice-common/src/test/java/org/apache/james/utils/InMemoryMailRepositoryStoreTest.java
+++ b/server/container/guice/guice-common/src/test/java/org/apache/james/utils/InMemoryMailRepositoryStoreTest.java
@@ -29,6 +29,7 @@ import org.apache.commons.configuration.HierarchicalConfiguration;
 import org.apache.james.core.builder.MimeMessageBuilder;
 import org.apache.james.mailrepository.api.MailRepository;
 import org.apache.james.mailrepository.api.MailRepositoryStore;
+import org.apache.james.mailrepository.api.MailRepositoryUrl;
 import org.apache.james.mailrepository.file.FileMailRepository;
 import org.apache.james.mailrepository.memory.MemoryMailRepository;
 import org.apache.james.modules.server.MailStoreRepositoryModule;
@@ -43,6 +44,7 @@ import org.junit.Test;
 import com.google.common.collect.Sets;
 
 public class InMemoryMailRepositoryStoreTest {
+    private static final MailRepositoryUrl FILE_REPO = MailRepositoryUrl.from("file://repo");
 
     private static class MemoryMailRepositoryProvider implements MailRepositoryProvider {
         @Override
@@ -51,7 +53,7 @@ public class InMemoryMailRepositoryStoreTest {
         }
 
         @Override
-        public MailRepository provide(String url) {
+        public MailRepository provide(MailRepositoryUrl url) {
             return new MemoryMailRepository();
         }
     }
@@ -77,23 +79,26 @@ public class InMemoryMailRepositoryStoreTest {
     }
 
     @Test(expected = MailRepositoryStore.MailRepositoryStoreException.class)
-    public void selectingANonRegisteredProtocolShouldFail() throws Exception {
-        repositoryStore.select("proto://repo");
+    public void selectingANonRegisteredProtocolShouldFail() {
+        repositoryStore.select(MailRepositoryUrl.from("proto://repo"));
     }
 
     @Test
-    public void selectingARegisteredProtocolShouldWork() throws Exception {
-        assertThat(repositoryStore.select("file://repo")).isInstanceOf(FileMailRepository.class);
+    public void selectingARegisteredProtocolShouldWork() {
+        assertThat(repositoryStore.select(FILE_REPO))
+            .isInstanceOf(FileMailRepository.class);
     }
 
     @Test
-    public void selectingTwiceARegisteredProtocolWithSameDestinationShouldReturnTheSameResult() throws Exception {
-        assertThat(repositoryStore.select("file://repo")).isEqualTo(repositoryStore.select("file://repo"));
+    public void selectingTwiceARegisteredProtocolWithSameDestinationShouldReturnTheSameResult() {
+        assertThat(repositoryStore.select(FILE_REPO))
+            .isEqualTo(repositoryStore.select(FILE_REPO));
     }
 
     @Test
-    public void selectingTwiceARegisteredProtocolWithDifferentDestinationShouldReturnDifferentResults() throws Exception {
-        assertThat(repositoryStore.select("file://repo")).isNotEqualTo(repositoryStore.select("file://repo1"));
+    public void selectingTwiceARegisteredProtocolWithDifferentDestinationShouldReturnDifferentResults() {
+        assertThat(repositoryStore.select(FILE_REPO))
+            .isNotEqualTo(repositoryStore.select(MailRepositoryUrl.from("file://repo1")));
     }
 
     @Test
@@ -123,10 +128,10 @@ public class InMemoryMailRepositoryStoreTest {
     }
 
     @Test
-    public void getUrlsShouldReturnUsedUrls() throws Exception {
-        String url1 = "file://repo1";
-        String url2 = "file://repo2";
-        String url3 = "file://repo3";
+    public void getUrlsShouldReturnUsedUrls() {
+        MailRepositoryUrl url1 = MailRepositoryUrl.from("file://repo1");
+        MailRepositoryUrl url2 = MailRepositoryUrl.from("file://repo2");
+        MailRepositoryUrl url3 = MailRepositoryUrl.from("file://repo3");
         repositoryStore.select(url1);
         repositoryStore.select(url2);
         repositoryStore.select(url3);
@@ -134,31 +139,29 @@ public class InMemoryMailRepositoryStoreTest {
     }
 
     @Test
-    public void getUrlsResultsShouldNotBeDuplicated() throws Exception {
-        String url1 = "file://repo1";
-        repositoryStore.select(url1);
-        repositoryStore.select(url1);
-        assertThat(repositoryStore.getUrls()).containsExactly(url1);
+    public void getUrlsResultsShouldNotBeDuplicated() {
+        repositoryStore.select(FILE_REPO);
+        repositoryStore.select(FILE_REPO);
+        assertThat(repositoryStore.getUrls()).containsExactly(FILE_REPO);
     }
 
     @Test
     public void getShouldReturnEmptyWhenUrlNotInUse() {
-        assertThat(repositoryStore.get("file://repo"))
+        assertThat(repositoryStore.get(FILE_REPO))
             .isEmpty();
     }
 
     @Test
-    public void getShouldReturnPreviouslyCreatedMailRepository() throws Exception {
-        String url = "file://repo";
-        MailRepository mailRepository = repositoryStore.select(url);
+    public void getShouldReturnPreviouslyCreatedMailRepository() {
+        MailRepository mailRepository = repositoryStore.select(FILE_REPO);
 
-        assertThat(repositoryStore.get(url))
+        assertThat(repositoryStore.get(FILE_REPO))
             .contains(mailRepository);
     }
 
     @Test
     public void selectShouldNotReturnDifferentResultsWhenUsedInAConcurrentEnvironment() throws Exception {
-        String url = "memory://repo";
+        MailRepositoryUrl url = MailRepositoryUrl.from("memory://repo");
         int threadCount = 10;
         int operationCount = 1;
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/946c68be/server/container/spring/src/main/java/org/apache/james/container/spring/bean/factory/mailrepositorystore/MailRepositoryStoreBeanFactory.java
----------------------------------------------------------------------
diff --git a/server/container/spring/src/main/java/org/apache/james/container/spring/bean/factory/mailrepositorystore/MailRepositoryStoreBeanFactory.java b/server/container/spring/src/main/java/org/apache/james/container/spring/bean/factory/mailrepositorystore/MailRepositoryStoreBeanFactory.java
index 2004442..b83af66 100644
--- a/server/container/spring/src/main/java/org/apache/james/container/spring/bean/factory/mailrepositorystore/MailRepositoryStoreBeanFactory.java
+++ b/server/container/spring/src/main/java/org/apache/james/container/spring/bean/factory/mailrepositorystore/MailRepositoryStoreBeanFactory.java
@@ -35,6 +35,8 @@ import org.apache.james.container.spring.bean.factory.AbstractBeanFactory;
 import org.apache.james.lifecycle.api.Configurable;
 import org.apache.james.mailrepository.api.MailRepository;
 import org.apache.james.mailrepository.api.MailRepositoryStore;
+import org.apache.james.mailrepository.api.MailRepositoryUrl;
+import org.apache.james.mailrepository.api.Protocol;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
@@ -49,17 +51,17 @@ public class MailRepositoryStoreBeanFactory extends AbstractBeanFactory implemen
     /**
      * Map of [destinationURL + type]->Repository
      */
-    private Map<String, MailRepository> repositories;
+    private Map<MailRepositoryUrl, MailRepository> repositories;
 
     /**
      * Map of [protocol(destinationURL) + type ]->classname of repository;
      */
-    private Map<String, String> classes;
+    private Map<Protocol, String> classes;
 
     /**
      * Map of [protocol(destinationURL) + type ]->default config for repository.
      */
-    private Map<String, HierarchicalConfiguration> defaultConfigs;
+    private Map<Protocol, HierarchicalConfiguration> defaultConfigs;
 
     /**
      * The configuration used by the instance
@@ -67,7 +69,7 @@ public class MailRepositoryStoreBeanFactory extends AbstractBeanFactory implemen
     private HierarchicalConfiguration configuration;
 
     @Override
-    public void configure(HierarchicalConfiguration configuration) throws ConfigurationException {
+    public void configure(HierarchicalConfiguration configuration) {
         this.configuration = configuration;
     }
 
@@ -88,7 +90,7 @@ public class MailRepositoryStoreBeanFactory extends AbstractBeanFactory implemen
     }
 
     @Override
-    public Optional<MailRepository> get(String url) throws MailRepositoryStoreException {
+    public Optional<MailRepository> get(MailRepositoryUrl url) {
         return Optional.ofNullable(repositories.get(url));
     }
 
@@ -121,14 +123,14 @@ public class MailRepositoryStoreBeanFactory extends AbstractBeanFactory implemen
 
             LOGGER.info("Registering Repository instance of class {} to handle {} protocol requests", className, protocol);
 
-            if (classes.get(protocol) != null) {
+            if (classes.get(new Protocol(protocol)) != null) {
                 throw new ConfigurationException("The combination of protocol and type comprise a unique key for repositories.  This constraint has been violated.  Please check your repository configuration.");
             }
 
-            classes.put(protocol, className);
+            classes.put(new Protocol(protocol), className);
 
             if (defConf != null) {
-                defaultConfigs.put(protocol, defConf);
+                defaultConfigs.put(new Protocol(protocol), defConf);
             }
         }
 
@@ -153,33 +155,26 @@ public class MailRepositoryStoreBeanFactory extends AbstractBeanFactory implemen
      */
     @Override
     @SuppressWarnings("deprecation")
-    public synchronized MailRepository select(String destination) throws MailRepositoryStoreException {
-        int idx = destination.indexOf(':');
-        if (idx == -1) {
-            throw new MailRepositoryStoreException("Destination is malformed. Must be a valid URL: " + destination);
-        }
-        String protocol = destination.substring(0, idx);
-
-        String repID = destination;
-        MailRepository reply = repositories.get(repID);
+    public synchronized MailRepository select(MailRepositoryUrl destination) throws MailRepositoryStoreException {
+        MailRepository reply = repositories.get(destination);
         if (reply != null) {
-            LOGGER.debug("obtained repository: {},{}", repID, reply.getClass());
+            LOGGER.debug("obtained repository: {},{}", destination, reply.getClass());
             return reply;
         } else {
-            String repClass = classes.get(protocol);
-            LOGGER.debug("obtained repository: {} to handle: {}", repClass, protocol);
+            String repClass = classes.get(destination.getProtocol());
+            LOGGER.debug("obtained repository: {} to handle: {}", repClass, destination.getProtocol().getValue());
 
             // If default values have been set, create a new repository
             // configuration element using the default values
             // and the values in the selector.
             // If no default values, just use the selector.
             final CombinedConfiguration config = new CombinedConfiguration();
-            HierarchicalConfiguration defConf = defaultConfigs.get(protocol);
+            HierarchicalConfiguration defConf = defaultConfigs.get(destination.getProtocol());
             if (defConf != null) {
                 config.addConfiguration(defConf);
             }
             DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
-            builder.addProperty("[@destinationURL]", destination);
+            builder.addProperty("[@destinationURL]", destination.asString());
             config.addConfiguration(builder);
 
             try {
@@ -192,10 +187,10 @@ public class MailRepositoryStoreBeanFactory extends AbstractBeanFactory implemen
                     ((Configurable) reply).configure(config);
                 }
 
-                reply = (MailRepository) getBeanFactory().initializeBean(reply, protocol);
+                reply = (MailRepository) getBeanFactory().initializeBean(reply, destination.getProtocol().getValue());
 
-                repositories.put(repID, reply);
-                LOGGER.info("added repository: {}->{}", repID, repClass);
+                repositories.put(destination, reply);
+                LOGGER.info("added repository: {}->{}", defConf, repClass);
                 return reply;
             } catch (Exception e) {
                 LOGGER.warn("Exception while creating repository: {}", e.getMessage(), e);
@@ -206,7 +201,7 @@ public class MailRepositoryStoreBeanFactory extends AbstractBeanFactory implemen
     }
 
     @Override
-    public synchronized List<String> getUrls() {
+    public synchronized List<MailRepositoryUrl> getUrls() {
         return new ArrayList<>(repositories.keySet());
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/946c68be/server/container/spring/src/main/java/org/apache/james/container/spring/tool/James23Importer.java
----------------------------------------------------------------------
diff --git a/server/container/spring/src/main/java/org/apache/james/container/spring/tool/James23Importer.java b/server/container/spring/src/main/java/org/apache/james/container/spring/tool/James23Importer.java
index 42eeded..c3bccbe 100644
--- a/server/container/spring/src/main/java/org/apache/james/container/spring/tool/James23Importer.java
+++ b/server/container/spring/src/main/java/org/apache/james/container/spring/tool/James23Importer.java
@@ -33,9 +33,11 @@ import org.apache.james.mailbox.MessageManager;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.exception.MailboxExistsException;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailrepository.api.MailKey;
 import org.apache.james.mailrepository.api.MailRepository;
 import org.apache.james.mailrepository.api.MailRepositoryStore;
 import org.apache.james.mailrepository.api.MailRepositoryStore.MailRepositoryStoreException;
+import org.apache.james.mailrepository.api.MailRepositoryUrl;
 import org.apache.james.server.core.MimeMessageInputStream;
 import org.apache.james.user.api.UsersRepository;
 import org.apache.james.user.api.UsersRepositoryException;
@@ -135,8 +137,8 @@ public class James23Importer {
         while (james23userRepositoryIterator.hasNext()) {
 
             String userName23 = james23userRepositoryIterator.next();
-            MailRepository mailRepository = mailRepositoryStore.select(james23MailRepositoryPath + "/" + userName23);
-            Iterator<String> mailRepositoryIterator = mailRepository.list();
+            MailRepository mailRepository = mailRepositoryStore.select(MailRepositoryUrl.from(james23MailRepositoryPath + "/" + userName23));
+            Iterator<MailKey> mailRepositoryIterator = mailRepository.list();
 
             String userName30 = convert23UserTo30(userName23);
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/946c68be/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryStore.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryStore.java b/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryStore.java
index 37f1902..e13c31c 100644
--- a/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryStore.java
+++ b/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryStore.java
@@ -31,13 +31,13 @@ public interface MailRepositoryStore {
      * @return repository
      * @throws MailRepositoryStoreException
      */
-    MailRepository select(String url) throws MailRepositoryStoreException;
+    MailRepository select(MailRepositoryUrl url) throws MailRepositoryStoreException;
 
     /**
      * Create the {@link MailRepository} for the given url and return it. If the repository already exists,
      * then no new repository is created, the old one will be returned.
      */
-    default MailRepository create(String url) throws MailRepositoryStoreException {
+    default MailRepository create(MailRepositoryUrl url) throws MailRepositoryStoreException {
         return select(url);
     }
 
@@ -45,7 +45,7 @@ public interface MailRepositoryStore {
      * Returns the {@link MailRepository} for the given url.
      * This mail repository will not be created if it does not exist.
      */
-    Optional<MailRepository> get(String url) throws MailRepositoryStoreException;
+    Optional<MailRepository> get(MailRepositoryUrl url) throws MailRepositoryStoreException;
 
     /**
      * Return a {@link List} which contains all urls of the selected
@@ -53,7 +53,7 @@ public interface MailRepositoryStore {
      * 
      * @return urls
      */
-    List<String> getUrls();
+    List<MailRepositoryUrl> getUrls();
 
     class MailRepositoryStoreException extends Exception {
         public MailRepositoryStoreException(String msg, Throwable t) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/946c68be/server/data/data-file/src/main/java/org/apache/james/mailrepository/file/FileMailRepository.java
----------------------------------------------------------------------
diff --git a/server/data/data-file/src/main/java/org/apache/james/mailrepository/file/FileMailRepository.java b/server/data/data-file/src/main/java/org/apache/james/mailrepository/file/FileMailRepository.java
index 2123562..1f6b1d1 100644
--- a/server/data/data-file/src/main/java/org/apache/james/mailrepository/file/FileMailRepository.java
+++ b/server/data/data-file/src/main/java/org/apache/james/mailrepository/file/FileMailRepository.java
@@ -36,6 +36,7 @@ import javax.mail.internet.MimeMessage;
 import org.apache.commons.configuration.DefaultConfigurationBuilder;
 import org.apache.commons.configuration.HierarchicalConfiguration;
 import org.apache.james.filesystem.api.FileSystem;
+import org.apache.james.mailrepository.api.MailKey;
 import org.apache.james.mailrepository.lib.AbstractMailRepository;
 import org.apache.james.repository.file.FilePersistentObjectRepository;
 import org.apache.james.repository.file.FilePersistentStreamRepository;
@@ -124,7 +125,7 @@ public class FileMailRepository extends AbstractMailRepository {
             Collection<String> strandedStreams = (Collection<String>) streamKeys.clone();
             strandedStreams.removeAll(objectKeys);
             for (Object strandedStream : strandedStreams) {
-                String key = (String) strandedStream;
+                MailKey key = new MailKey((String) strandedStream);
                 remove(key);
             }
 
@@ -132,7 +133,7 @@ public class FileMailRepository extends AbstractMailRepository {
             Collection<String> strandedObjects = (Collection<String>) objectKeys.clone();
             strandedObjects.removeAll(streamKeys);
             for (Object strandedObject : strandedObjects) {
-                String key = (String) strandedObject;
+                MailKey key = new MailKey((String) strandedObject);
                 remove(key);
             }
 
@@ -218,11 +219,11 @@ public class FileMailRepository extends AbstractMailRepository {
     }
 
     @Override
-    public Mail retrieve(String key) throws MessagingException {
+    public Mail retrieve(MailKey key) throws MessagingException {
         try {
             Mail mc;
             try {
-                mc = (Mail) objectRepository.get(key);
+                mc = (Mail) objectRepository.get(key.asString());
             } catch (RuntimeException re) {
                 if (re.getCause() instanceof Error) {
                     LOGGER.warn("Error when retrieving mail, not deleting: {}", re, re);
@@ -232,7 +233,7 @@ public class FileMailRepository extends AbstractMailRepository {
                 }
                 return null;
             }
-            MimeMessageStreamRepositorySource source = new MimeMessageStreamRepositorySource(streamRepository, destination, key);
+            MimeMessageStreamRepositorySource source = new MimeMessageStreamRepositorySource(streamRepository, destination, key.asString());
             mc.setMessage(new MimeMessageCopyOnWriteProxy(source));
 
             return mc;
@@ -243,16 +244,16 @@ public class FileMailRepository extends AbstractMailRepository {
     }
 
     @Override
-    protected void internalRemove(String key) throws MessagingException {
+    protected void internalRemove(MailKey key) throws MessagingException {
         if (keys != null) {
-            keys.remove(key);
+            keys.remove(key.asString());
         }
-        streamRepository.remove(key);
-        objectRepository.remove(key);
+        streamRepository.remove(key.asString());
+        objectRepository.remove(key.asString());
     }
 
     @Override
-    public Iterator<String> list() {
+    public Iterator<MailKey> list() {
         // Fix ConcurrentModificationException by cloning
         // the keyset before getting an iterator
         final ArrayList<String> clone;
@@ -270,6 +271,8 @@ public class FileMailRepository extends AbstractMailRepository {
             Collections.sort(clone); // Keys is a HashSet; impose FIFO for apps
         }
         // that need it
-        return clone.iterator();
+        return clone.stream()
+            .map(MailKey::new)
+            .iterator();
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/946c68be/server/data/data-file/src/main/java/org/apache/james/mailrepository/file/MBoxMailRepository.java
----------------------------------------------------------------------
diff --git a/server/data/data-file/src/main/java/org/apache/james/mailrepository/file/MBoxMailRepository.java b/server/data/data-file/src/main/java/org/apache/james/mailrepository/file/MBoxMailRepository.java
index bcc69bb..e4f8350 100755
--- a/server/data/data-file/src/main/java/org/apache/james/mailrepository/file/MBoxMailRepository.java
+++ b/server/data/data-file/src/main/java/org/apache/james/mailrepository/file/MBoxMailRepository.java
@@ -71,6 +71,7 @@ import org.apache.commons.configuration.ConfigurationException;
 import org.apache.commons.configuration.HierarchicalConfiguration;
 import org.apache.commons.io.FileUtils;
 import org.apache.james.lifecycle.api.Configurable;
+import org.apache.james.mailrepository.api.MailKey;
 import org.apache.james.mailrepository.api.MailRepository;
 import org.apache.james.server.core.MailImpl;
 import org.apache.mailet.Mail;
@@ -467,7 +468,7 @@ public class MBoxMailRepository implements MailRepository, Configurable {
     }
 
     @Override
-    public void store(Mail mc) {
+    public MailKey store(Mail mc) {
         LOGGER.debug("Will store message to file {}", mboxFile);
 
         this.mList = null;
@@ -494,16 +495,16 @@ public class MBoxMailRepository implements MailRepository, Configurable {
             saveFile.writeBytes((fromHeader + "\n"));
             saveFile.writeBytes((message + "\n"));
             saveFile.close();
-
         } catch (FileNotFoundException e) {
             LOGGER.error("Unable to save(open) file (File not found) {}", mboxFile, e);
         } catch (IOException e) {
             LOGGER.error("Unable to write file (General I/O problem) {}", mboxFile, e);
         }
+        return MailKey.forMail(mc);
     }
 
     @Override
-    public Iterator<String> list() {
+    public Iterator<MailKey> list() {
         ArrayList<String> keys = loadKeysAsArray();
 
         if (!keys.isEmpty()) {
@@ -517,7 +518,9 @@ public class MBoxMailRepository implements MailRepository, Configurable {
         if (fifo) {
             Collections.sort(keys); // Keys is a HashSet; impose FIFO for apps that need it
         }
-        return keys.iterator();
+        return keys.stream()
+            .map(MailKey::new)
+            .iterator();
     }
 
     private ArrayList<String> loadKeysAsArray() {
@@ -526,19 +529,19 @@ public class MBoxMailRepository implements MailRepository, Configurable {
     }
 
     @Override
-    public Mail retrieve(String key) throws MessagingException {
+    public Mail retrieve(MailKey key) throws MessagingException {
 
         loadKeys();
         MailImpl res;
 
-        MimeMessage foundMessage = findMessage(key);
+        MimeMessage foundMessage = findMessage(key.asString());
         if (foundMessage == null) {
             LOGGER.error("found message is null!");
             return null;
         }
         res = new MailImpl();
         res.setMessage(foundMessage);
-        res.setName(key);
+        res.setName(key.asString());
         LOGGER.debug("Retrieving entry for key {}", key);
         return res;
     }
@@ -669,7 +672,7 @@ public class MBoxMailRepository implements MailRepository, Configurable {
     }
 
     @Override
-    public void remove(String key) throws MessagingException {
+    public void remove(MailKey key) throws MessagingException {
         loadKeys();
         try {
             lockMBox();
@@ -685,23 +688,23 @@ public class MBoxMailRepository implements MailRepository, Configurable {
     }
 
     @Override
-    public boolean lock(String key) {
+    public boolean lock(MailKey key) {
         return false;
     }
 
     @Override
-    public boolean unlock(String key) {
+    public boolean unlock(MailKey key) {
         return false;
     }
 
     @Override
-    public long size() throws MessagingException {
+    public long size() {
         return loadKeysAsArray().size();
     }
 
     @Override
     public void removeAll() throws MessagingException {
         ImmutableList.copyOf(list())
-            .forEach(Throwing.<String>consumer(this::remove).sneakyThrow());
+            .forEach(Throwing.<MailKey>consumer(this::remove).sneakyThrow());
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/946c68be/server/data/data-file/src/test/java/org/apache/james/mailrepository/MBoxMailRepositoryTest.java
----------------------------------------------------------------------
diff --git a/server/data/data-file/src/test/java/org/apache/james/mailrepository/MBoxMailRepositoryTest.java b/server/data/data-file/src/test/java/org/apache/james/mailrepository/MBoxMailRepositoryTest.java
index b874cd9..30ff7b0 100644
--- a/server/data/data-file/src/test/java/org/apache/james/mailrepository/MBoxMailRepositoryTest.java
+++ b/server/data/data-file/src/test/java/org/apache/james/mailrepository/MBoxMailRepositoryTest.java
@@ -26,6 +26,7 @@ import java.util.Iterator;
 
 import org.apache.commons.configuration.DefaultConfigurationBuilder;
 import org.apache.james.filesystem.api.mock.MockFileSystem;
+import org.apache.james.mailrepository.api.MailKey;
 import org.apache.james.mailrepository.api.MailRepository;
 import org.apache.james.mailrepository.file.MBoxMailRepository;
 import org.junit.Test;
@@ -67,7 +68,7 @@ public class MBoxMailRepositoryTest {
     public void testReadMboxrdFile() throws Exception {
         MailRepository mr = getMailRepository();
 
-        Iterator<String> keys = mr.list();
+        Iterator<MailKey> keys = mr.list();
 
         assertTrue("Two messages in list", keys.hasNext());
         keys.next();

http://git-wip-us.apache.org/repos/asf/james-project/blob/946c68be/server/data/data-jcr/src/main/java/org/apache/james/mailrepository/jcr/JCRMailRepository.java
----------------------------------------------------------------------
diff --git a/server/data/data-jcr/src/main/java/org/apache/james/mailrepository/jcr/JCRMailRepository.java b/server/data/data-jcr/src/main/java/org/apache/james/mailrepository/jcr/JCRMailRepository.java
index 1f9328c..0f57114 100644
--- a/server/data/data-jcr/src/main/java/org/apache/james/mailrepository/jcr/JCRMailRepository.java
+++ b/server/data/data-jcr/src/main/java/org/apache/james/mailrepository/jcr/JCRMailRepository.java
@@ -59,6 +59,7 @@ import org.apache.jackrabbit.commons.cnd.CndImporter;
 import org.apache.jackrabbit.util.ISO9075;
 import org.apache.jackrabbit.util.Text;
 import org.apache.james.core.MailAddress;
+import org.apache.james.mailrepository.api.MailKey;
 import org.apache.james.mailrepository.api.MailRepository;
 import org.apache.james.mailrepository.lib.AbstractMailRepository;
 import org.apache.james.server.core.MailImpl;
@@ -118,7 +119,7 @@ public class JCRMailRepository extends AbstractMailRepository implements MailRep
     }
 
     @Override
-    public Iterator<String> list() throws MessagingException {
+    public Iterator<MailKey> list() throws MessagingException {
         try {
             Session session = login();
             try {
@@ -130,7 +131,9 @@ public class JCRMailRepository extends AbstractMailRepository implements MailRep
                     String name = iterator.nextNode().getName();
                     keys.add(Text.unescapeIllegalJcrChars(name));
                 }
-                return keys.iterator();
+                return keys.stream()
+                    .map(MailKey::new)
+                    .iterator();
             } finally {
                 session.logout();
             }
@@ -140,11 +143,11 @@ public class JCRMailRepository extends AbstractMailRepository implements MailRep
     }
 
     @Override
-    public Mail retrieve(String key) throws MessagingException {
+    public Mail retrieve(MailKey key) throws MessagingException {
         try {
             Session session = login();
             try {
-                String name = toSafeName(key);
+                String name = toSafeName(key.asString());
                 QueryManager manager = session.getWorkspace().getQueryManager();
                 Query query = manager.createQuery("/jcr:root/" + MAIL_PATH + "//element(" + name + ",james:mail)", Query.XPATH);
                 NodeIterator iterator = query.execute().getNodes();
@@ -591,11 +594,11 @@ public class JCRMailRepository extends AbstractMailRepository implements MailRep
     }
 
     @Override
-    protected void internalRemove(String key) throws MessagingException {
+    protected void internalRemove(MailKey key) throws MessagingException {
         try {
             Session session = login();
             try {
-                String name = ISO9075.encode(Text.escapeIllegalJcrChars(key));
+                String name = ISO9075.encode(Text.escapeIllegalJcrChars(key.asString()));
                 QueryManager manager = session.getWorkspace().getQueryManager();
                 Query query = manager.createQuery("/jcr:root/" + MAIL_PATH + "//element(" + name + ",james:mail)", Query.XPATH);
                 NodeIterator nodes = query.execute().getNodes();

http://git-wip-us.apache.org/repos/asf/james-project/blob/946c68be/server/data/data-jdbc/src/main/java/org/apache/james/mailrepository/jdbc/JDBCMailRepository.java
----------------------------------------------------------------------
diff --git a/server/data/data-jdbc/src/main/java/org/apache/james/mailrepository/jdbc/JDBCMailRepository.java b/server/data/data-jdbc/src/main/java/org/apache/james/mailrepository/jdbc/JDBCMailRepository.java
index dae0b7b..31a728e 100644
--- a/server/data/data-jdbc/src/main/java/org/apache/james/mailrepository/jdbc/JDBCMailRepository.java
+++ b/server/data/data-jdbc/src/main/java/org/apache/james/mailrepository/jdbc/JDBCMailRepository.java
@@ -53,6 +53,7 @@ import org.apache.commons.configuration.DefaultConfigurationBuilder;
 import org.apache.commons.configuration.HierarchicalConfiguration;
 import org.apache.james.core.MailAddress;
 import org.apache.james.filesystem.api.FileSystem;
+import org.apache.james.mailrepository.api.MailKey;
 import org.apache.james.mailrepository.lib.AbstractMailRepository;
 import org.apache.james.repository.file.FilePersistentStreamRepository;
 import org.apache.james.server.core.MailImpl;
@@ -592,7 +593,7 @@ public class JDBCMailRepository extends AbstractMailRepository {
 
     @Override
     @SuppressWarnings("unchecked")
-    public Mail retrieve(String key) throws MessagingException {
+    public Mail retrieve(MailKey key) throws MessagingException {
         if (DEEP_DEBUG) {
             System.err.println("retrieving " + key);
         }
@@ -606,7 +607,7 @@ public class JDBCMailRepository extends AbstractMailRepository {
             }
 
             retrieveMessage = conn.prepareStatement(sqlQueries.getSqlString("retrieveMessageSQL", true));
-            retrieveMessage.setString(1, key);
+            retrieveMessage.setString(1, key.asString());
             retrieveMessage.setString(2, repositoryName);
             rsMessage = retrieveMessage.executeQuery();
             if (DEEP_DEBUG) {
@@ -625,7 +626,7 @@ public class JDBCMailRepository extends AbstractMailRepository {
                 try {
                     retrieveMessageAttr = conn.prepareStatement(retrieveMessageAttrSql);
 
-                    retrieveMessageAttr.setString(1, key);
+                    retrieveMessageAttr.setString(1, key.asString());
                     retrieveMessageAttr.setString(2, repositoryName);
                     rsMessageAttr = retrieveMessageAttr.executeQuery();
 
@@ -662,7 +663,7 @@ public class JDBCMailRepository extends AbstractMailRepository {
 
             MailImpl mc = new MailImpl();
             mc.setAttributesRaw(attributes);
-            mc.setName(key);
+            mc.setName(key.asString());
             mc.setState(rsMessage.getString(1));
             mc.setErrorMessage(rsMessage.getString(2));
             String sender = rsMessage.getString(3);
@@ -681,7 +682,7 @@ public class JDBCMailRepository extends AbstractMailRepository {
             mc.setRemoteAddr(rsMessage.getString(6));
             mc.setLastUpdated(rsMessage.getTimestamp(7));
 
-            MimeMessageJDBCSource source = new MimeMessageJDBCSource(this, key, sr);
+            MimeMessageJDBCSource source = new MimeMessageJDBCSource(this, key.asString(), sr);
             MimeMessageCopyOnWriteProxy message = new MimeMessageCopyOnWriteProxy(source);
             mc.setMessage(message);
             return mc;
@@ -699,18 +700,18 @@ public class JDBCMailRepository extends AbstractMailRepository {
     }
 
     @Override
-    protected void internalRemove(String key) throws MessagingException {
+    protected void internalRemove(MailKey key) throws MessagingException {
         Connection conn = null;
         PreparedStatement removeMessage = null;
         try {
             conn = datasource.getConnection();
             removeMessage = conn.prepareStatement(sqlQueries.getSqlString("removeMessageSQL", true));
-            removeMessage.setString(1, key);
+            removeMessage.setString(1, key.asString());
             removeMessage.setString(2, repositoryName);
             removeMessage.execute();
 
             if (sr != null) {
-                sr.remove(key);
+                sr.remove(key.asString());
             }
         } catch (Exception me) {
             throw new MessagingException("Exception while removing mail: " + me.getMessage(), me);
@@ -721,7 +722,7 @@ public class JDBCMailRepository extends AbstractMailRepository {
     }
 
     @Override
-    public Iterator<String> list() throws MessagingException {
+    public Iterator<MailKey> list() throws MessagingException {
         // System.err.println("listing messages");
         Connection conn = null;
         PreparedStatement listMessages = null;
@@ -736,7 +737,9 @@ public class JDBCMailRepository extends AbstractMailRepository {
             while (rsListMessages.next() && !Thread.currentThread().isInterrupted()) {
                 messageList.add(rsListMessages.getString(1));
             }
-            return messageList.iterator();
+            return messageList.stream()
+                .map(MailKey::new)
+                .iterator();
         } catch (Exception me) {
             throw new MessagingException("Exception while listing mail: " + me.getMessage(), me);
         } finally {

http://git-wip-us.apache.org/repos/asf/james-project/blob/946c68be/server/data/data-library/src/main/java/org/apache/james/mailrepository/lib/AbstractMailRepository.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/main/java/org/apache/james/mailrepository/lib/AbstractMailRepository.java b/server/data/data-library/src/main/java/org/apache/james/mailrepository/lib/AbstractMailRepository.java
index bc9b813..4e988e5 100644
--- a/server/data/data-library/src/main/java/org/apache/james/mailrepository/lib/AbstractMailRepository.java
+++ b/server/data/data-library/src/main/java/org/apache/james/mailrepository/lib/AbstractMailRepository.java
@@ -27,6 +27,7 @@ import javax.mail.MessagingException;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.commons.configuration.HierarchicalConfiguration;
 import org.apache.james.lifecycle.api.Configurable;
+import org.apache.james.mailrepository.api.MailKey;
 import org.apache.james.mailrepository.api.MailRepository;
 import org.apache.james.repository.api.Initializable;
 import org.apache.mailet.Mail;
@@ -73,7 +74,7 @@ public abstract class AbstractMailRepository implements MailRepository, Configur
      * @return true if successfully released the lock, false otherwise
      */
     @Override
-    public boolean unlock(String key) {
+    public boolean unlock(MailKey key) {
         return lock.unlock(key);
     }
 
@@ -86,14 +87,14 @@ public abstract class AbstractMailRepository implements MailRepository, Configur
      * @return true if successfully obtained the lock, false otherwise
      */
     @Override
-    public boolean lock(String key) {
+    public boolean lock(MailKey key) {
         return lock.lock(key);
     }
 
     @Override
-    public void store(Mail mc) throws MessagingException {
+    public MailKey store(Mail mc) throws MessagingException {
         boolean wasLocked = true;
-        String key = mc.getName();
+        MailKey key = MailKey.forMail(mc);
         try {
             synchronized (this) {
                 wasLocked = lock.isLocked(key);
@@ -103,6 +104,7 @@ public abstract class AbstractMailRepository implements MailRepository, Configur
                 }
             }
             internalStore(mc);
+            return key;
         } catch (MessagingException e) {
             LOGGER.error("Exception caught while storing mail {}", key, e);
             throw e;
@@ -124,7 +126,7 @@ public abstract class AbstractMailRepository implements MailRepository, Configur
 
     @Override
     public void remove(Mail mail) throws MessagingException {
-        remove(mail.getName());
+        remove(MailKey.forMail(mail));
     }
 
     @Override
@@ -135,7 +137,7 @@ public abstract class AbstractMailRepository implements MailRepository, Configur
     }
 
     @Override
-    public void remove(String key) throws MessagingException {
+    public void remove(MailKey key) throws MessagingException {
         if (lock(key)) {
             try {
                 internalRemove(key);
@@ -143,12 +145,11 @@ public abstract class AbstractMailRepository implements MailRepository, Configur
                 unlock(key);
             }
         } else {
-            String exceptionBuffer = "Cannot lock " + key + " to remove it";
-            throw new MessagingException(exceptionBuffer.toString());
+            throw new MessagingException("Cannot lock " + key + " to remove it");
         }
     }
 
-    protected abstract void internalRemove(String key) throws MessagingException;
+    protected abstract void internalRemove(MailKey key) throws MessagingException;
 
     @Override
     public long size() throws MessagingException {
@@ -158,6 +159,6 @@ public abstract class AbstractMailRepository implements MailRepository, Configur
     @Override
     public void removeAll() throws MessagingException {
         ImmutableList.copyOf(list())
-            .forEach(Throwing.<String>consumer(this::remove).sneakyThrow());
+            .forEach(Throwing.<MailKey>consumer(this::remove).sneakyThrow());
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/946c68be/server/data/data-library/src/test/java/org/apache/james/mailrepository/mock/MockMailRepositoryStore.java
----------------------------------------------------------------------
diff --git a/server/data/data-library/src/test/java/org/apache/james/mailrepository/mock/MockMailRepositoryStore.java b/server/data/data-library/src/test/java/org/apache/james/mailrepository/mock/MockMailRepositoryStore.java
index ef9e085..f232e43 100644
--- a/server/data/data-library/src/test/java/org/apache/james/mailrepository/mock/MockMailRepositoryStore.java
+++ b/server/data/data-library/src/test/java/org/apache/james/mailrepository/mock/MockMailRepositoryStore.java
@@ -27,27 +27,28 @@ import java.util.Optional;
 
 import org.apache.james.mailrepository.api.MailRepository;
 import org.apache.james.mailrepository.api.MailRepositoryStore;
+import org.apache.james.mailrepository.api.MailRepositoryUrl;
 
 public class MockMailRepositoryStore implements MailRepositoryStore {
 
-    final Map<String, MailRepository> storedObjectMap = new HashMap<>();
+    private final Map<MailRepositoryUrl, MailRepository> storedObjectMap = new HashMap<>();
 
-    public void add(String url, MailRepository obj) {
+    public void add(MailRepositoryUrl url, MailRepository obj) {
         storedObjectMap.put(url, obj);
     }
 
     @Override
-    public MailRepository select(String url) throws MailRepositoryStoreException {
+    public MailRepository select(MailRepositoryUrl url) {
         return storedObjectMap.get(url);
     }
 
     @Override
-    public Optional<MailRepository> get(String url) throws MailRepositoryStoreException {
+    public Optional<MailRepository> get(MailRepositoryUrl url) {
         return Optional.ofNullable(storedObjectMap.get(url));
     }
 
     @Override
-    public List<String> getUrls() {
+    public List<MailRepositoryUrl> getUrls() {
         return new ArrayList<>(storedObjectMap.keySet());
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/946c68be/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/MailetErrorsTest.java
----------------------------------------------------------------------
diff --git a/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/MailetErrorsTest.java b/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/MailetErrorsTest.java
index ffd8013..0dc9ed0 100644
--- a/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/MailetErrorsTest.java
+++ b/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/MailetErrorsTest.java
@@ -31,6 +31,7 @@ import org.apache.james.mailets.configuration.CommonProcessors;
 import org.apache.james.mailets.configuration.MailetConfiguration;
 import org.apache.james.mailets.configuration.MailetContainer;
 import org.apache.james.mailets.configuration.ProcessorConfiguration;
+import org.apache.james.mailrepository.api.MailRepositoryUrl;
 import org.apache.james.transport.mailets.ErrorMailet;
 import org.apache.james.transport.mailets.ErrorMatcher;
 import org.apache.james.transport.mailets.NoopMailet;
@@ -49,7 +50,7 @@ import org.junit.rules.TemporaryFolder;
 
 public class MailetErrorsTest {
     public static final String CUSTOM_PROCESSOR = "custom";
-    public static final String CUSTOM_REPOSITORY = "file://var/mail/custom/";
+    public static final MailRepositoryUrl CUSTOM_REPOSITORY = MailRepositoryUrl.from("file://var/mail/custom/");
 
     @Rule
     public TemporaryFolder temporaryFolder = new TemporaryFolder();
@@ -162,7 +163,7 @@ public class MailetErrorsTest {
                     .addMailet(MailetConfiguration.builder()
                         .matcher(All.class)
                         .mailet(ToRepository.class)
-                        .addProperty("repositoryPath", CUSTOM_REPOSITORY))))
+                        .addProperty("repositoryPath", CUSTOM_REPOSITORY.asString()))))
             .build(temporaryFolder);
         MailRepositoryProbeImpl probe = jamesServer.getProbe(MailRepositoryProbeImpl.class);
 
@@ -187,7 +188,7 @@ public class MailetErrorsTest {
                     .addMailet(MailetConfiguration.builder()
                         .matcher(All.class)
                         .mailet(ToRepository.class)
-                        .addProperty("repositoryPath", CUSTOM_REPOSITORY))))
+                        .addProperty("repositoryPath", CUSTOM_REPOSITORY.asString()))))
             .build(temporaryFolder);
         MailRepositoryProbeImpl probe = jamesServer.getProbe(MailRepositoryProbeImpl.class);
 
@@ -292,7 +293,7 @@ public class MailetErrorsTest {
                     .addMailet(MailetConfiguration.builder()
                         .matcher(All.class)
                         .mailet(ToRepository.class)
-                        .addProperty("repositoryPath", CUSTOM_REPOSITORY))))
+                        .addProperty("repositoryPath", CUSTOM_REPOSITORY.asString()))))
             .build(temporaryFolder);
         MailRepositoryProbeImpl probe = jamesServer.getProbe(MailRepositoryProbeImpl.class);
 
@@ -317,7 +318,7 @@ public class MailetErrorsTest {
                     .addMailet(MailetConfiguration.builder()
                         .matcher(All.class)
                         .mailet(ToRepository.class)
-                        .addProperty("repositoryPath", CUSTOM_REPOSITORY))))
+                        .addProperty("repositoryPath", CUSTOM_REPOSITORY.asString()))))
             .build(temporaryFolder);
         MailRepositoryProbeImpl probe = jamesServer.getProbe(MailRepositoryProbeImpl.class);
 
@@ -338,7 +339,7 @@ public class MailetErrorsTest {
                     .addMailet(MailetConfiguration.builder()
                         .matcher(RuntimeErrorMatcher.class)
                         .mailet(ToRepository.class)
-                        .addProperty("repositoryPath", CUSTOM_REPOSITORY)
+                        .addProperty("repositoryPath", CUSTOM_REPOSITORY.asString())
                         .addProperty("onMatchException", "matchall"))
                     .addMailet(MailetConfiguration.builder()
                         .matcher(All.class)
@@ -363,7 +364,7 @@ public class MailetErrorsTest {
                     .addMailet(MailetConfiguration.builder()
                         .matcher(ErrorMatcher.class)
                         .mailet(ToRepository.class)
-                        .addProperty("repositoryPath", CUSTOM_REPOSITORY)
+                        .addProperty("repositoryPath", CUSTOM_REPOSITORY.asString())
                         .addProperty("onMatchException", "matchall"))
                     .addMailet(MailetConfiguration.builder()
                         .matcher(All.class)
@@ -387,11 +388,11 @@ public class MailetErrorsTest {
                             .matcher(HasException.class)
                             .matcherCondition("javax.mail.MessagingException")
                             .mailet(ToRepository.class)
-                            .addProperty("repositoryPath", CUSTOM_REPOSITORY))
+                            .addProperty("repositoryPath", CUSTOM_REPOSITORY.asString()))
                     .addMailet(MailetConfiguration.builder()
                             .matcher(All.class)
                             .mailet(ToRepository.class)
-                            .addProperty("repositoryPath", ERROR_REPOSITORY)))
+                            .addProperty("repositoryPath", ERROR_REPOSITORY.asString())))
                 .putProcessor(customProcessor())
                 .putProcessor(ProcessorConfiguration.root()
                     .addMailet(MailetConfiguration.builder()
@@ -416,11 +417,11 @@ public class MailetErrorsTest {
                             .matcher(HasException.class)
                             .matcherCondition("javax.mail.MessagingException")
                             .mailet(ToRepository.class)
-                            .addProperty("repositoryPath", CUSTOM_REPOSITORY))
+                            .addProperty("repositoryPath", CUSTOM_REPOSITORY.asString()))
                     .addMailet(MailetConfiguration.builder()
                             .matcher(All.class)
                             .mailet(ToRepository.class)
-                            .addProperty("repositoryPath", ERROR_REPOSITORY)))
+                            .addProperty("repositoryPath", ERROR_REPOSITORY.asString())))
                 .putProcessor(customProcessor())
                 .putProcessor(ProcessorConfiguration.root()
                     .addMailet(MailetConfiguration.builder()
@@ -445,11 +446,11 @@ public class MailetErrorsTest {
                             .matcher(HasException.class)
                             .matcherCondition("javax.mail.MessagingException")
                             .mailet(ToRepository.class)
-                            .addProperty("repositoryPath", CUSTOM_REPOSITORY))
+                            .addProperty("repositoryPath", CUSTOM_REPOSITORY.asString()))
                     .addMailet(MailetConfiguration.builder()
                             .matcher(All.class)
                             .mailet(ToRepository.class)
-                            .addProperty("repositoryPath", ERROR_REPOSITORY)))
+                            .addProperty("repositoryPath", ERROR_REPOSITORY.asString())))
                 .putProcessor(customProcessor())
                 .putProcessor(ProcessorConfiguration.root()
                     .addMailet(MailetConfiguration.builder()
@@ -474,11 +475,11 @@ public class MailetErrorsTest {
                             .matcher(HasException.class)
                             .matcherCondition("javax.mail.MessagingException")
                             .mailet(ToRepository.class)
-                            .addProperty("repositoryPath", CUSTOM_REPOSITORY))
+                            .addProperty("repositoryPath", CUSTOM_REPOSITORY.asString()))
                     .addMailet(MailetConfiguration.builder()
                             .matcher(All.class)
                             .mailet(ToRepository.class)
-                            .addProperty("repositoryPath", ERROR_REPOSITORY)))
+                            .addProperty("repositoryPath", ERROR_REPOSITORY.asString())))
                 .putProcessor(customProcessor())
                 .putProcessor(ProcessorConfiguration.root()
                     .addMailet(MailetConfiguration.builder()
@@ -497,7 +498,7 @@ public class MailetErrorsTest {
             .addMailet(MailetConfiguration.builder()
                 .matcher(All.class)
                 .mailet(ToRepository.class)
-                .addProperty("repositoryPath", ERROR_REPOSITORY));
+                .addProperty("repositoryPath", ERROR_REPOSITORY.asString()));
     }
 
     private ProcessorConfiguration.Builder customProcessor() {
@@ -506,6 +507,6 @@ public class MailetErrorsTest {
             .addMailet(MailetConfiguration.builder()
                 .matcher(All.class)
                 .mailet(ToRepository.class)
-                .addProperty("repositoryPath", CUSTOM_REPOSITORY));
+                .addProperty("repositoryPath", CUSTOM_REPOSITORY.asString()));
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/946c68be/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/NetworkMatcherIntegrationTest.java
----------------------------------------------------------------------
diff --git a/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/NetworkMatcherIntegrationTest.java b/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/NetworkMatcherIntegrationTest.java
index 7fcc013..7132860 100644
--- a/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/NetworkMatcherIntegrationTest.java
+++ b/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/NetworkMatcherIntegrationTest.java
@@ -31,6 +31,7 @@ import org.apache.james.MemoryJamesServerMain;
 import org.apache.james.mailets.configuration.CommonProcessors;
 import org.apache.james.mailets.configuration.MailetConfiguration;
 import org.apache.james.mailets.configuration.ProcessorConfiguration;
+import org.apache.james.mailrepository.api.MailRepositoryUrl;
 import org.apache.james.probe.DataProbe;
 import org.apache.james.transport.mailets.ToProcessor;
 import org.apache.james.transport.mailets.ToRepository;
@@ -48,7 +49,7 @@ import org.junit.rules.TemporaryFolder;
 
 public class NetworkMatcherIntegrationTest {
     private static final String FROM = "fromuser@" + DEFAULT_DOMAIN;
-    private static final String DROPPED_MAILS = "file://var/mail/dropped-mails/";
+    private static final MailRepositoryUrl DROPPED_MAILS = MailRepositoryUrl.from("file://var/mail/dropped-mails/");
 
     @Rule
     public TemporaryFolder temporaryFolder = new TemporaryFolder();
@@ -77,7 +78,7 @@ public class NetworkMatcherIntegrationTest {
         return MailetConfiguration.builder()
             .matcher(All.class)
             .mailet(ToRepository.class)
-            .addProperty("repositoryPath", DROPPED_MAILS);
+            .addProperty("repositoryPath", DROPPED_MAILS.asString());
     }
 
     @After

http://git-wip-us.apache.org/repos/asf/james-project/blob/946c68be/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/SmtpAuthIntegrationTest.java
----------------------------------------------------------------------
diff --git a/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/SmtpAuthIntegrationTest.java b/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/SmtpAuthIntegrationTest.java
index 0796b77..4f5085e 100644
--- a/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/SmtpAuthIntegrationTest.java
+++ b/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/SmtpAuthIntegrationTest.java
@@ -32,6 +32,7 @@ import org.apache.james.mailets.configuration.CommonProcessors;
 import org.apache.james.mailets.configuration.MailetConfiguration;
 import org.apache.james.mailets.configuration.MailetContainer;
 import org.apache.james.mailets.configuration.ProcessorConfiguration;
+import org.apache.james.mailrepository.api.MailRepositoryUrl;
 import org.apache.james.probe.DataProbe;
 import org.apache.james.transport.mailets.ToProcessor;
 import org.apache.james.transport.mailets.ToRepository;
@@ -49,7 +50,7 @@ import org.junit.rules.TemporaryFolder;
 
 public class SmtpAuthIntegrationTest {
     private static final String FROM = "fromuser@" + DEFAULT_DOMAIN;
-    private static final String DROPPED_MAILS = "file://var/mail/dropped-mails/";
+    private static final MailRepositoryUrl DROPPED_MAILS = MailRepositoryUrl.from("file://var/mail/dropped-mails/");
 
     @Rule
     public IMAPMessageReader imapMessageReader = new IMAPMessageReader();
@@ -91,7 +92,7 @@ public class SmtpAuthIntegrationTest {
             .addMailet(MailetConfiguration.builder()
                 .matcher(All.class)
                 .mailet(ToRepository.class)
-                .addProperty("repositoryPath", DROPPED_MAILS));
+                .addProperty("repositoryPath", DROPPED_MAILS.asString()));
     }
 
     @After

http://git-wip-us.apache.org/repos/asf/james-project/blob/946c68be/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/configuration/CommonProcessors.java
----------------------------------------------------------------------
diff --git a/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/configuration/CommonProcessors.java b/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/configuration/CommonProcessors.java
index 73daf8b..d465620 100644
--- a/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/configuration/CommonProcessors.java
+++ b/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/configuration/CommonProcessors.java
@@ -21,6 +21,7 @@
 package org.apache.james.mailets.configuration;
 
 import org.apache.james.jmap.mailet.VacationMailet;
+import org.apache.james.mailrepository.api.MailRepositoryUrl;
 import org.apache.james.transport.mailets.AddDeliveredToHeader;
 import org.apache.james.transport.mailets.Bounce;
 import org.apache.james.transport.mailets.DSNBounce;
@@ -46,7 +47,7 @@ import org.apache.mailet.Mail;
 
 public class CommonProcessors {
 
-    public static final String ERROR_REPOSITORY = "file://var/mail/error/";
+    public static final MailRepositoryUrl ERROR_REPOSITORY = MailRepositoryUrl.from("file://var/mail/error/");
 
     public static ProcessorConfiguration root() {
         return ProcessorConfiguration.root()
@@ -106,7 +107,7 @@ public class CommonProcessors {
                 .addMailet(MailetConfiguration.builder()
                         .matcher(All.class)
                         .mailet(ToRepository.class)
-                        .addProperty("repositoryPath", ERROR_REPOSITORY))
+                        .addProperty("repositoryPath", ERROR_REPOSITORY.asString()))
                 .build();
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/946c68be/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/GroupMappingTest.java
----------------------------------------------------------------------
diff --git a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/GroupMappingTest.java b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/GroupMappingTest.java
index f0f6ba6..45bbcd8 100644
--- a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/GroupMappingTest.java
+++ b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/GroupMappingTest.java
@@ -39,6 +39,7 @@ import org.apache.james.mailets.configuration.CommonProcessors;
 import org.apache.james.mailets.configuration.MailetConfiguration;
 import org.apache.james.mailets.configuration.MailetContainer;
 import org.apache.james.mailets.configuration.ProcessorConfiguration;
+import org.apache.james.mailrepository.api.MailRepositoryUrl;
 import org.apache.james.modules.MailboxProbeImpl;
 import org.apache.james.probe.DataProbe;
 import org.apache.james.transport.matchers.All;
@@ -74,7 +75,7 @@ public class GroupMappingTest {
     private static final String USER_DOMAIN2 = "user@" + DOMAIN2;
     private static final String MESSAGE_CONTENT = "any text";
     public static final String RRT_ERROR = "rrt-error";
-    public static final String RRT_ERROR_REPOSITORY = "file://var/mail/rrt-error/";
+    public static final MailRepositoryUrl RRT_ERROR_REPOSITORY = MailRepositoryUrl.from("file://var/mail/rrt-error/");
 
     private TemporaryJamesServer jamesServer;
     private MimeMessage message;
@@ -111,7 +112,7 @@ public class GroupMappingTest {
                     .matcher(All.class)
                     .mailet(ToRepository.class)
                     .addProperty("passThrough", "true")
-                    .addProperty("repositoryPath", RRT_ERROR_REPOSITORY))
+                    .addProperty("repositoryPath", RRT_ERROR_REPOSITORY.asString()))
                 .addMailet(MailetConfiguration.builder()
                     .matcher(IsSenderInRRTLoop.class)
                     .mailet(Null.class))

http://git-wip-us.apache.org/repos/asf/james-project/blob/946c68be/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/ToRepositoryTest.java
----------------------------------------------------------------------
diff --git a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/ToRepositoryTest.java b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/ToRepositoryTest.java
index 04c4abd..0fecd96 100644
--- a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/ToRepositoryTest.java
+++ b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/ToRepositoryTest.java
@@ -27,13 +27,12 @@ import static org.apache.james.mailets.configuration.Constants.PASSWORD;
 import static org.apache.james.mailets.configuration.Constants.SMTP_PORT;
 import static org.apache.james.mailets.configuration.Constants.awaitAtMostOneMinute;
 
-import java.net.URLEncoder;
-import java.nio.charset.StandardCharsets;
-
 import org.apache.james.mailets.TemporaryJamesServer;
 import org.apache.james.mailets.configuration.MailetConfiguration;
 import org.apache.james.mailets.configuration.MailetContainer;
 import org.apache.james.mailets.configuration.ProcessorConfiguration;
+import org.apache.james.mailrepository.api.MailKey;
+import org.apache.james.mailrepository.api.MailRepositoryUrl;
 import org.apache.james.probe.DataProbe;
 import org.apache.james.transport.matchers.All;
 import org.apache.james.utils.DataProbeImpl;
@@ -54,7 +53,7 @@ import com.jayway.restassured.specification.RequestSpecification;
 
 public class ToRepositoryTest {
     private static final String RECIPIENT = "touser@" + DEFAULT_DOMAIN;
-    public static final String CUSTOM_REPOSITORY = "file://var/mail/custom/";
+    public static final MailRepositoryUrl CUSTOM_REPOSITORY = MailRepositoryUrl.from("file://var/mail/custom/");
 
     @Rule
     public TemporaryFolder temporaryFolder = new TemporaryFolder();
@@ -74,7 +73,7 @@ public class ToRepositoryTest {
                 .addMailet(MailetConfiguration.builder()
                     .matcher(All.class)
                     .mailet(ToRepository.class)
-                    .addProperty("repositoryPath", CUSTOM_REPOSITORY)));
+                    .addProperty("repositoryPath", CUSTOM_REPOSITORY.asString())));
 
         jamesServer = TemporaryJamesServer.builder()
             .withMailetContainer(mailetContainer)
@@ -118,7 +117,7 @@ public class ToRepositoryTest {
             .queryParam("processor", ProcessorConfiguration.STATE_TRANSPORT)
             .queryParam("action", "reprocess")
         .patch(MailRepositoriesRoutes.MAIL_REPOSITORIES
-                + "/" + URLEncoder.encode(CUSTOM_REPOSITORY, StandardCharsets.UTF_8.displayName())
+                + "/" + CUSTOM_REPOSITORY.urlEncoded()
                 + "/mails")
             .jsonPath()
             .getString("taskId");
@@ -142,15 +141,15 @@ public class ToRepositoryTest {
             .sendMessage(RECIPIENT, RECIPIENT);
 
         awaitAtMostOneMinute.until(() -> probe.getRepositoryMailCount(CUSTOM_REPOSITORY) == 2);
-        String key = probe.listMailKeys(CUSTOM_REPOSITORY).get(0);
+        MailKey key = probe.listMailKeys(CUSTOM_REPOSITORY).get(0);
 
         with()
             .spec(webAdminAPI)
             .queryParam("processor", ProcessorConfiguration.STATE_TRANSPORT)
             .queryParam("action", "reprocess")
             .patch(MailRepositoriesRoutes.MAIL_REPOSITORIES
-                + "/" + URLEncoder.encode(CUSTOM_REPOSITORY, StandardCharsets.UTF_8.displayName())
-                + "/mails/" + key)
+                + "/" + CUSTOM_REPOSITORY.urlEncoded()
+                + "/mails/" + key.asString())
             .jsonPath()
             .get("taskId");
 


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