You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by bt...@apache.org on 2019/11/14 02:09:36 UTC

[james-project] 19/32: MAILBOX-391 MailboxMapper::findMailboxWithPathLike should use MailboxQuery.UserBound

This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 86044a30a55c9a4bdefddec6aa95d7020b2d193e
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Mon Nov 11 16:55:44 2019 +0700

    MAILBOX-391  MailboxMapper::findMailboxWithPathLike should use MailboxQuery.UserBound
---
 .../james/mailbox/model/search/MailboxQuery.java   | 26 ++++++++++++++--
 .../cassandra/mail/CassandraMailboxMapper.java     | 13 ++++----
 .../cassandra/mail/CassandraMailboxMapperTest.java | 33 +++++++++++++++-----
 .../james/mailbox/jpa/mail/JPAMailboxMapper.java   | 18 ++++++-----
 .../jpa/mail/TransactionalMailboxMapper.java       |  5 +--
 .../mailbox/maildir/mail/MaildirMailboxMapper.java | 31 ++++++++++++-------
 .../inmemory/mail/InMemoryMailboxMapper.java       | 12 ++------
 .../MailboxExpressionBackwardCompatibility.java    | 35 +++++++++++++++++++++
 .../james/mailbox/store/StoreMailboxManager.java   | 36 +++++++++++-----------
 .../james/mailbox/store/mail/MailboxMapper.java    |  3 +-
 .../store/quota/DefaultUserQuotaRootResolver.java  |  8 ++++-
 .../mailbox/store/StoreMailboxManagerTest.java     | 23 ++++++++++----
 .../store/mail/model/MailboxMapperTest.java        | 30 ++++++++++++++----
 .../quota/DefaultUserQuotaRootResolverTest.java    |  2 +-
 14 files changed, 196 insertions(+), 79 deletions(-)

diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/search/MailboxQuery.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/search/MailboxQuery.java
index 616b108..388280f 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/search/MailboxQuery.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/search/MailboxQuery.java
@@ -34,7 +34,7 @@ import com.google.common.base.Preconditions;
 /**
  * Expresses select criteria for mailboxes.
  */
