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 ro...@apache.org on 2019/05/02 12:42:59 UTC
[james-project] 01/06: JMAP getMailboxes preload quotas for user
namespace/name in order to avoid doing it for each mailbox
This is an automated email from the ASF dual-hosted git repository.
rouazana pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 7bf9d99ac8524bac5fe0b587732f4ab08394d396
Author: RĂ©mi Kowalski <rk...@linagora.com>
AuthorDate: Tue Apr 23 17:19:35 2019 +0200
JMAP getMailboxes preload quotas for user namespace/name in order to avoid doing it for each mailbox
---
.../james/jmap/methods/GetMailboxesMethod.java | 38 ++++++++++++++------
.../apache/james/jmap/model/MailboxFactory.java | 42 +++++++++++++++++-----
.../apache/james/jmap/model/mailbox/Quotas.java | 15 ++++++++
.../james/jmap/model/mailbox/QuotaIdTest.java | 32 +++++++++++++++++
4 files changed, 108 insertions(+), 19 deletions(-)
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/GetMailboxesMethod.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/GetMailboxesMethod.java
index 9b33064..ab22edc 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/GetMailboxesMethod.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/GetMailboxesMethod.java
@@ -33,6 +33,7 @@ import org.apache.james.jmap.model.GetMailboxesResponse;
import org.apache.james.jmap.model.MailboxFactory;
import org.apache.james.jmap.model.MailboxProperty;
import org.apache.james.jmap.model.mailbox.Mailbox;
+import org.apache.james.jmap.model.mailbox.Quotas;
import org.apache.james.mailbox.MailboxManager;
import org.apache.james.mailbox.MailboxSession;
import org.apache.james.mailbox.exception.MailboxException;
@@ -44,6 +45,7 @@ import org.apache.james.util.MDCBuilder;
import org.apache.james.util.OptionalUtils;
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.ImmutableList;
@@ -54,6 +56,8 @@ public class GetMailboxesMethod implements Method {
private static final Method.Request.Name METHOD_NAME = Method.Request.name("getMailboxes");
private static final Method.Response.Name RESPONSE_NAME = Method.Response.name("mailboxes");
+ private static final Optional<List<MailboxMetaData>> NO_PRELOADED_METADATA = Optional.empty();
+ private static final Optional<Quotas> NO_PRELOADED_QUOTAS = Optional.empty();
private final MailboxManager mailboxManager;
private final MailboxFactory mailboxFactory;
@@ -106,10 +110,10 @@ public class GetMailboxesMethod implements Method {
GetMailboxesResponse.Builder builder = GetMailboxesResponse.builder();
try {
Optional<ImmutableList<MailboxId>> mailboxIds = mailboxesRequest.getIds();
- retrieveMailboxes(mailboxIds, mailboxSession)
+ List<Mailbox> mailboxes = retrieveMailboxes(mailboxIds, mailboxSession)
.sorted(Comparator.comparing(Mailbox::getSortOrder))
- .forEach(builder::add);
- return builder.build();
+ .collect(Guavate.toImmutableList());
+ return builder.addAll(mailboxes).build();
} catch (MailboxException e) {
throw new RuntimeException(e);
}
@@ -121,31 +125,43 @@ public class GetMailboxesMethod implements Method {
.orElseGet(Throwing.supplier(() -> retrieveAllMailboxes(mailboxSession)).sneakyThrow());
}
+
+
private Stream<Mailbox> retrieveSpecificMailboxes(MailboxSession mailboxSession, ImmutableList<MailboxId> mailboxIds) {
return mailboxIds
.stream()
- .map(mailboxId -> mailboxFactory.builder()
+ .map(mailboxId -> mailboxFactory.builder()
.id(mailboxId)
.session(mailboxSession)
- .build())
+ .usingPreloadedMailboxesMetadata(NO_PRELOADED_METADATA)
+ .usingPreloadedUserDefaultQuotas(NO_PRELOADED_QUOTAS)
+ .build()
+ )
.flatMap(OptionalUtils::toStream);
}
private Stream<Mailbox> retrieveAllMailboxes(MailboxSession mailboxSession) throws MailboxException {
- List<MailboxMetaData> userMailboxes = mailboxManager.search(
- MailboxQuery.builder()
- .matchesAllMailboxNames()
- .build(),
- mailboxSession);
+ List<MailboxMetaData> userMailboxes = getAllMailboxesMetaData(mailboxSession);
+ Quotas mailboxQuotas = mailboxFactory.getUserDefaultQuotas(mailboxSession);
+
return userMailboxes
.stream()
.map(MailboxMetaData::getId)
.map(mailboxId -> mailboxFactory.builder()
.id(mailboxId)
.session(mailboxSession)
- .usingPreloadedMailboxesMetadata(userMailboxes)
+ .usingPreloadedMailboxesMetadata(Optional.of(userMailboxes))
+ .usingPreloadedUserDefaultQuotas(Optional.of(mailboxQuotas))
.build())
.flatMap(OptionalUtils::toStream);
}
+ private List<MailboxMetaData> getAllMailboxesMetaData(MailboxSession mailboxSession) throws MailboxException {
+ return mailboxManager.search(
+ MailboxQuery.builder()
+ .matchesAllMailboxNames()
+ .build(),
+ mailboxSession);
+ }
+
}
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MailboxFactory.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MailboxFactory.java
index 0080339..d2506fb 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MailboxFactory.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MailboxFactory.java
@@ -59,7 +59,8 @@ public class MailboxFactory {
private final MailboxFactory mailboxFactory;
private MailboxSession session;
private MailboxId id;
- private List<MailboxMetaData> userMailboxesMetadata;
+ private Optional<List<MailboxMetaData>> userMailboxesMetadata = Optional.empty();
+ private Optional<Quotas> preloadedUserDefaultQuotas = Optional.empty();
private MailboxBuilder(MailboxFactory mailboxFactory) {
this.mailboxFactory = mailboxFactory;
@@ -75,18 +76,23 @@ public class MailboxFactory {
return this;
}
- public MailboxBuilder usingPreloadedMailboxesMetadata(List<MailboxMetaData> userMailboxesMetadata) {
+ public MailboxBuilder usingPreloadedMailboxesMetadata(Optional<List<MailboxMetaData>> userMailboxesMetadata) {
this.userMailboxesMetadata = userMailboxesMetadata;
return this;
}
+ public MailboxBuilder usingPreloadedUserDefaultQuotas(Optional<Quotas> preloadedUserDefaultQuotas) {
+ this.preloadedUserDefaultQuotas = preloadedUserDefaultQuotas;
+ return this;
+ }
+
public Optional<Mailbox> build() {
Preconditions.checkNotNull(id);
Preconditions.checkNotNull(session);
try {
MessageManager mailbox = mailboxFactory.mailboxManager.getMailbox(id, session);
- return Optional.of(mailboxFactory.fromMessageManager(mailbox, Optional.ofNullable(userMailboxesMetadata), session));
+ return Optional.of(mailboxFactory.fromMessageManager(mailbox, userMailboxesMetadata, preloadedUserDefaultQuotas, session));
} catch (MailboxNotFoundException e) {
return Optional.empty();
} catch (MailboxException e) {
@@ -106,8 +112,10 @@ public class MailboxFactory {
return new MailboxBuilder(this);
}
- private Mailbox fromMessageManager(MessageManager messageManager, Optional<List<MailboxMetaData>> userMailboxesMetadata,
- MailboxSession mailboxSession) throws MailboxException {
+ private Mailbox fromMessageManager(MessageManager messageManager,
+ Optional<List<MailboxMetaData>> userMailboxesMetadata,
+ Optional<Quotas> preloadedDefaultUserQuotas,
+ MailboxSession mailboxSession) throws MailboxException {
MailboxPath mailboxPath = messageManager.getMailboxPath();
boolean isOwner = mailboxPath.belongsTo(mailboxSession);
Optional<Role> role = Role.from(mailboxPath.getName());
@@ -116,7 +124,8 @@ public class MailboxFactory {
Rights rights = Rights.fromACL(messageManager.getResolvedAcl(mailboxSession))
.removeEntriesFor(Username.forMailboxPath(mailboxPath));
Username username = Username.fromSession(mailboxSession);
- Quotas quotas = getQuotas(mailboxPath);
+
+ Quotas quotas = getQuotas(mailboxPath, preloadedDefaultUserQuotas);
return Mailbox.builder()
.id(messageManager.getId())
@@ -138,15 +147,32 @@ public class MailboxFactory {
.build();
}
- private Quotas getQuotas(MailboxPath mailboxPath) throws MailboxException {
+ private Quotas getQuotas(MailboxPath mailboxPath, Optional<Quotas> preloadedUserDefaultQuotas) throws MailboxException {
QuotaRoot quotaRoot = quotaRootResolver.getQuotaRoot(mailboxPath);
+ QuotaId quotaId = QuotaId.fromQuotaRoot(quotaRoot);
+
+ if (containsQuotaId(preloadedUserDefaultQuotas, quotaId)) {
+ return preloadedUserDefaultQuotas.get();
+ }
return Quotas.from(
- QuotaId.fromQuotaRoot(quotaRoot),
+ quotaId,
Quotas.Quota.from(
quotaToValue(quotaManager.getStorageQuota(quotaRoot)),
quotaToValue(quotaManager.getMessageQuota(quotaRoot))));
}
+ private boolean containsQuotaId(Optional<Quotas> preloadedUserDefaultQuotas, QuotaId quotaId) {
+ return preloadedUserDefaultQuotas
+ .map(Quotas::getQuotas)
+ .map(quotaIdQuotaMap -> quotaIdQuotaMap.containsKey(quotaId))
+ .orElse(false);
+ }
+
+ public Quotas getUserDefaultQuotas(MailboxSession mailboxSession) throws MailboxException {
+ MailboxPath inboxPath = MailboxPath.inbox(mailboxSession);
+ return getQuotas(inboxPath, Optional.empty());
+ }
+
private <T extends QuotaValue<T>> Quotas.Value<T> quotaToValue(Quota<T> quota) {
return new Quotas.Value<>(
quotaValueToNumber(quota.getUsed()),
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/mailbox/Quotas.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/mailbox/Quotas.java
index 30ae9a2..a090cb5 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/mailbox/Quotas.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/mailbox/Quotas.java
@@ -19,6 +19,7 @@
package org.apache.james.jmap.model.mailbox;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
import org.apache.james.core.quota.QuotaCount;
@@ -66,6 +67,20 @@ public class Quotas {
public String getName() {
return quotaRoot.getValue();
}
+
+ @Override
+ public final boolean equals(Object o) {
+ if (o instanceof QuotaId) {
+ QuotaId other = (QuotaId) o;
+ return Objects.equals(quotaRoot, other.quotaRoot);
+ }
+ return false;
+ }
+
+ @Override
+ public final int hashCode() {
+ return Objects.hashCode(quotaRoot);
+ }
}
public static class Quota {
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/mailbox/QuotaIdTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/mailbox/QuotaIdTest.java
new file mode 100644
index 0000000..591b69d
--- /dev/null
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/mailbox/QuotaIdTest.java
@@ -0,0 +1,32 @@
+/****************************************************************
+ * 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.jmap.model.mailbox;
+
+import org.junit.Test;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+
+public class QuotaIdTest {
+
+ @Test
+ public void shouldRespectJavaBeanContract() {
+ EqualsVerifier.forClass(Quotas.QuotaId.class).verify();
+ }
+
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org