-public final class MailboxQuery {
+public class MailboxQuery {
 
     public static Builder builder() {
         return new Builder();
@@ -110,8 +110,24 @@ public final class MailboxQuery {
         }
     }
 
-    private final Optional<String> namespace;
-    private final Optional<String> user;
+    public static class UserBound extends MailboxQuery {
+        private UserBound(Optional<String> namespace, Optional<String> user, MailboxNameExpression mailboxNameExpression) {
+            super(namespace, user, mailboxNameExpression);
+            Preconditions.checkArgument(namespace.isPresent());
+            Preconditions.checkArgument(user.isPresent());
+        }
+
+        public String getFixedNamespace() {
+            return namespace.get();
+        }
+
+        public String getFixedUser() {
+            return user.get();
+        }
+    }
+
+    protected final Optional<String> namespace;
+    protected final Optional<String> user;
     private final MailboxNameExpression mailboxNameExpression;
 
     /**
@@ -162,6 +178,10 @@ public final class MailboxQuery {
             && isExpressionMatch(mailboxPath.getName());
     }
 
+    public UserBound asUserBound() {
+        return new UserBound(namespace, user, mailboxNameExpression);
+    }
+
     public String toString() {
         return MoreObjects.toStringHelper(this)
             .add("namespace", namespace)
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
index 919a9c2..06d5246 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
@@ -39,6 +39,7 @@ import org.apache.james.mailbox.model.MailboxACL;
 import org.apache.james.mailbox.model.MailboxACL.Right;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.search.MailboxQuery;
 import org.apache.james.mailbox.store.mail.MailboxMapper;
 import org.apache.james.util.ReactorUtils;
 import org.slf4j.Logger;
@@ -134,9 +135,9 @@ public class CassandraMailboxMapper implements MailboxMapper {
     }
 
     @Override
-    public List<Mailbox> findMailboxWithPathLike(MailboxPath path) {
-        List<Mailbox> mailboxesV2 = toMailboxes(path, mailboxPathV2DAO.listUserMailboxes(path.getNamespace(), path.getUser()));
-        List<Mailbox> mailboxesV1 = toMailboxes(path, mailboxPathDAO.listUserMailboxes(path.getNamespace(), path.getUser()));
+    public List<Mailbox> findMailboxWithPathLike(MailboxQuery.UserBound query) {
+        List<Mailbox> mailboxesV2 = toMailboxes(query, mailboxPathV2DAO.listUserMailboxes(query.getFixedNamespace(), query.getFixedUser()));
+        List<Mailbox> mailboxesV1 = toMailboxes(query, mailboxPathDAO.listUserMailboxes(query.getFixedNamespace(), query.getFixedUser()));
 
         List<Mailbox> mailboxesV1NotInV2 = mailboxesV1.stream()
             .filter(mailboxV1 -> mailboxesV2.stream()
@@ -150,11 +151,9 @@ public class CassandraMailboxMapper implements MailboxMapper {
             .build();
     }
 
-    private List<Mailbox> toMailboxes(MailboxPath path, Flux<CassandraIdAndPath> listUserMailboxes) {
-        Pattern regex = Pattern.compile(constructEscapedRegexForMailboxNameMatching(path));
-
+    private List<Mailbox> toMailboxes(MailboxQuery.UserBound query, Flux<CassandraIdAndPath> listUserMailboxes) {
         return listUserMailboxes
-                .filter(idAndPath -> regex.matcher(idAndPath.getMailboxPath().getName()).matches())
+                .filter(idAndPath -> query.isPathMatch(idAndPath.getMailboxPath()))
                 .flatMap(this::retrieveMailbox)
                 .collectList()
                 .block();
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java
index ff0f610..e408fb7 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java
@@ -37,8 +37,9 @@ import org.apache.james.mailbox.cassandra.modules.CassandraMailboxModule;
 import org.apache.james.mailbox.exception.MailboxNotFoundException;
 import org.apache.james.mailbox.exception.TooLongMailboxNameException;
 import org.apache.james.mailbox.model.Mailbox;
-import org.apache.james.mailbox.model.MailboxConstants;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.search.MailboxQuery;
+import org.apache.james.mailbox.model.search.Wildcard;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Ignore;
@@ -55,9 +56,7 @@ public class CassandraMailboxMapperTest {
 
     private static final CassandraId MAILBOX_ID_2 = CassandraId.timeBased();
 
-
     private static final Mailbox MAILBOX_BIS = new Mailbox(MAILBOX_PATH, UID_VALIDITY, MAILBOX_ID_2);
-    private static final String WILDCARD = "%";
 
     private static final CassandraModule MODULES = CassandraModule.aggregateModules(
         CassandraMailboxModule.MODULE,
@@ -236,7 +235,12 @@ public class CassandraMailboxMapperTest {
         mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
             .block();
     
-        List<Mailbox> mailboxes = testee.findMailboxWithPathLike(new MailboxPath(MailboxConstants.USER_NAMESPACE, USER, WILDCARD));
+        List<Mailbox> mailboxes = testee.findMailboxWithPathLike(MailboxQuery.builder()
+            .privateNamespace()
+            .username(USER)
+            .expression(Wildcard.INSTANCE)
+            .build()
+            .asUserBound());
 
         assertThat(mailboxes).containsOnly(MAILBOX);
     }
@@ -250,7 +254,12 @@ public class CassandraMailboxMapperTest {
         mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
             .block();
 
-        List<Mailbox> mailboxes = testee.findMailboxWithPathLike(new MailboxPath(MailboxConstants.USER_NAMESPACE, USER, WILDCARD));
+        List<Mailbox> mailboxes = testee.findMailboxWithPathLike(MailboxQuery.builder()
+            .privateNamespace()
+            .username(USER)
+            .expression(Wildcard.INSTANCE)
+            .build()
+            .asUserBound());
 
         assertThat(mailboxes).containsOnly(MAILBOX);
     }
@@ -262,7 +271,12 @@ public class CassandraMailboxMapperTest {
         mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
             .block();
     
-        List<Mailbox> mailboxes = testee.findMailboxWithPathLike(new MailboxPath(MailboxConstants.USER_NAMESPACE, USER, WILDCARD));
+        List<Mailbox> mailboxes = testee.findMailboxWithPathLike(MailboxQuery.builder()
+            .privateNamespace()
+            .username(USER)
+            .expression(Wildcard.INSTANCE)
+            .build()
+            .asUserBound());
 
         assertThat(mailboxes).containsOnly(MAILBOX);
     }
@@ -335,7 +349,12 @@ public class CassandraMailboxMapperTest {
         mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID_2).block();
 
         assertThat(testee.findMailboxWithPathLike(
-            new MailboxPath(MailboxConstants.USER_NAMESPACE, USER, WILDCARD)))
+            MailboxQuery.builder()
+                .privateNamespace()
+                .username(USER)
+                .expression(Wildcard.INSTANCE)
+                .build()
+                .asUserBound()))
             .containsOnly(MAILBOX);
     }
 }
diff --git a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAMailboxMapper.java b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAMailboxMapper.java
index ca633e7..8b69d39 100644
--- a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAMailboxMapper.java
+++ b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAMailboxMapper.java
@@ -40,6 +40,8 @@ import org.apache.james.mailbox.model.MailboxACL;
 import org.apache.james.mailbox.model.MailboxACL.Right;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.search.MailboxQuery;
+import org.apache.james.mailbox.store.MailboxExpressionBackwardCompatibility;
 import org.apache.james.mailbox.store.mail.MailboxMapper;
 
 import com.github.steveash.guavate.Guavate;
@@ -189,23 +191,25 @@ public class JPAMailboxMapper extends JPATransactionalMapper implements MailboxM
     }
 
     @Override
-    public List<Mailbox> findMailboxWithPathLike(MailboxPath path) throws MailboxException {
+    public List<Mailbox> findMailboxWithPathLike(MailboxQuery.UserBound query) throws MailboxException {
         try {
-            return findMailboxWithPathLikeTypedQuery(path)
+            String pathLike = MailboxExpressionBackwardCompatibility.getPathLike(query);
+            return findMailboxWithPathLikeTypedQuery(query.getFixedNamespace(), query.getFixedUser(), pathLike)
                 .getResultList()
                 .stream()
                 .map(JPAMailbox::toMailbox)
+                .filter(mailbox -> query.isPathMatch(mailbox.generateAssociatedPath()))
                 .collect(Guavate.toImmutableList());
         } catch (PersistenceException e) {
-            throw new MailboxException("Search of mailbox " + path + " failed", e);
+            throw new MailboxException("Search of mailbox " + query + " failed", e);
         }
     }
 
-    private TypedQuery<JPAMailbox> findMailboxWithPathLikeTypedQuery(MailboxPath path) {
+    private TypedQuery<JPAMailbox> findMailboxWithPathLikeTypedQuery(String namespace, String user, String pathLike) {
         return getEntityManager().createNamedQuery("findMailboxWithNameLikeWithUser", JPAMailbox.class)
-            .setParameter("nameParam", path.getName())
-            .setParameter("namespaceParam", path.getNamespace())
-            .setParameter("userParam", path.getUser().asId());
+            .setParameter("nameParam", pathLike)
+            .setParameter("namespaceParam", namespace)
+            .setParameter("userParam", user);
     }
 
     public void deleteAllMemberships() throws MailboxException {
diff --git a/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/TransactionalMailboxMapper.java b/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/TransactionalMailboxMapper.java
index 98537b1..45c8706 100644
--- a/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/TransactionalMailboxMapper.java
+++ b/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/TransactionalMailboxMapper.java
@@ -30,6 +30,7 @@ import org.apache.james.mailbox.model.MailboxACL;
 import org.apache.james.mailbox.model.MailboxACL.Right;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.search.MailboxQuery;
 import org.apache.james.mailbox.store.mail.MailboxMapper;
 import org.apache.james.mailbox.store.transaction.Mapper;
 
@@ -71,8 +72,8 @@ public class TransactionalMailboxMapper implements MailboxMapper {
     }
 
     @Override
-    public List<Mailbox> findMailboxWithPathLike(MailboxPath mailboxPath) throws MailboxException {
-        return wrapped.findMailboxWithPathLike(mailboxPath);
+    public List<Mailbox> findMailboxWithPathLike(MailboxQuery.UserBound query) throws MailboxException {
+        return wrapped.findMailboxWithPathLike(query);
     }
 
     @Override
diff --git a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMailboxMapper.java b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMailboxMapper.java
index b7e6db5..843fe95 100644
--- a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMailboxMapper.java
+++ b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMailboxMapper.java
@@ -42,11 +42,15 @@ import org.apache.james.mailbox.model.MailboxACL.Right;
 import org.apache.james.mailbox.model.MailboxConstants;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.search.MailboxQuery;
+import org.apache.james.mailbox.model.search.PrefixedWildcard;
+import org.apache.james.mailbox.store.MailboxExpressionBackwardCompatibility;
 import org.apache.james.mailbox.store.mail.MailboxMapper;
 import org.apache.james.mailbox.store.transaction.NonTransactionalMapper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.github.steveash.guavate.Guavate;
 import com.google.common.collect.ImmutableList;
 
 public class MaildirMailboxMapper extends NonTransactionalMapper implements MailboxMapper {
@@ -119,34 +123,39 @@ public class MaildirMailboxMapper extends NonTransactionalMapper implements Mail
     }
     
     @Override
-    public List<Mailbox> findMailboxWithPathLike(MailboxPath mailboxPath)
-            throws MailboxException {
+    public List<Mailbox> findMailboxWithPathLike(MailboxQuery.UserBound query) throws MailboxException {
+        String pathLike = MailboxExpressionBackwardCompatibility.getPathLike(query);
         final Pattern searchPattern = Pattern.compile("[" + MaildirStore.maildirDelimiter + "]"
-                + mailboxPath.getName().replace(".", "\\.").replace(MaildirStore.WILDCARD, ".*"));
+                + pathLike.replace(".", "\\.").replace(MaildirStore.WILDCARD, ".*"));
         FilenameFilter filter = MaildirMessageName.createRegexFilter(searchPattern);
-        File root = maildirStore.getMailboxRootForUser(mailboxPath.getUser());
+        File root = maildirStore.getMailboxRootForUser(query.getFixedUser());
         File[] folders = root.listFiles(filter);
         ArrayList<Mailbox> mailboxList = new ArrayList<>();
         for (File folder : folders) {
             if (folder.isDirectory()) {
-                Mailbox mailbox = maildirStore.loadMailbox(session, root, mailboxPath.getNamespace(), mailboxPath.getUser(), folder.getName());
+                Mailbox mailbox = maildirStore.loadMailbox(session, root, query.getFixedNamespace(), query.getFixedUser(), folder.getName());
                 mailboxList.add(mailbox);
             }
         }
         // INBOX is in the root of the folder
-        if (Pattern.matches(mailboxPath.getName().replace(MaildirStore.WILDCARD, ".*"), MailboxConstants.INBOX)) {
-            Mailbox mailbox = maildirStore.loadMailbox(session, root, mailboxPath.getNamespace(), mailboxPath.getUser(), "");
+        if (Pattern.matches(pathLike.replace(MaildirStore.WILDCARD, ".*"), MailboxConstants.INBOX)) {
+            Mailbox mailbox = maildirStore.loadMailbox(session, root, query.getFixedNamespace(), query.getFixedUser(), "");
             mailboxList.add(0, mailbox);
         }
-        return mailboxList;
+        return mailboxList.stream()
+            .filter(mailbox -> query.isPathMatch(mailbox.generateAssociatedPath()))
+            .collect(Guavate.toImmutableList());
     }
 
     @Override
     public boolean hasChildren(Mailbox mailbox, char delimiter) throws MailboxException, MailboxNotFoundException {
-        String searchString = mailbox.getName() + MaildirStore.maildirDelimiter + MaildirStore.WILDCARD;
         List<Mailbox> mailboxes = findMailboxWithPathLike(
-                new MailboxPath(mailbox.getNamespace(), mailbox.getUser(), searchString));
-        return (mailboxes.size() > 0);
+            MailboxQuery.builder()
+            .userAndNamespaceFrom(mailbox.generateAssociatedPath())
+            .expression(new PrefixedWildcard(mailbox.getName() + delimiter))
+            .build()
+            .asUserBound());
+        return mailboxes.size() > 0;
     }
 
     @Override
diff --git a/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryMailboxMapper.java b/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryMailboxMapper.java
index 9014dfc..d1d28a0 100644
--- a/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryMailboxMapper.java
+++ b/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryMailboxMapper.java
@@ -35,6 +35,7 @@ import org.apache.james.mailbox.model.MailboxACL.NameType;
 import org.apache.james.mailbox.model.MailboxACL.Right;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.search.MailboxQuery;
 import org.apache.james.mailbox.store.mail.MailboxMapper;
 
 import com.github.steveash.guavate.Guavate;
@@ -81,21 +82,14 @@ public class InMemoryMailboxMapper implements MailboxMapper {
     }
 
     @Override
-    public List<Mailbox> findMailboxWithPathLike(MailboxPath path) throws MailboxException {
-        final String regex = path.getName().replace("%", ".*");
+    public List<Mailbox> findMailboxWithPathLike(MailboxQuery.UserBound query) throws MailboxException {
         return mailboxesByPath.values()
             .stream()
-            .filter(mailbox -> mailboxMatchesRegex(mailbox, path, regex))
+            .filter(mailbox -> query.isPathMatch(mailbox.generateAssociatedPath()))
             .map(Mailbox::new)
             .collect(Guavate.toImmutableList());
     }
 
-    private boolean mailboxMatchesRegex(Mailbox mailbox, MailboxPath path, String regex) {
-        return Objects.equal(mailbox.getNamespace(), path.getNamespace())
-            && Objects.equal(mailbox.getUser(), path.getUser())
-            && mailbox.getName().matches(regex);
-    }
-
     @Override
     public MailboxId save(Mailbox mailbox) throws MailboxException {
         InMemoryId id = (InMemoryId) mailbox.getMailboxId();
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/MailboxExpressionBackwardCompatibility.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/MailboxExpressionBackwardCompatibility.java
new file mode 100644
index 0000000..e8e59a7
--- /dev/null
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/MailboxExpressionBackwardCompatibility.java
@@ -0,0 +1,35 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.store;
+
+import static org.apache.james.mailbox.store.StoreMailboxManager.SQL_WILDCARD_CHAR;
+
+import org.apache.james.mailbox.model.search.MailboxNameExpression;
+import org.apache.james.mailbox.model.search.MailboxQuery;
+
+public class MailboxExpressionBackwardCompatibility {
+    public static String getPathLike(MailboxQuery mailboxQuery) {
+        MailboxNameExpression nameExpression = mailboxQuery.getMailboxNameExpression();
+        return nameExpression.getCombinedName()
+            .replace(nameExpression.getFreeWildcard(), SQL_WILDCARD_CHAR)
+            .replace(nameExpression.getLocalWildcard(), SQL_WILDCARD_CHAR)
+            + SQL_WILDCARD_CHAR;
+    }
+}
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java
index b86fc79..d85608f 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java
@@ -68,8 +68,8 @@ import org.apache.james.mailbox.model.MessageMetaData;
 import org.apache.james.mailbox.model.MessageRange;
 import org.apache.james.mailbox.model.MultimailboxesSearchQuery;
 import org.apache.james.mailbox.model.QuotaRoot;
-import org.apache.james.mailbox.model.search.MailboxNameExpression;
 import org.apache.james.mailbox.model.search.MailboxQuery;
+import org.apache.james.mailbox.model.search.PrefixedWildcard;
 import org.apache.james.mailbox.quota.QuotaManager;
 import org.apache.james.mailbox.quota.QuotaRootResolver;
 import org.apache.james.mailbox.store.event.EventFactory;
@@ -85,7 +85,6 @@ import org.slf4j.LoggerFactory;
 
 import com.github.fge.lambdas.Throwing;
 import com.github.steveash.guavate.Guavate;
-import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
@@ -510,13 +509,17 @@ public class StoreMailboxManager implements MailboxManager {
             .block();
 
         // rename submailboxes
-        MailboxPath children = new MailboxPath(from.getNamespace(), from.getUser(), from.getName() + getDelimiter() + "%");
-        locker.executeWithLock(session, children, (LockAwareExecution<Void>) () -> {
-            List<Mailbox> subMailboxes = mapper.findMailboxWithPathLike(children);
+        MailboxQuery.UserBound query = MailboxQuery.builder()
+            .userAndNamespaceFrom(from)
+            .expression(new PrefixedWildcard(from.getName() + getDelimiter()))
+            .build()
+            .asUserBound();
+        locker.executeWithLock(session, from, (LockAwareExecution<Void>) () -> {
+            List<Mailbox> subMailboxes = mapper.findMailboxWithPathLike(query);
             for (Mailbox sub : subMailboxes) {
                 String subOriginalName = sub.getName();
                 String subNewName = to.getName() + subOriginalName.substring(from.getName().length());
-                MailboxPath fromPath = new MailboxPath(children, subOriginalName);
+                MailboxPath fromPath = new MailboxPath(from, subOriginalName);
                 sub.setName(subNewName);
                 mapper.save(sub);
                 eventBus.dispatch(EventFactory.mailboxRenamed()
@@ -574,7 +577,7 @@ public class StoreMailboxManager implements MailboxManager {
     private List<MailboxMetaData> searchMailboxes(MailboxQuery mailboxExpression, MailboxSession session, Right right) throws MailboxException {
         MailboxMapper mailboxMapper = mailboxSessionMapperFactory.getMailboxMapper(session);
         Stream<Mailbox> baseMailboxes = mailboxMapper
-            .findMailboxWithPathLike(getPathLike(mailboxExpression, session))
+            .findMailboxWithPathLike(toSingleUserQuery(mailboxExpression, session))
             .stream();
         Stream<Mailbox> delegatedMailboxes = getDelegatedMailboxes(mailboxMapper, mailboxExpression, right, session);
         List<Mailbox> mailboxes = Stream.concat(baseMailboxes,
@@ -591,18 +594,15 @@ public class StoreMailboxManager implements MailboxManager {
             .collect(Guavate.toImmutableList());
     }
 
-    @VisibleForTesting
-    public static MailboxPath getPathLike(MailboxQuery mailboxQuery, MailboxSession mailboxSession) {
+    public static MailboxQuery.UserBound toSingleUserQuery(MailboxQuery mailboxQuery, MailboxSession mailboxSession) {
         MailboxNameExpression nameExpression = mailboxQuery.getMailboxNameExpression();
-        String combinedName = nameExpression.getCombinedName()
-            .replace(nameExpression.getFreeWildcard(), SQL_WILDCARD_CHAR)
-            .replace(nameExpression.getLocalWildcard(), SQL_WILDCARD_CHAR)
-            + SQL_WILDCARD_CHAR;
-        MailboxPath base = new MailboxPath(
-            mailboxQuery.getNamespace().orElse(MailboxConstants.USER_NAMESPACE),
-            mailboxQuery.getUser().orElse(mailboxSession.getUser().asString()),
-            combinedName);
-        return new MailboxPath(base, combinedName);
+
+        return MailboxQuery.builder()
+            .namespace(mailboxQuery.getNamespace().orElse(MailboxConstants.USER_NAMESPACE))
+            .username(mailboxQuery.getUser().orElse(mailboxSession.getUser().asString()))
+            .expression(nameExpression)
+            .build()
+            .asUserBound();
     }
 
     private Stream<Mailbox> getDelegatedMailboxes(MailboxMapper mailboxMapper, MailboxQuery mailboxQuery,
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/MailboxMapper.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/MailboxMapper.java
index d91e6ad..6b73444 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/MailboxMapper.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/MailboxMapper.java
@@ -28,6 +28,7 @@ import org.apache.james.mailbox.model.MailboxACL;
 import org.apache.james.mailbox.model.MailboxACL.Right;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.search.MailboxQuery;
 import org.apache.james.mailbox.store.transaction.Mapper;
 
 /**
@@ -68,7 +69,7 @@ public interface MailboxMapper extends Mapper {
     /**
      * Return a List of {@link Mailbox} which name is like the given name
      */
-    List<Mailbox> findMailboxWithPathLike(MailboxPath mailboxPath)
+    List<Mailbox> findMailboxWithPathLike(MailboxQuery.UserBound query)
             throws MailboxException;
 
     /**
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/DefaultUserQuotaRootResolver.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/DefaultUserQuotaRootResolver.java
index d7f54d9..7bcd0e9 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/DefaultUserQuotaRootResolver.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/DefaultUserQuotaRootResolver.java
@@ -32,6 +32,7 @@ import org.apache.james.mailbox.model.MailboxConstants;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.QuotaRoot;
+import org.apache.james.mailbox.model.search.MailboxQuery;
 import org.apache.james.mailbox.quota.QuotaRootDeserializer;
 import org.apache.james.mailbox.quota.UserQuotaRootResolver;
 import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
@@ -113,6 +114,11 @@ public class DefaultUserQuotaRootResolver implements UserQuotaRootResolver {
         String namespace = parts.get(0);
         String user = parts.get(1);
         return factory.getMailboxMapper(mailboxSession)
-            .findMailboxWithPathLike(new MailboxPath(namespace, user, "%"));
+            .findMailboxWithPathLike(MailboxQuery.builder()
+                .namespace(namespace)
+                .user(Username.of(user))
+                .matchesAllMailboxNames()
+                .build()
+                .asUserBound());
     }
 }
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMailboxManagerTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMailboxManagerTest.java
index c00c201..db99510 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMailboxManagerTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMailboxManagerTest.java
@@ -38,6 +38,7 @@ import org.apache.james.mailbox.exception.NotAdminException;
 import org.apache.james.mailbox.exception.UserDoesNotExistException;
 import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxACL;
+import org.apache.james.mailbox.model.MailboxConstants;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MessageId;
@@ -195,7 +196,7 @@ public class StoreMailboxManagerTest {
     }
 
     @Test
-    public void getPathLikeShouldReturnUserPathLikeWhenNoPrefixDefined() throws Exception {
+    public void getPathLikeShouldReturnUserPathLikeWhenNoPrefixDefined() {
         //Given
         MailboxSession session = MailboxSessionUtil.create("user");
         MailboxQuery.Builder testee = MailboxQuery.builder()
@@ -203,12 +204,17 @@ public class StoreMailboxManagerTest {
         //When
         MailboxQuery mailboxQuery = testee.build();
 
-        assertThat(StoreMailboxManager.getPathLike(mailboxQuery, session))
-            .isEqualTo(MailboxPath.forUser("user", "abc%"));
+        assertThat(StoreMailboxManager.toSingleUserQuery(mailboxQuery, session))
+            .isEqualTo(MailboxQuery.builder()
+                .namespace(MailboxConstants.USER_NAMESPACE)
+                .username("user")
+                .expression(new PrefixedRegex(EMPTY_PREFIX, "abc", session.getPathDelimiter()))
+                .build()
+                .asUserBound());
     }
 
     @Test
-    public void getPathLikeShouldReturnUserPathLikeWhenPrefixDefined() throws Exception {
+    public void getPathLikeShouldReturnUserPathLikeWhenPrefixDefined() {
         //Given
         MailboxSession session = MailboxSessionUtil.create("user");
         MailboxQuery.Builder testee = MailboxQuery.builder()
@@ -217,8 +223,13 @@ public class StoreMailboxManagerTest {
         //When
         MailboxQuery mailboxQuery = testee.build();
 
-        assertThat(StoreMailboxManager.getPathLike(mailboxQuery, session))
-            .isEqualTo(MailboxPath.forUser("user", "prefix.abc%"));
+        assertThat(StoreMailboxManager.toSingleUserQuery(mailboxQuery, session))
+            .isEqualTo(MailboxQuery.builder()
+                .namespace(MailboxConstants.USER_NAMESPACE)
+                .username("user")
+                .expression(new PrefixedRegex("prefix.", "abc", session.getPathDelimiter()))
+                .build()
+                .asUserBound());
     }
 }
 
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MailboxMapperTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MailboxMapperTest.java
index 06a1909..739d1bd 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MailboxMapperTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MailboxMapperTest.java
@@ -32,6 +32,9 @@ import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxAssert;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.search.ExactName;
+import org.apache.james.mailbox.model.search.MailboxQuery;
+import org.apache.james.mailbox.model.search.PrefixedWildcard;
 import org.apache.james.mailbox.store.mail.MailboxMapper;
 import org.junit.Test;
 
@@ -129,8 +132,13 @@ public abstract class MailboxMapperTest {
     @Test
     public void findMailboxWithPathLikeShouldBeLimitedToUserAndNamespace() throws MailboxException {
         saveAll();
-        MailboxPath mailboxPathQuery = new MailboxPath(bobInboxMailbox.getNamespace(), bobInboxMailbox.getUser(), "IN" + WILDCARD);
-        List<Mailbox> mailboxes = mailboxMapper.findMailboxWithPathLike(mailboxPathQuery);
+        MailboxQuery.UserBound mailboxQuery = MailboxQuery.builder()
+            .userAndNamespaceFrom(bobInboxPath)
+            .expression(new PrefixedWildcard("IN"))
+            .build()
+            .asUserBound();
+
+        List<Mailbox> mailboxes = mailboxMapper.findMailboxWithPathLike(mailboxQuery);
 
         assertMailboxes(mailboxes).containOnly(bobInboxMailbox);
     }
@@ -147,8 +155,13 @@ public abstract class MailboxMapperTest {
     @Test
     public void findMailboxWithPathLikeWithChildRegexShouldRetrieveChildren() throws MailboxException {
         saveAll();
-        MailboxPath regexPath = new MailboxPath(benwaWorkPath.getNamespace(), benwaWorkPath.getUser(), benwaWorkPath.getName() + WILDCARD);
-        List<Mailbox> mailboxes = mailboxMapper.findMailboxWithPathLike(regexPath);
+        MailboxQuery.UserBound mailboxQuery = MailboxQuery.builder()
+            .userAndNamespaceFrom(benwaWorkPath)
+            .expression(new PrefixedWildcard(benwaWorkPath.getName()))
+            .build()
+            .asUserBound();
+
+        List<Mailbox> mailboxes = mailboxMapper.findMailboxWithPathLike(mailboxQuery);
 
         assertMailboxes(mailboxes).containOnly(benwaWorkMailbox, benwaWorkDoneMailbox, benwaWorkTodoMailbox);
     }
@@ -170,8 +183,13 @@ public abstract class MailboxMapperTest {
     @Test
     public void findMailboxWithPathLikeShouldEscapeMailboxName() throws MailboxException {
         saveAll();
-        MailboxPath regexPath = new MailboxPath(benwaInboxPath.getNamespace(), benwaInboxPath.getUser(), "INB?X");
-        assertThat(mailboxMapper.findMailboxWithPathLike(regexPath)).isEmpty();
+        MailboxQuery.UserBound mailboxQuery = MailboxQuery.builder()
+            .userAndNamespaceFrom(benwaInboxPath)
+            .expression(new ExactName("INB?X"))
+            .build()
+            .asUserBound();
+
+        assertThat(mailboxMapper.findMailboxWithPathLike(mailboxQuery)).isEmpty();
     }
 
     @Test
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/DefaultUserQuotaRootResolverTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/DefaultUserQuotaRootResolverTest.java
index e8cb58d..97bb334 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/DefaultUserQuotaRootResolverTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/DefaultUserQuotaRootResolverTest.java
@@ -87,7 +87,7 @@ public class DefaultUserQuotaRootResolverTest {
     public void retrieveAssociatedMailboxesShouldWork() throws Exception {
         MailboxMapper mockedMapper = mock(MailboxMapper.class);
         when(mockedFactory.getMailboxMapper(MAILBOX_SESSION)).thenReturn(mockedMapper);
-        when(mockedMapper.findMailboxWithPathLike(PATH_LIKE)).thenReturn(Lists.newArrayList(MAILBOX, MAILBOX_2));
+        when(mockedMapper.findMailboxWithPathLike(any())).thenReturn(Lists.newArrayList(MAILBOX, MAILBOX_2));
 
         assertThat(testee.retrieveAssociatedMailboxes(QUOTA_ROOT, MAILBOX_SESSION)).containsOnly(MAILBOX, MAILBOX_2);
     }


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