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:58 UTC

[james-project] branch master updated (59e4b07 -> 0bb1bc6)

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

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


    from 59e4b07  JAMES-2740 Cache mailbox listing in RandomStoring mailet
     new 7bf9d99  JMAP getMailboxes preload quotas for user namespace/name in order to avoid doing it for each mailbox
     new 3897673  JAMES-2746 extract QuotaLoader from MailboxFactory
     new aa1540f  JAMES-2694 zip archive loader - read mailboxes
     new 232688e  JAMES-2694 restore mailbox
     new 57ce846  JAMES-2694 shoud not restore in non empty account
     new 0bb1bc6  JAMES-2694 add package info for zip archive

The 6 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../james/mailbox/model/search/MailboxQuery.java   |   7 +-
 .../james/mailbox/backup/DefaultMailboxBackup.java |  57 ++++++-
 .../james/mailbox/backup/MailArchiveEntry.java     |  14 +-
 .../james/mailbox/backup/MailArchiveIterator.java  |  10 +-
 ...MailboxBackup.java => MailArchiveRestorer.java} |  10 +-
 .../james/mailbox/backup/MailArchivesLoader.java}  |  10 +-
 .../apache/james/mailbox/backup/MailboxBackup.java |  15 ++
 .../backup/MailboxWithAnnotationsArchiveEntry.java |  55 ++++---
 .../james/mailbox/backup/MessageArchiveEntry.java} | 168 +++++++++------------
 .../james/mailbox/backup/SerializedMailboxId.java  |  34 ++---
 .../james/mailbox/backup/SerializedMessageId.java  |  34 ++---
 .../{Directory.java => UnknownArchiveEntry.java}   |  17 ++-
 .../mailbox/backup/ZipMailArchiveRestorer.java     | 101 +++++++++++++
 .../mailbox/backup/zip/ExtraFieldExtractor.java    |  51 +++----
 .../mailbox/backup/zip/ZipArchivesLoader.java      |  29 ++--
 .../james/mailbox/backup/zip/ZipEntryIterator.java |  70 ++++++---
 .../backup/zip/ZippedMailAccountIterator.java      | 109 +++++++++++++
 .../apache/james/mailbox/backup/zip/Zipper.java    |   2 +-
 .../james/mailbox/backup/zip/package-info.java     |  52 +++++++
 .../mailbox/backup/DefaultMailboxBackupTest.java   | 139 +++++++++++++----
 .../mailbox/backup/MailboxMessageFixture.java      |  16 +-
 .../mailbox/backup/ZipArchivesLoaderTest.java      | 147 ++++++++++++++++++
 .../james/jmap/methods/GetMailboxesMethod.java     |  45 ++++--
 .../apache/james/jmap/model/MailboxFactory.java    |  67 ++++----
 .../apache/james/jmap/model/mailbox/Quotas.java    |  15 ++
 .../jmap/utils/quotas/DefaultQuotaLoader.java      |  35 +++--
 .../james/jmap/utils/quotas/QuotaLoader.java       |  40 +++--
 .../quotas/QuotaLoaderWithDefaultPreloaded.java    |  80 ++++++++++
 .../james/jmap/methods/GetMailboxesMethodTest.java |  31 ++--
 .../james/jmap/model/MailboxFactoryTest.java       |   2 +
 .../james/jmap/model/mailbox/QuotaIdTest.java}     |  13 +-
 31 files changed, 1067 insertions(+), 408 deletions(-)
 copy server/container/cli/src/main/java/org/apache/james/cli/exceptions/JamesCliException.java => mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailArchiveEntry.java (86%)
 copy backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/ClientProvider.java => mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailArchiveIterator.java (86%)
 copy mailbox/backup/src/main/java/org/apache/james/mailbox/backup/{MailboxBackup.java => MailArchiveRestorer.java} (85%)
 copy mailbox/{api/src/main/java/org/apache/james/mailbox/extractor/TextExtractor.java => backup/src/main/java/org/apache/james/mailbox/backup/MailArchivesLoader.java} (87%)
 copy protocols/imap/src/main/java/org/apache/james/imap/message/response/AnnotationResponse.java => mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailboxWithAnnotationsArchiveEntry.java (50%)
 copy mailbox/{api/src/main/java/org/apache/james/mailbox/model/MessageMetaData.java => backup/src/main/java/org/apache/james/mailbox/backup/MessageArchiveEntry.java} (55%)
 copy server/data/data-api/src/main/java/org/apache/james/sieverepository/api/ScriptName.java => mailbox/backup/src/main/java/org/apache/james/mailbox/backup/SerializedMailboxId.java (69%)
 copy server/data/data-api/src/main/java/org/apache/james/sieverepository/api/ScriptName.java => mailbox/backup/src/main/java/org/apache/james/mailbox/backup/SerializedMessageId.java (69%)
 copy mailbox/backup/src/main/java/org/apache/james/mailbox/backup/{Directory.java => UnknownArchiveEntry.java} (78%)
 create mode 100644 mailbox/backup/src/main/java/org/apache/james/mailbox/backup/ZipMailArchiveRestorer.java
 copy server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/AddressesArrayToMailAddressListConverter.java => mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ExtraFieldExtractor.java (51%)
 copy protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/EmptyContent.java => mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ZipArchivesLoader.java (69%)
 copy server/protocols/jwt/src/main/java/org/apache/james/jwt/PublicKeyReader.java => mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ZipEntryIterator.java (51%)
 create mode 100644 mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ZippedMailAccountIterator.java
 create mode 100644 mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/package-info.java
 create mode 100644 mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipArchivesLoaderTest.java
 copy mailbox/api/src/test/java/org/apache/james/mailbox/manager/IntegrationResources.java => server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/quotas/DefaultQuotaLoader.java (56%)
 copy mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/quota/QuotaCodec.java => server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/quotas/QuotaLoader.java (58%)
 create mode 100644 server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/quotas/QuotaLoaderWithDefaultPreloaded.java
 copy server/{task/src/test/java/org/apache/james/task/TaskIdTest.java => protocols/jmap/src/test/java/org/apache/james/jmap/model/mailbox/QuotaIdTest.java} (87%)


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


[james-project] 04/06: JAMES-2694 restore mailbox

Posted by ro...@apache.org.
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 232688edb7f0d593457f3cc1557d53d9029f68ad
Author: Rémi Kowalski <rk...@linagora.com>
AuthorDate: Mon Apr 8 12:02:30 2019 +0200

    JAMES-2694 restore mailbox
---
 .../james/mailbox/backup/DefaultMailboxBackup.java |  38 +++++--
 ...MailboxBackup.java => MailArchiveRestorer.java} |  10 +-
 .../apache/james/mailbox/backup/MailboxBackup.java |   9 ++
 .../james/mailbox/backup/SerializedMailboxId.java  |   4 +-
 .../james/mailbox/backup/SerializedMessageId.java  |   4 +-
 .../mailbox/backup/ZipMailArchiveRestorer.java     | 101 +++++++++++++++++
 .../mailbox/backup/zip/ExtraFieldExtractor.java    |   3 +-
 .../james/mailbox/backup/zip/ZipEntryIterator.java |   2 +-
 .../backup/zip/ZippedMailAccountIterator.java      |   1 -
 .../mailbox/backup/DefaultMailboxBackupTest.java   | 123 ++++++++++++++++-----
 .../mailbox/backup/MailboxMessageFixture.java      |   4 +-
 .../mailbox/backup/ZipArchivesLoaderTest.java      |  20 ++--
 12 files changed, 257 insertions(+), 62 deletions(-)

diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/DefaultMailboxBackup.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/DefaultMailboxBackup.java
index 578c9ec..0496b40 100644
--- a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/DefaultMailboxBackup.java
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/DefaultMailboxBackup.java
@@ -19,6 +19,7 @@
 package org.apache.james.mailbox.backup;
 
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.List;
 import java.util.stream.Stream;
@@ -37,16 +38,22 @@ import org.apache.james.mailbox.model.MessageRange;
 import org.apache.james.mailbox.model.MessageResult;
 import org.apache.james.mailbox.model.search.MailboxQuery;
 import org.apache.james.util.streams.Iterators;
+import org.reactivestreams.Publisher;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.github.fge.lambdas.Throwing;
 import com.github.steveash.guavate.Guavate;
+import com.google.common.annotations.VisibleForTesting;
+import reactor.core.publisher.Mono;
+import reactor.core.scheduler.Schedulers;
 
 public class DefaultMailboxBackup implements MailboxBackup {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(DefaultMailboxBackup.class);
 
-    private static class MailAccountContent {
+    @VisibleForTesting
+    static class MailAccountContent {
         private final MailboxWithAnnotations mailboxWithAnnotations;
         private final Stream<MessageResult> messages;
 
@@ -64,9 +71,14 @@ public class DefaultMailboxBackup implements MailboxBackup {
         }
     }
 
-    public DefaultMailboxBackup(MailboxManager mailboxManager, ArchiveService archiveService) {
+    private final MailboxManager mailboxManager;
+    private final ArchiveService archiveService;
+    private final MailArchiveRestorer archiveRestorer;
+
+    public DefaultMailboxBackup(MailboxManager mailboxManager, ArchiveService archiveService, MailArchiveRestorer archiveRestorer) {
         this.mailboxManager = mailboxManager;
         this.archiveService = archiveService;
+        this.archiveRestorer = archiveRestorer;
     }
 
     @Override
@@ -81,12 +93,18 @@ public class DefaultMailboxBackup implements MailboxBackup {
         archive(mailboxes, messages, destination);
     }
 
-    private final MailboxManager mailboxManager;
-    private final ArchiveService archiveService;
+    @Override
+    public Publisher<Void> restore(User user, InputStream source) {
+        return Mono.fromRunnable(Throwing.runnable(() -> archiveRestorer.restore(user, source)))
+            .subscribeOn(Schedulers.elastic())
+            .doOnError(e -> LOGGER.error("Error during account restoration for user : " + user, e))
+            .doOnTerminate(Throwing.runnable(source::close))
+            .then();
+    }
 
     private Stream<MailAccountContent> getMailboxWithAnnotationsFromPath(MailboxSession session, MailboxPath path) {
         try {
-            MessageManager messageManager =  mailboxManager.getMailbox(path, session);
+            MessageManager messageManager = mailboxManager.getMailbox(path, session);
             Mailbox mailbox = messageManager.getMailboxEntity();
             List<MailboxAnnotation> annotations = mailboxManager.getAllAnnotations(path, session);
             MailboxWithAnnotations mailboxWithAnnotations = new MailboxWithAnnotations(mailbox, annotations);
@@ -98,9 +116,13 @@ public class DefaultMailboxBackup implements MailboxBackup {
         }
     }
 
-    private List<MailAccountContent> getAccountContentForUser(MailboxSession session) throws MailboxException {
-        MailboxQuery queryUser = MailboxQuery.builder().username(session.getUser().asString()).build();
-        Stream<MailboxPath> paths = mailboxManager.search(queryUser, session).stream()
+    @VisibleForTesting
+    List<MailAccountContent> getAccountContentForUser(MailboxSession session) throws MailboxException {
+        MailboxQuery queryUser = MailboxQuery.builder()
+            .user(session.getUser())
+            .build();
+        Stream<MailboxPath> paths = mailboxManager.search(queryUser, session)
+            .stream()
             .map(MailboxMetaData::getPath);
         List<MailAccountContent> mailboxes = paths
             .flatMap(path -> getMailboxWithAnnotationsFromPath(session, path))
diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailboxBackup.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailArchiveRestorer.java
similarity index 85%
copy from mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailboxBackup.java
copy to mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailArchiveRestorer.java
index 1b3151e..091a258 100644
--- a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailboxBackup.java
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailArchiveRestorer.java
@@ -19,16 +19,12 @@
 package org.apache.james.mailbox.backup;
 
 import java.io.IOException;
-import java.io.OutputStream;
+import java.io.InputStream;
 
 import org.apache.james.core.User;
 import org.apache.james.mailbox.exception.MailboxException;
 
-public interface MailboxBackup {
-
-    /**
-     * @param user the user account to export
-     */
-    void backupAccount(User user, OutputStream destination) throws IOException, MailboxException;
+public interface MailArchiveRestorer {
 
+    void restore(User user, InputStream source) throws MailboxException, IOException;
 }
diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailboxBackup.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailboxBackup.java
index 1b3151e..5f837b2 100644
--- a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailboxBackup.java
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailboxBackup.java
@@ -19,10 +19,12 @@
 package org.apache.james.mailbox.backup;
 
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 
 import org.apache.james.core.User;
 import org.apache.james.mailbox.exception.MailboxException;
+import org.reactivestreams.Publisher;
 
 public interface MailboxBackup {
 
@@ -31,4 +33,11 @@ public interface MailboxBackup {
      */
     void backupAccount(User user, OutputStream destination) throws IOException, MailboxException;
 
+    /**
+     * @param user the user in which account the restored elements will be stored.
+     * @param source the input stream to the archive containing the account elements.
+     * @return a Publisher indicating when the action is completed
+     */
+    Publisher<Void> restore(User user, InputStream source) throws IOException, MailboxException;
+
 }
diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/SerializedMailboxId.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/SerializedMailboxId.java
index dc0fd6b..d50152a 100644
--- a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/SerializedMailboxId.java
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/SerializedMailboxId.java
@@ -29,8 +29,8 @@ public class SerializedMailboxId {
         this.value = value;
     }
 
-    public SerializedMailboxId(MailboxId mailboxId) {
-        this.value = mailboxId.serialize();
+    public static SerializedMailboxId from(MailboxId mailboxId) {
+        return new SerializedMailboxId(mailboxId.serialize());
     }
 
     public String getValue() {
diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/SerializedMessageId.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/SerializedMessageId.java
index 76b4c6f..63f3b6b 100644
--- a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/SerializedMessageId.java
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/SerializedMessageId.java
@@ -29,8 +29,8 @@ public class SerializedMessageId {
         this.value = value;
     }
 
-    public SerializedMessageId(MessageId messageId) {
-        this.value = messageId.serialize();
+    public static SerializedMessageId from(MessageId messageId) {
+        return new SerializedMessageId(messageId.serialize());
     }
 
     public String getValue() {
diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/ZipMailArchiveRestorer.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/ZipMailArchiveRestorer.java
new file mode 100644
index 0000000..90b96c5
--- /dev/null
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/ZipMailArchiveRestorer.java
@@ -0,0 +1,101 @@
+/****************************************************************
+ * 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.backup;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.james.core.User;
+import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MessageManager;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.MailboxId;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.util.OptionalUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.github.fge.lambdas.Throwing;
+import com.github.steveash.guavate.Guavate;
+import com.google.common.collect.ImmutableList;
+
+public class ZipMailArchiveRestorer implements MailArchiveRestorer {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(ZipMailArchiveRestorer.class);
+
+    private final MailboxManager mailboxManager;
+    private final MailArchivesLoader archiveLoader;
+
+    public ZipMailArchiveRestorer(MailboxManager mailboxManager, MailArchivesLoader archiveLoader) {
+        this.mailboxManager = mailboxManager;
+        this.archiveLoader = archiveLoader;
+    }
+
+    public void restore(User user, InputStream source) throws MailboxException, IOException {
+        MailboxSession session = mailboxManager.createSystemSession(user.asString());
+        restoreEntries(source, session);
+    }
+
+    private void restoreEntries(InputStream source, MailboxSession session) throws IOException {
+        try (MailArchiveIterator archiveIterator = archiveLoader.load(source)) {
+            List<MailboxWithAnnotationsArchiveEntry> mailboxes = readMailboxes(archiveIterator);
+            restoreMailboxes(session, mailboxes);
+        }
+    }
+
+    private Map<SerializedMailboxId, MessageManager> restoreMailboxes(MailboxSession session, List<MailboxWithAnnotationsArchiveEntry> mailboxes) {
+        return mailboxes.stream()
+            .flatMap(Throwing.<MailboxWithAnnotationsArchiveEntry, Stream<ImmutablePair<SerializedMailboxId, MessageManager>>>function(
+                mailboxEntry ->
+                    OptionalUtils.toStream(restoreMailboxEntry(session, mailboxEntry))).sneakyThrow())
+            .collect(Guavate.entriesToImmutableMap());
+    }
+
+    private List<MailboxWithAnnotationsArchiveEntry> readMailboxes(MailArchiveIterator iterator) {
+        ImmutableList.Builder<MailboxWithAnnotationsArchiveEntry> mailboxes = ImmutableList.builder();
+        while (iterator.hasNext()) {
+            MailArchiveEntry entry = iterator.next();
+            switch (entry.getType()) {
+                case MAILBOX:
+                    mailboxes.add((MailboxWithAnnotationsArchiveEntry) entry);
+                    break;
+                case UNKNOWN:
+                    String entryName = ((UnknownArchiveEntry) entry).getEntryName();
+                    LOGGER.warn("unknown entry found in zip :" + entryName);
+                    break;
+            }
+        }
+        return mailboxes.build();
+    }
+
+    private Optional<ImmutablePair<SerializedMailboxId, MessageManager>> restoreMailboxEntry(MailboxSession session,
+                                                                                             MailboxWithAnnotationsArchiveEntry mailboxWithAnnotationsArchiveEntry) throws MailboxException {
+        MailboxPath mailboxPath = MailboxPath.forUser(session.getUser().asString(), mailboxWithAnnotationsArchiveEntry.getMailboxName());
+        Optional<MailboxId> newMailboxId = mailboxManager.createMailbox(mailboxPath, session);
+        mailboxManager.updateAnnotations(mailboxPath, session, mailboxWithAnnotationsArchiveEntry.getAnnotations());
+        return newMailboxId.map(Throwing.<MailboxId, ImmutablePair<SerializedMailboxId, MessageManager>>function(newId ->
+            ImmutablePair.of(mailboxWithAnnotationsArchiveEntry.getMailboxId(), mailboxManager.getMailbox(newId, session))).sneakyThrow());
+    }
+}
diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ExtraFieldExtractor.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ExtraFieldExtractor.java
index abc0c28..1c1155c 100644
--- a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ExtraFieldExtractor.java
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ExtraFieldExtractor.java
@@ -35,7 +35,8 @@ public class ExtraFieldExtractor {
         ZipExtraField[] extraFields = ExtraFieldUtils.parse(entry.getExtra());
         return Arrays.stream(extraFields)
             .filter(field -> field.getHeaderId().equals(id))
-            .map(extraField -> ((StringExtraField) extraField).getValue())
+            .map(StringExtraField.class::cast)
+            .map(StringExtraField::getValue)
             .findFirst()
             .flatMap(Function.identity());
     }
diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ZipEntryIterator.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ZipEntryIterator.java
index 160bf74..e834335 100644
--- a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ZipEntryIterator.java
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ZipEntryIterator.java
@@ -39,7 +39,7 @@ public class ZipEntryIterator implements Iterator<ZipEntry>, Closeable {
         try {
             next = Optional.ofNullable(zipInputStream.getNextEntry());
         } catch (IOException e) {
-            //EMPTY STREAM
+            LOGGER.error("Empty stream or error during reading first entry", e);
             next = Optional.empty();
         }
     }
diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ZippedMailAccountIterator.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ZippedMailAccountIterator.java
index 5b1d5c2..1b690f1 100644
--- a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ZippedMailAccountIterator.java
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ZippedMailAccountIterator.java
@@ -96,7 +96,6 @@ public class ZippedMailAccountIterator implements MailArchiveIterator {
 
     private MailArchiveEntry fromMailboxEntry(ZipEntry current) throws ZipException {
         return new MailboxWithAnnotationsArchiveEntry(getMailboxName(current), getMailBoxId(current).get(), NO_ANNOTATION);
-
     }
 
     private MailArchiveEntry from(ZipEntry current, ZipEntryType currentEntryType) throws ZipException {
diff --git a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/DefaultMailboxBackupTest.java b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/DefaultMailboxBackupTest.java
index 81f5dc3..d1eff05 100644
--- a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/DefaultMailboxBackupTest.java
+++ b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/DefaultMailboxBackupTest.java
@@ -18,44 +18,55 @@
  ****************************************************************/
 package org.apache.james.mailbox.backup;
 
+import static org.assertj.core.api.Assertions.assertThat;
 
+import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.util.Arrays;
-import java.util.HashSet;
+import java.util.List;
 
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.MessageManager;
 import org.apache.james.mailbox.backup.ZipAssert.EntryChecks;
+import org.apache.james.mailbox.backup.zip.ZipArchivesLoader;
 import org.apache.james.mailbox.backup.zip.Zipper;
-import org.apache.james.mailbox.extension.PreDeletionHook;
-import org.apache.james.mailbox.inmemory.MemoryMailboxManagerProvider;
+import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
+import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
 import com.github.fge.lambdas.Throwing;
+import reactor.core.publisher.Mono;
 
 class DefaultMailboxBackupTest implements MailboxMessageFixture {
-
-    private static final HashSet<PreDeletionHook> PRE_DELETION_HOOKS = new HashSet<>();
-
     private static final int BUFFER_SIZE = 4096;
+    public static final String EXPECTED_ANNOTATIONS_DIR = "annotations";
 
     private final ArchiveService archiveService = new Zipper();
+    private final MailArchivesLoader archiveLoader = new ZipArchivesLoader();
 
+    private MailArchiveRestorer archiveRestorer;
     private MailboxManager mailboxManager;
     private DefaultMailboxBackup backup;
 
+    private MailboxSession sessionUser;
+    private MailboxSession sessionOtherUser;
+
     @BeforeEach
-    void beforeEach() {
-        mailboxManager = MemoryMailboxManagerProvider.provideMailboxManager(PRE_DELETION_HOOKS);
-        backup = new DefaultMailboxBackup(mailboxManager, archiveService);
+    void beforeEach() throws Exception {
+        mailboxManager = InMemoryIntegrationResources.defaultResources().getMailboxManager();
+        archiveRestorer = new ZipMailArchiveRestorer(mailboxManager, archiveLoader);
+        backup = new DefaultMailboxBackup(mailboxManager, archiveService, archiveRestorer);
+        sessionUser = mailboxManager.createSystemSession(USER);
+        sessionOtherUser = mailboxManager.createSystemSession(OTHER_USER);
     }
 
-    private void createMailBoxWithMessage(MailboxSession session, MailboxPath mailboxPath, MessageManager.AppendCommand... messages) throws Exception {
+    private void createMailBoxWithMessages(MailboxSession session, MailboxPath mailboxPath, MessageManager.AppendCommand... messages) throws Exception {
         MailboxId mailboxId = mailboxManager.createMailbox(mailboxPath, session).get();
         Arrays.stream(messages).forEach(Throwing.consumer(message ->
                 mailboxManager.getMailbox(mailboxId, session).appendMessage(message, session)
@@ -63,6 +74,10 @@ class DefaultMailboxBackupTest implements MailboxMessageFixture {
         );
     }
 
+    private void createMailbox(MailboxSession session, MailboxPath mailboxPath) throws Exception {
+        createMailBoxWithMessages(session, mailboxPath);
+    }
+
     @Test
     void doBackupWithoutMailboxShouldStoreEmptyBackup() throws Exception {
         ByteArrayOutputStream destination = new ByteArrayOutputStream(BUFFER_SIZE);
@@ -75,8 +90,7 @@ class DefaultMailboxBackupTest implements MailboxMessageFixture {
     @Test
     void doBackupWithoutMessageShouldStoreAnArchiveWithOnlyOneEntry() throws Exception {
         ByteArrayOutputStream destination = new ByteArrayOutputStream(BUFFER_SIZE);
-        MailboxSession session = mailboxManager.createSystemSession(USER);
-        createMailBoxWithMessage(session, MAILBOX_PATH_USER1_MAILBOX1);
+        createMailbox(sessionUser, MAILBOX_PATH_USER1_MAILBOX1);
 
         backup.backupAccount(USER1, destination);
         try (ZipAssert zipAssert = ZipAssert.assertThatZip(destination)) {
@@ -87,15 +101,14 @@ class DefaultMailboxBackupTest implements MailboxMessageFixture {
     @Test
     void doBackupMailboxWithAnnotationShouldStoreAnArchiveWithMailboxAndAnnotation() throws Exception {
         ByteArrayOutputStream destination = new ByteArrayOutputStream(BUFFER_SIZE);
-        MailboxSession session = mailboxManager.createSystemSession(USER);
-        createMailBoxWithMessage(session, MAILBOX_PATH_USER1_MAILBOX1);
-        mailboxManager.updateAnnotations(MAILBOX_PATH_USER1_MAILBOX1, session, WITH_ANNOTATION_1);
+        createMailbox(sessionUser, MAILBOX_PATH_USER1_MAILBOX1);
+        mailboxManager.updateAnnotations(MAILBOX_PATH_USER1_MAILBOX1, sessionUser, WITH_ANNOTATION_1);
 
         backup.backupAccount(USER1, destination);
         try (ZipAssert zipAssert = ZipAssert.assertThatZip(destination)) {
             zipAssert.containsOnlyEntriesMatching(EntryChecks.hasName(MAILBOX_1_NAME + "/").isDirectory(),
-                EntryChecks.hasName(MAILBOX_1_NAME + "/" + "annotations" + "/").isDirectory(),
-                EntryChecks.hasName(MAILBOX_1_NAME + "/" + "annotations" + "/" + ANNOTATION_1_KEY.asString()).hasStringContent(ANNOTATION_1_CONTENT)
+                EntryChecks.hasName(MAILBOX_1_NAME + "/" + EXPECTED_ANNOTATIONS_DIR + "/").isDirectory(),
+                EntryChecks.hasName(MAILBOX_1_NAME + "/" + EXPECTED_ANNOTATIONS_DIR + "/" + ANNOTATION_1_KEY.asString()).hasStringContent(ANNOTATION_1_CONTENT)
             );
         }
     }
@@ -103,8 +116,7 @@ class DefaultMailboxBackupTest implements MailboxMessageFixture {
     @Test
     void doBackupWithOneMessageShouldStoreAnArchiveWithTwoEntries() throws Exception {
         ByteArrayOutputStream destination = new ByteArrayOutputStream(BUFFER_SIZE);
-        MailboxSession session = mailboxManager.createSystemSession(USER);
-        createMailBoxWithMessage(session, MAILBOX_PATH_USER1_MAILBOX1, getMessage1AppendCommand());
+        createMailBoxWithMessages(sessionUser, MAILBOX_PATH_USER1_MAILBOX1, getMessage1AppendCommand());
 
         backup.backupAccount(USER1, destination);
 
@@ -119,9 +131,8 @@ class DefaultMailboxBackupTest implements MailboxMessageFixture {
     @Test
     void doBackupWithTwoMailboxesAndOneMessageShouldStoreAnArchiveWithThreeEntries() throws Exception {
         ByteArrayOutputStream destination = new ByteArrayOutputStream(BUFFER_SIZE);
-        MailboxSession session = mailboxManager.createSystemSession(USER);
-        createMailBoxWithMessage(session, MAILBOX_PATH_USER1_MAILBOX1, getMessage1AppendCommand());
-        createMailBoxWithMessage(session, MAILBOX_PATH_USER1_MAILBOX2);
+        createMailBoxWithMessages(sessionUser, MAILBOX_PATH_USER1_MAILBOX1, getMessage1AppendCommand());
+        createMailbox(sessionUser, MAILBOX_PATH_USER1_MAILBOX2);
 
         backup.backupAccount(USER1, destination);
 
@@ -137,11 +148,9 @@ class DefaultMailboxBackupTest implements MailboxMessageFixture {
     @Test
     void doBackupShouldOnlyArchiveTheMailboxOfTheUser() throws Exception {
         ByteArrayOutputStream destination = new ByteArrayOutputStream(BUFFER_SIZE);
-        MailboxSession session = mailboxManager.createSystemSession(USER);
-        MailboxSession otherSession = mailboxManager.createSystemSession(OTHER_USER);
 
-        createMailBoxWithMessage(session, MAILBOX_PATH_USER1_MAILBOX1, getMessage1AppendCommand());
-        createMailBoxWithMessage(otherSession, MAILBOX_PATH_OTHER_USER_MAILBOX1, getMessage1OtherUserAppendCommand());
+        createMailBoxWithMessages(sessionUser, MAILBOX_PATH_USER1_MAILBOX1, getMessage1AppendCommand());
+        createMailBoxWithMessages(sessionOtherUser, MAILBOX_PATH_OTHER_USER_MAILBOX1, getMessage1OtherUserAppendCommand());
 
         backup.backupAccount(USER1, destination);
         try (ZipAssert zipAssert = ZipAssert.assertThatZip(destination)) {
@@ -152,10 +161,72 @@ class DefaultMailboxBackupTest implements MailboxMessageFixture {
         }
     }
 
+    @Test
+    void backupEmptyAccountThenRestoringItInUser2AccountShouldCreateNoElements() throws Exception {
+        ByteArrayOutputStream destination = new ByteArrayOutputStream(BUFFER_SIZE);
+        backup.backupAccount(USER1, destination);
+
+        InputStream source = new ByteArrayInputStream(destination.toByteArray());
+        Mono.from(backup.restore(USER2, source)).block();
+
+        List<DefaultMailboxBackup.MailAccountContent> content = backup.getAccountContentForUser(sessionOtherUser);
+
+        assertThat(content).isEmpty();
+    }
+
+    @Test
+    void backupAccountWithOneMailboxThenRestoringItInUser2AccountShouldCreateOneMailbox() throws Exception {
+        createMailbox(sessionUser, MAILBOX_PATH_USER1_MAILBOX1);
+
+        ByteArrayOutputStream destination = new ByteArrayOutputStream(BUFFER_SIZE);
+        backup.backupAccount(USER1, destination);
+
+        InputStream source = new ByteArrayInputStream(destination.toByteArray());
+        Mono.from(backup.restore(USER2, source)).block();
+
+        List<DefaultMailboxBackup.MailAccountContent> content = backup.getAccountContentForUser(sessionOtherUser);
+
+        assertThat(content).hasSize(1);
+        DefaultMailboxBackup.MailAccountContent mailAccountContent = content.get(0);
+        Mailbox mailbox = mailAccountContent.getMailboxWithAnnotations().mailbox;
+        assertThat(mailbox.getName()).isEqualTo(MAILBOX_1_NAME);
+        assertThat(mailAccountContent.getMessages().count()).isEqualTo(0);
+    }
+
+    @Test
+    void backupAccountWithTwoMailboxesThenRestoringItInUser2AccountShouldCreateTwoMailboxes() throws Exception {
+        createMailbox(sessionUser, MAILBOX_PATH_USER1_MAILBOX1);
+        createMailbox(sessionUser, MAILBOX_PATH_USER1_MAILBOX2);
+
+        ByteArrayOutputStream destination = new ByteArrayOutputStream(BUFFER_SIZE);
+        backup.backupAccount(USER1, destination);
+
+        InputStream source = new ByteArrayInputStream(destination.toByteArray());
+        Mono.from(backup.restore(USER2, source)).block();
+
+        List<DefaultMailboxBackup.MailAccountContent> content = backup.getAccountContentForUser(sessionOtherUser);
+
+        assertThat(content).hasSize(2);
+        DefaultMailboxBackup.MailAccountContent contentMailbox1 = content.get(0);
+        Mailbox mailbox1 = contentMailbox1.getMailboxWithAnnotations().mailbox;
+        assertThat(mailbox1.getName()).isEqualTo(MAILBOX_1_NAME);
+        assertThat(contentMailbox1.getMessages().count()).isEqualTo(0);
+
+        DefaultMailboxBackup.MailAccountContent contentMailbox2 = content.get(1);
+        Mailbox mailbox2 = contentMailbox2.getMailboxWithAnnotations().mailbox;
+        assertThat(mailbox2.getName()).isEqualTo(MAILBOX_2_NAME);
+        assertThat(contentMailbox2.getMessages().count()).isEqualTo(0);
+
+    }
+
     private MessageManager.AppendCommand getMessage1AppendCommand() throws IOException {
         return MessageManager.AppendCommand.builder().withFlags(flags1).build(MESSAGE_1.getFullContent());
     }
 
+    private MessageManager.AppendCommand getMessage2AppendCommand() throws IOException {
+        return MessageManager.AppendCommand.builder().withFlags(flags1).build(MESSAGE_2.getFullContent());
+    }
+
     private MessageManager.AppendCommand getMessage1OtherUserAppendCommand() throws IOException {
         return MessageManager.AppendCommand.builder().withFlags(flags1).build(MESSAGE_1_OTHER_USER.getFullContent());
     }
diff --git a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java
index 9be370a..23641da 100644
--- a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java
+++ b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java
@@ -84,8 +84,8 @@ public interface MailboxMessageFixture {
     MailboxId MAILBOX_ID_2 = TestId.of(2L);
     MailboxId MAILBOX_ID_11 = TestId.of(11L);
 
-    SerializedMailboxId SERIALIZED_MAILBOX_ID_1 = new SerializedMailboxId(MAILBOX_ID_1);
-    SerializedMailboxId SERIALIZED_MAILBOX_ID_2 = new SerializedMailboxId(MAILBOX_ID_2);
+    SerializedMailboxId SERIALIZED_MAILBOX_ID_1 = SerializedMailboxId.from(MAILBOX_ID_1);
+    SerializedMailboxId SERIALIZED_MAILBOX_ID_2 = SerializedMailboxId.from(MAILBOX_ID_2);
 
     Flags flags1 = new Flags("myFlags");
 
diff --git a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipArchivesLoaderTest.java b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipArchivesLoaderTest.java
index a4054d3..67baac8 100644
--- a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipArchivesLoaderTest.java
+++ b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipArchivesLoaderTest.java
@@ -23,15 +23,10 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
-import java.io.IOException;
 import java.io.InputStream;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.NoSuchElementException;
 
-import javax.mail.Flags;
-
-import org.apache.commons.io.IOUtils;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.MessageManager;
@@ -52,16 +47,19 @@ public class ZipArchivesLoaderTest implements MailboxMessageFixture {
     private final ArchiveService archiveService = new Zipper();
     private final MailArchivesLoader archiveLoader = new ZipArchivesLoader();
 
+    private MailArchiveRestorer archiveRestorer;
     private MailboxManager mailboxManager;
     private DefaultMailboxBackup backup;
 
     @BeforeEach
     void beforeEach() {
         mailboxManager = InMemoryIntegrationResources.defaultResources().getMailboxManager();
-        backup = new DefaultMailboxBackup(mailboxManager, archiveService);
+        archiveRestorer = new ZipMailArchiveRestorer(mailboxManager, archiveLoader);
+        backup = new DefaultMailboxBackup(mailboxManager, archiveService, archiveRestorer);
     }
 
-    private void createMailBoxWithMessage(MailboxSession session, MailboxPath mailboxPath, MailboxMessage... messages) throws Exception {
+    private void createMailBoxWithMessage(MailboxPath mailboxPath, MailboxMessage... messages) throws Exception {
+        MailboxSession session = mailboxManager.createSystemSession(mailboxPath.getUser());
         MailboxId mailboxId = mailboxManager.createMailbox(mailboxPath, session).get();
         Arrays.stream(messages).forEach(Throwing.consumer(message ->
             {
@@ -102,8 +100,7 @@ public class ZipArchivesLoaderTest implements MailboxMessageFixture {
 
     @Test
     void mailAccountIteratorFromArchiveWithOneMailboxShouldContainOneMailbox() throws Exception {
-        MailboxSession session = mailboxManager.createSystemSession(USER);
-        createMailBoxWithMessage(session, MAILBOX_PATH_USER1_MAILBOX1);
+        createMailBoxWithMessage(MAILBOX_PATH_USER1_MAILBOX1);
 
         ByteArrayOutputStream destination = new ByteArrayOutputStream(BUFFER_SIZE);
         backup.backupAccount(USER1, destination);
@@ -119,9 +116,8 @@ public class ZipArchivesLoaderTest implements MailboxMessageFixture {
 
     @Test
     void mailAccountIteratorFromArchiveWithTwoMailboxesShouldContainTwoMailboxes() throws Exception {
-        MailboxSession session = mailboxManager.createSystemSession(USER);
-        createMailBoxWithMessage(session, MAILBOX_PATH_USER1_MAILBOX1);
-        createMailBoxWithMessage(session, MAILBOX_PATH_USER1_MAILBOX2);
+        createMailBoxWithMessage(MAILBOX_PATH_USER1_MAILBOX1);
+        createMailBoxWithMessage(MAILBOX_PATH_USER1_MAILBOX2);
 
         ByteArrayOutputStream destination = new ByteArrayOutputStream(BUFFER_SIZE);
         backup.backupAccount(USER1, destination);


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


[james-project] 01/06: JMAP getMailboxes preload quotas for user namespace/name in order to avoid doing it for each mailbox

Posted by ro...@apache.org.
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


[james-project] 03/06: JAMES-2694 zip archive loader - read mailboxes

Posted by ro...@apache.org.
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 aa1540fb41b2d54e3c0edba95673e6c512dcfe37
Author: Rémi Kowalski <rk...@linagora.com>
AuthorDate: Mon Apr 8 12:02:11 2019 +0200

    JAMES-2694 zip archive loader - read mailboxes
---
 .../james/mailbox/model/search/MailboxQuery.java   |   7 +-
 .../james/mailbox/backup/MailArchiveEntry.java     |  30 ++++
 .../james/mailbox/backup/MailArchiveIterator.java  |  26 ++++
 .../james/mailbox/backup/MailArchivesLoader.java   |  26 ++++
 .../backup/MailboxWithAnnotationsArchiveEntry.java |  77 +++++++++++
 .../james/mailbox/backup/MessageArchiveEntry.java  |  72 ++++++++++
 .../james/mailbox/backup/SerializedMailboxId.java  |  54 ++++++++
 .../james/mailbox/backup/SerializedMessageId.java  |  54 ++++++++
 .../james/mailbox/backup/UnknownArchiveEntry.java  |  38 ++++++
 .../mailbox/backup/zip/ExtraFieldExtractor.java    |  56 ++++++++
 .../mailbox/backup/zip/ZipArchivesLoader.java      |  35 +++++
 .../james/mailbox/backup/zip/ZipEntryIterator.java |  80 +++++++++++
 .../backup/zip/ZippedMailAccountIterator.java      | 110 +++++++++++++++
 .../apache/james/mailbox/backup/zip/Zipper.java    |   2 +-
 .../mailbox/backup/MailboxMessageFixture.java      |  16 ++-
 .../mailbox/backup/ZipArchivesLoaderTest.java      | 151 +++++++++++++++++++++
 16 files changed, 828 insertions(+), 6 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 ed2f747..6c10eac 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
@@ -76,6 +76,11 @@ public final class MailboxQuery {
             return this;
         }
 
+        public Builder user(User user) {
+            this.username(user.asString());
+            return this;
+        }
+
         public Builder namespace(String namespace) {
             Preconditions.checkState(!this.namespace.isPresent());
 
@@ -89,7 +94,7 @@ public final class MailboxQuery {
             this.namespace = Optional.of(MailboxConstants.USER_NAMESPACE);
             return this;
         }
-        
+
         public Builder expression(MailboxNameExpression expression) {
             this.mailboxNameExpression = Optional.of(expression);
             return this;
diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailArchiveEntry.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailArchiveEntry.java
new file mode 100644
index 0000000..672c4d2
--- /dev/null
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailArchiveEntry.java
@@ -0,0 +1,30 @@
+/****************************************************************
+ * 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.backup;
+
+public interface MailArchiveEntry {
+    enum ArchiveEntryType {
+        MAILBOX,
+        MESSAGE,
+        UNKNOWN
+    }
+
+    ArchiveEntryType getType();
+
+}
diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailArchiveIterator.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailArchiveIterator.java
new file mode 100644
index 0000000..43b0966
--- /dev/null
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailArchiveIterator.java
@@ -0,0 +1,26 @@
+/****************************************************************
+ * 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.backup;
+
+import java.io.Closeable;
+import java.util.Iterator;
+
+public interface MailArchiveIterator extends Iterator<MailArchiveEntry>, Closeable {
+
+}
\ No newline at end of file
diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailArchivesLoader.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailArchivesLoader.java
new file mode 100644
index 0000000..5616d16
--- /dev/null
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailArchivesLoader.java
@@ -0,0 +1,26 @@
+/****************************************************************
+ * 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.backup;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public interface MailArchivesLoader {
+    MailArchiveIterator load(InputStream inputStream) throws IOException;
+}
diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailboxWithAnnotationsArchiveEntry.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailboxWithAnnotationsArchiveEntry.java
new file mode 100644
index 0000000..77c3bfc
--- /dev/null
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailboxWithAnnotationsArchiveEntry.java
@@ -0,0 +1,77 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+package org.apache.james.mailbox.backup;
+
+import java.util.List;
+import java.util.Objects;
+
+import org.apache.james.mailbox.model.MailboxAnnotation;
+
+import com.google.common.collect.ImmutableList;
+
+public class MailboxWithAnnotationsArchiveEntry implements MailArchiveEntry {
+    private final String mailboxName;
+    private final SerializedMailboxId mailboxId;
+
+    private final ImmutableList<MailboxAnnotation> annotations;
+
+    public MailboxWithAnnotationsArchiveEntry(String mailboxName, SerializedMailboxId mailboxId, List<MailboxAnnotation> annotations) {
+        this.mailboxName = mailboxName;
+        this.mailboxId = mailboxId;
+        this.annotations = ImmutableList.copyOf(annotations);
+    }
+
+    public String getMailboxName() {
+        return mailboxName;
+    }
+
+    public SerializedMailboxId getMailboxId() {
+        return mailboxId;
+    }
+
+    public List<MailboxAnnotation> getAnnotations() {
+        return annotations;
+    }
+
+    public MailboxWithAnnotationsArchiveEntry appendAnnotation(MailboxAnnotation annotation) {
+        ImmutableList<MailboxAnnotation> newAnnotations = ImmutableList.<MailboxAnnotation>builder().addAll(annotations).add(annotation).build();
+        return new MailboxWithAnnotationsArchiveEntry(mailboxName, mailboxId, newAnnotations);
+    }
+
+    @Override
+    public ArchiveEntryType getType() {
+        return ArchiveEntryType.MAILBOX;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof MailboxWithAnnotationsArchiveEntry) {
+            MailboxWithAnnotationsArchiveEntry that = (MailboxWithAnnotationsArchiveEntry) o;
+            return Objects.equals(mailboxName, that.mailboxName) &&
+                Objects.equals(mailboxId, that.mailboxId) &&
+                Objects.equals(annotations, that.annotations);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mailboxName, mailboxId, annotations);
+    }
+}
diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MessageArchiveEntry.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MessageArchiveEntry.java
new file mode 100644
index 0000000..3b3a6f9
--- /dev/null
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MessageArchiveEntry.java
@@ -0,0 +1,72 @@
+/****************************************************************
+ * 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.backup;
+
+import java.io.InputStream;
+import java.util.Date;
+
+import javax.mail.Flags;
+
+public class MessageArchiveEntry implements MailArchiveEntry {
+
+    private final SerializedMessageId messageId;
+    private final SerializedMailboxId mailboxId;
+    private final long size;
+    private final Date internalDate;
+    private final Flags flags;
+    private final InputStream content;
+
+    public MessageArchiveEntry(SerializedMessageId messageId, SerializedMailboxId mailboxId, long size, Date internalDate, Flags flags, InputStream content) {
+        this.messageId = messageId;
+        this.mailboxId = mailboxId;
+        this.size = size;
+        this.internalDate = internalDate;
+        this.flags = flags;
+        this.content = content;
+    }
+
+    public SerializedMessageId getMessageId() {
+        return messageId;
+    }
+
+    public SerializedMailboxId getMailboxId() {
+        return mailboxId;
+    }
+
+    public long getSize() {
+        return size;
+    }
+
+    public Date getInternalDate() {
+        return internalDate;
+    }
+
+    public Flags getFlags() {
+        return flags;
+    }
+
+    public InputStream getContent() {
+        return content;
+    }
+
+    @Override
+    public ArchiveEntryType getType() {
+        return ArchiveEntryType.MESSAGE;
+    }
+}
diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/SerializedMailboxId.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/SerializedMailboxId.java
new file mode 100644
index 0000000..dc0fd6b
--- /dev/null
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/SerializedMailboxId.java
@@ -0,0 +1,54 @@
+/****************************************************************
+ * 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.backup;
+
+import org.apache.james.mailbox.model.MailboxId;
+
+import com.google.common.base.Objects;
+
+public class SerializedMailboxId {
+    private final String value;
+
+    public SerializedMailboxId(String value) {
+        this.value = value;
+    }
+
+    public SerializedMailboxId(MailboxId mailboxId) {
+        this.value = mailboxId.serialize();
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof SerializedMailboxId) {
+            SerializedMailboxId that = (SerializedMailboxId) o;
+            return Objects.equal(value, that.value);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(value);
+    }
+
+}
diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/SerializedMessageId.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/SerializedMessageId.java
new file mode 100644
index 0000000..76b4c6f
--- /dev/null
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/SerializedMessageId.java
@@ -0,0 +1,54 @@
+/****************************************************************
+ * 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.backup;
+
+import org.apache.james.mailbox.model.MessageId;
+
+import com.google.common.base.Objects;
+
+public class SerializedMessageId {
+    private final String value;
+
+    public SerializedMessageId(String value) {
+        this.value = value;
+    }
+
+    public SerializedMessageId(MessageId messageId) {
+        this.value = messageId.serialize();
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof SerializedMessageId) {
+            SerializedMessageId that = (SerializedMessageId) o;
+            return Objects.equal(value, that.value);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(value);
+    }
+
+}
diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/UnknownArchiveEntry.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/UnknownArchiveEntry.java
new file mode 100644
index 0000000..88c858c
--- /dev/null
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/UnknownArchiveEntry.java
@@ -0,0 +1,38 @@
+/****************************************************************
+ * 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.backup;
+
+public class UnknownArchiveEntry implements MailArchiveEntry {
+
+    private final String entryName;
+
+    public UnknownArchiveEntry(String entryName) {
+        this.entryName = entryName;
+    }
+
+    public String getEntryName() {
+        return entryName;
+    }
+
+    @Override
+    public ArchiveEntryType getType() {
+        return ArchiveEntryType.UNKNOWN;
+    }
+
+}
diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ExtraFieldExtractor.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ExtraFieldExtractor.java
new file mode 100644
index 0000000..abc0c28
--- /dev/null
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ExtraFieldExtractor.java
@@ -0,0 +1,56 @@
+/****************************************************************
+ * 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.backup.zip;
+
+import java.util.Arrays;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
+
+import org.apache.commons.compress.archivers.zip.ExtraFieldUtils;
+import org.apache.commons.compress.archivers.zip.ZipExtraField;
+import org.apache.commons.compress.archivers.zip.ZipShort;
+import org.apache.james.util.OptionalUtils;
+
+public class ExtraFieldExtractor {
+
+    public static Optional<String> getStringExtraField(ZipShort id, ZipEntry entry) throws ZipException {
+        ZipExtraField[] extraFields = ExtraFieldUtils.parse(entry.getExtra());
+        return Arrays.stream(extraFields)
+            .filter(field -> field.getHeaderId().equals(id))
+            .map(extraField -> ((StringExtraField) extraField).getValue())
+            .findFirst()
+            .flatMap(Function.identity());
+    }
+
+    public static Optional<ZipEntryType> getEntryType(ZipEntry entry) {
+        try {
+            ZipExtraField[] extraFields = ExtraFieldUtils.parse(entry.getExtra());
+            return Arrays.stream(extraFields)
+                .filter(field -> field.getHeaderId().equals(EntryTypeExtraField.ID_AQ))
+                .flatMap(extraField ->
+                    OptionalUtils.toStream(((EntryTypeExtraField) extraField).getEnumValue()))
+                .findFirst();
+        } catch (Exception e) {
+            return Optional.empty();
+        }
+    }
+
+}
diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ZipArchivesLoader.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ZipArchivesLoader.java
new file mode 100644
index 0000000..14e6838
--- /dev/null
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ZipArchivesLoader.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.backup.zip;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.ZipInputStream;
+
+import org.apache.james.mailbox.backup.MailArchiveIterator;
+import org.apache.james.mailbox.backup.MailArchivesLoader;
+
+public class ZipArchivesLoader implements MailArchivesLoader {
+    @Override
+    public MailArchiveIterator load(InputStream inputStream) throws IOException {
+        ZipInputStream zipInputStream = new ZipInputStream(inputStream);
+        ZipEntryIterator zipEntryIterator = new ZipEntryIterator(zipInputStream);
+        return new ZippedMailAccountIterator(zipEntryIterator);
+    }
+}
diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ZipEntryIterator.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ZipEntryIterator.java
new file mode 100644
index 0000000..160bf74
--- /dev/null
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ZipEntryIterator.java
@@ -0,0 +1,80 @@
+/****************************************************************
+ * 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.backup.zip;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Optional;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ZipEntryIterator implements Iterator<ZipEntry>, Closeable {
+    private final ZipInputStream zipInputStream;
+    private Optional<ZipEntry> next;
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(ZipEntryIterator.class);
+
+    public ZipEntryIterator(ZipInputStream inputStream) {
+        zipInputStream = inputStream;
+        try {
+            next = Optional.ofNullable(zipInputStream.getNextEntry());
+        } catch (IOException e) {
+            //EMPTY STREAM
+            next = Optional.empty();
+        }
+    }
+
+    @Override
+    public boolean hasNext() {
+        return next.isPresent();
+    }
+
+    @Override
+    public ZipEntry next() {
+        Optional<ZipEntry> current = next;
+        if (!current.isPresent()) {
+            return null;
+        }
+
+        ZipEntry currentEntry = current.get();
+
+        advanceToNextEntry();
+
+        return currentEntry;
+    }
+
+    private void advanceToNextEntry() {
+        try {
+            next = Optional.ofNullable(zipInputStream.getNextEntry());
+        } catch (IOException e) {
+            LOGGER.error("Error when reading archive", e);
+            next = Optional.empty();
+        }
+    }
+
+    @Override
+    public void close() throws IOException {
+        zipInputStream.close();
+    }
+
+}
diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ZippedMailAccountIterator.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ZippedMailAccountIterator.java
new file mode 100644
index 0000000..5b1d5c2
--- /dev/null
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/ZippedMailAccountIterator.java
@@ -0,0 +1,110 @@
+/****************************************************************
+ * 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.backup.zip;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Optional;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.james.mailbox.backup.MailArchiveEntry;
+import org.apache.james.mailbox.backup.MailArchiveIterator;
+import org.apache.james.mailbox.backup.MailboxWithAnnotationsArchiveEntry;
+import org.apache.james.mailbox.backup.SerializedMailboxId;
+import org.apache.james.mailbox.backup.UnknownArchiveEntry;
+import org.apache.james.mailbox.model.MailboxAnnotation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.github.fge.lambdas.Throwing;
+import com.google.common.collect.ImmutableList;
+
+public class ZippedMailAccountIterator implements MailArchiveIterator {
+    private static final Logger LOGGER = LoggerFactory.getLogger(ZippedMailAccountIterator.class);
+    private static final List<MailboxAnnotation> NO_ANNOTATION = ImmutableList.of();
+    private final ZipEntryIterator zipEntryIterator;
+    private Optional<MailboxWithAnnotationsArchiveEntry> currentMailBox;
+    private Optional<ZipEntry> next;
+
+    public ZippedMailAccountIterator(ZipEntryIterator zipEntryIterator) {
+        this.zipEntryIterator = zipEntryIterator;
+        next = Optional.ofNullable(zipEntryIterator.next());
+    }
+
+    @Override
+    public void close() throws IOException {
+        zipEntryIterator.close();
+    }
+
+    @Override
+    public boolean hasNext() {
+        return next.isPresent();
+    }
+
+    @Override
+    public MailArchiveEntry next() {
+        return next.map(this::doNext).orElseThrow(() -> new NoSuchElementException());
+    }
+
+    private MailArchiveEntry doNext(ZipEntry currentElement) {
+        next = Optional.ofNullable(zipEntryIterator.next());
+        try {
+            return getMailArchiveEntry(currentElement);
+        } catch (Exception e) {
+            LOGGER.error("Error when reading archive on entry : " + currentElement.getName(), e);
+            next = Optional.empty();
+            return new UnknownArchiveEntry(currentElement.getName());
+        }
+    }
+
+    private MailArchiveEntry getMailArchiveEntry(ZipEntry currentElement) throws Exception {
+        Optional<ZipEntryType> entryType = ExtraFieldExtractor.getEntryType(currentElement);
+        return entryType
+            .map(Throwing.<ZipEntryType, MailArchiveEntry>function(type ->
+                from(currentElement, type)).sneakyThrow()
+            )
+            .orElseGet(() -> new UnknownArchiveEntry(currentElement.getName()));
+    }
+
+    private Optional<SerializedMailboxId> getMailBoxId(ZipEntry entry) throws ZipException {
+        return ExtraFieldExtractor.getStringExtraField(MailboxIdExtraField.ID_AM, entry)
+            .map(SerializedMailboxId::new);
+    }
+
+    private String getMailboxName(ZipEntry current) {
+        return StringUtils.chop(current.getName());
+    }
+
+    private MailArchiveEntry fromMailboxEntry(ZipEntry current) throws ZipException {
+        return new MailboxWithAnnotationsArchiveEntry(getMailboxName(current), getMailBoxId(current).get(), NO_ANNOTATION);
+
+    }
+
+    private MailArchiveEntry from(ZipEntry current, ZipEntryType currentEntryType) throws ZipException {
+        switch (currentEntryType) {
+            case MAILBOX:
+                return fromMailboxEntry(current);
+            default:
+                return new UnknownArchiveEntry(current.getName());
+        }
+    }
+}
diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/Zipper.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/Zipper.java
index b0d2e63..0600b4b 100644
--- a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/Zipper.java
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/Zipper.java
@@ -47,7 +47,7 @@ import com.google.common.base.Charsets;
 
 public class Zipper implements ArchiveService {
 
-    private static final String ANNOTATION_DIRECTORY = "annotations";
+    public static final String ANNOTATION_DIRECTORY = "annotations";
     private static final boolean AUTO_FLUSH = true;
     private static final Logger LOGGER = LoggerFactory.getLogger(Zipper.class);
 
diff --git a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java
index 257a9f8..9be370a 100644
--- a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java
+++ b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java
@@ -51,6 +51,7 @@ public interface MailboxMessageFixture {
     String OTHER_USER = "otherUser";
 
     User USER1 = User.fromUsername(USER);
+    User USER2 = User.fromUsername(OTHER_USER);
 
     String DATE_STRING_1 = "2018-02-15T15:54:02Z";
     String DATE_STRING_2 = "2018-03-15T15:54:02Z";
@@ -60,16 +61,19 @@ public interface MailboxMessageFixture {
     MessageId.Factory MESSAGE_ID_FACTORY = new TestMessageId.Factory();
     Charset MESSAGE_CHARSET = StandardCharsets.UTF_8;
     String MESSAGE_CONTENT_1 = "Simple message content";
-    SharedByteArrayInputStream CONTENT_STREAM_1 = new SharedByteArrayInputStream(MESSAGE_CONTENT_1.getBytes(MESSAGE_CHARSET));
+    byte[] MESSAGE_CONTENT_BYTES_1 = MESSAGE_CONTENT_1.getBytes(MESSAGE_CHARSET);
+    SharedByteArrayInputStream CONTENT_STREAM_1 = new SharedByteArrayInputStream(MESSAGE_CONTENT_BYTES_1);
     String MESSAGE_CONTENT_2 = "Other message content";
-    SharedByteArrayInputStream CONTENT_STREAM_2 = new SharedByteArrayInputStream(MESSAGE_CONTENT_2.getBytes(MESSAGE_CHARSET));
+
+    byte[] MESSAGE_CONTENT_BYTES_2 = MESSAGE_CONTENT_2.getBytes(MESSAGE_CHARSET);
+    SharedByteArrayInputStream CONTENT_STREAM_2 = new SharedByteArrayInputStream(MESSAGE_CONTENT_BYTES_2);
     MessageId MESSAGE_ID_1 = MESSAGE_ID_FACTORY.generate();
     MessageId MESSAGE_ID_2 = MESSAGE_ID_FACTORY.generate();
 
     MessageId MESSAGE_ID_OTHER_USER_1 = MESSAGE_ID_FACTORY.generate();
 
-    long SIZE_1 = 1000;
-    long SIZE_2 = 2000;
+    long SIZE_1 = MESSAGE_CONTENT_BYTES_1.length;
+    long SIZE_2 = MESSAGE_CONTENT_BYTES_2.length;
     long MESSAGE_UID_1_VALUE = 1111L;
     long MESSAGE_UID_2_VALUE = 2222L;
     long MESSAGE_UID_OTHER_USER_1_VALUE = 1111L;
@@ -79,6 +83,10 @@ public interface MailboxMessageFixture {
     MailboxId MAILBOX_ID_1 = TestId.of(1L);
     MailboxId MAILBOX_ID_2 = TestId.of(2L);
     MailboxId MAILBOX_ID_11 = TestId.of(11L);
+
+    SerializedMailboxId SERIALIZED_MAILBOX_ID_1 = new SerializedMailboxId(MAILBOX_ID_1);
+    SerializedMailboxId SERIALIZED_MAILBOX_ID_2 = new SerializedMailboxId(MAILBOX_ID_2);
+
     Flags flags1 = new Flags("myFlags");
 
     MailboxSession MAILBOX_SESSION = MailboxSessionUtil.create(USER);
diff --git a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipArchivesLoaderTest.java b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipArchivesLoaderTest.java
new file mode 100644
index 0000000..a4054d3
--- /dev/null
+++ b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipArchivesLoaderTest.java
@@ -0,0 +1,151 @@
+/****************************************************************
+ * 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.backup;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.NoSuchElementException;
+
+import javax.mail.Flags;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MessageManager;
+import org.apache.james.mailbox.backup.zip.ZipArchivesLoader;
+import org.apache.james.mailbox.backup.zip.Zipper;
+import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
+import org.apache.james.mailbox.model.MailboxId;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import com.github.fge.lambdas.Throwing;
+
+public class ZipArchivesLoaderTest implements MailboxMessageFixture {
+    private static final int BUFFER_SIZE = 4096;
+
+    private final ArchiveService archiveService = new Zipper();
+    private final MailArchivesLoader archiveLoader = new ZipArchivesLoader();
+
+    private MailboxManager mailboxManager;
+    private DefaultMailboxBackup backup;
+
+    @BeforeEach
+    void beforeEach() {
+        mailboxManager = InMemoryIntegrationResources.defaultResources().getMailboxManager();
+        backup = new DefaultMailboxBackup(mailboxManager, archiveService);
+    }
+
+    private void createMailBoxWithMessage(MailboxSession session, MailboxPath mailboxPath, MailboxMessage... messages) throws Exception {
+        MailboxId mailboxId = mailboxManager.createMailbox(mailboxPath, session).get();
+        Arrays.stream(messages).forEach(Throwing.consumer(message ->
+            {
+                MessageManager.AppendCommand appendCommand = MessageManager.AppendCommand.builder()
+                    .withFlags(message.createFlags())
+                    .build(message.getFullContent());
+                mailboxManager.getMailbox(mailboxId, session).appendMessage(appendCommand, session);
+            }
+            )
+        );
+    }
+
+    @Test
+    void mailAccountIteratorFromEmptyArchiveShouldThrowNoSuchElementException() throws Exception {
+        ByteArrayOutputStream destination = new ByteArrayOutputStream(BUFFER_SIZE);
+        backup.backupAccount(USER1, destination);
+
+        InputStream source = new ByteArrayInputStream(destination.toByteArray());
+        MailArchiveIterator mailArchiveIterator = archiveLoader.load(source);
+
+        assertThat(mailArchiveIterator.hasNext()).isEqualTo(false);
+        assertThatThrownBy(() -> mailArchiveIterator.next()).isInstanceOf(NoSuchElementException.class);
+    }
+
+    @Test
+    void callingNextSeveralTimeOnAnEmptyIteratorShouldThrowNoSuchElementException()  throws Exception {
+        ByteArrayOutputStream destination = new ByteArrayOutputStream(BUFFER_SIZE);
+        backup.backupAccount(USER1, destination);
+
+        InputStream source = new ByteArrayInputStream(destination.toByteArray());
+        MailArchiveIterator mailArchiveIterator = archiveLoader.load(source);
+
+        assertThat(mailArchiveIterator.hasNext()).isEqualTo(false);
+        assertThatThrownBy(() -> mailArchiveIterator.next()).isInstanceOf(NoSuchElementException.class);
+        assertThatThrownBy(() -> mailArchiveIterator.next()).isInstanceOf(NoSuchElementException.class);
+        assertThatThrownBy(() -> mailArchiveIterator.next()).isInstanceOf(NoSuchElementException.class);
+    }
+
+    @Test
+    void mailAccountIteratorFromArchiveWithOneMailboxShouldContainOneMailbox() throws Exception {
+        MailboxSession session = mailboxManager.createSystemSession(USER);
+        createMailBoxWithMessage(session, MAILBOX_PATH_USER1_MAILBOX1);
+
+        ByteArrayOutputStream destination = new ByteArrayOutputStream(BUFFER_SIZE);
+        backup.backupAccount(USER1, destination);
+
+        InputStream source = new ByteArrayInputStream(destination.toByteArray());
+        MailArchiveIterator mailArchiveIterator = archiveLoader.load(source);
+        assertThat(mailArchiveIterator.hasNext()).isEqualTo(true);
+
+        MailboxWithAnnotationsArchiveEntry expectedMailbox = new MailboxWithAnnotationsArchiveEntry(MAILBOX_1_NAME, SERIALIZED_MAILBOX_ID_1, NO_ANNOTATION);
+        MailboxWithAnnotationsArchiveEntry resultMailbox = (MailboxWithAnnotationsArchiveEntry) mailArchiveIterator.next();
+        verifyMailboxArchiveEntry(mailArchiveIterator, expectedMailbox, resultMailbox, false);
+    }
+
+    @Test
+    void mailAccountIteratorFromArchiveWithTwoMailboxesShouldContainTwoMailboxes() throws Exception {
+        MailboxSession session = mailboxManager.createSystemSession(USER);
+        createMailBoxWithMessage(session, MAILBOX_PATH_USER1_MAILBOX1);
+        createMailBoxWithMessage(session, MAILBOX_PATH_USER1_MAILBOX2);
+
+        ByteArrayOutputStream destination = new ByteArrayOutputStream(BUFFER_SIZE);
+        backup.backupAccount(USER1, destination);
+
+        InputStream source = new ByteArrayInputStream(destination.toByteArray());
+        MailArchiveIterator mailArchiveIterator = archiveLoader.load(source);
+        assertThat(mailArchiveIterator.hasNext()).isEqualTo(true);
+
+        MailboxWithAnnotationsArchiveEntry expectedMailbox = new MailboxWithAnnotationsArchiveEntry(MAILBOX_1_NAME, SERIALIZED_MAILBOX_ID_1, NO_ANNOTATION);
+        MailboxWithAnnotationsArchiveEntry resultMailbox = (MailboxWithAnnotationsArchiveEntry) mailArchiveIterator.next();
+        verifyMailboxArchiveEntry(mailArchiveIterator, expectedMailbox, resultMailbox, true);
+
+        MailboxWithAnnotationsArchiveEntry expectedSecondMailbox = new MailboxWithAnnotationsArchiveEntry(MAILBOX_2_NAME, SERIALIZED_MAILBOX_ID_2, NO_ANNOTATION);
+        MailboxWithAnnotationsArchiveEntry resultSecondMailbox = (MailboxWithAnnotationsArchiveEntry) mailArchiveIterator.next();
+        verifyMailboxArchiveEntry(mailArchiveIterator, expectedSecondMailbox, resultSecondMailbox, false);
+    }
+
+    private void verifyMailboxArchiveEntry(MailArchiveIterator mailArchiveIterator, MailboxWithAnnotationsArchiveEntry expectedMailbox,
+                                           MailboxWithAnnotationsArchiveEntry resultMailbox, boolean iteratorHasNextElement) {
+        assertThat(resultMailbox.getMailboxId()).isEqualTo(expectedMailbox.getMailboxId());
+        assertThat(resultMailbox.getMailboxName()).isEqualTo(expectedMailbox.getMailboxName());
+        assertThat(resultMailbox.getAnnotations()).isEqualTo(expectedMailbox.getAnnotations());
+        assertThat(resultMailbox).isEqualTo(expectedMailbox);
+        assertThat(mailArchiveIterator.hasNext()).isEqualTo(iteratorHasNextElement);
+    }
+
+}


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


[james-project] 02/06: JAMES-2746 extract QuotaLoader from MailboxFactory

Posted by ro...@apache.org.
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 3897673e44bf72a334947d7099bb7631ddbcbea3
Author: Rémi Kowalski <rk...@linagora.com>
AuthorDate: Tue Apr 30 16:31:56 2019 +0200

    JAMES-2746 extract QuotaLoader from MailboxFactory
---
 .../james/jmap/methods/GetMailboxesMethod.java     | 31 +++++----
 .../apache/james/jmap/model/MailboxFactory.java    | 79 +++++----------------
 .../jmap/utils/quotas/DefaultQuotaLoader.java      | 52 ++++++++++++++
 .../james/jmap/utils/quotas/QuotaLoader.java       | 50 ++++++++++++++
 .../quotas/QuotaLoaderWithDefaultPreloaded.java    | 80 ++++++++++++++++++++++
 .../james/jmap/methods/GetMailboxesMethodTest.java | 31 +++++----
 .../james/jmap/model/MailboxFactoryTest.java       |  2 +
 7 files changed, 237 insertions(+), 88 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 ab22edc..485d364 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,13 +33,16 @@ 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.jmap.utils.quotas.QuotaLoader;
+import org.apache.james.jmap.utils.quotas.QuotaLoaderWithDefaultPreloaded;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxMetaData;
 import org.apache.james.mailbox.model.search.MailboxQuery;
+import org.apache.james.mailbox.quota.QuotaManager;
+import org.apache.james.mailbox.quota.QuotaRootResolver;
 import org.apache.james.metrics.api.MetricFactory;
 import org.apache.james.util.MDCBuilder;
 import org.apache.james.util.OptionalUtils;
@@ -57,17 +60,21 @@ 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 MailboxManager mailboxManager;
     private final MailboxFactory mailboxFactory;
     private final MetricFactory metricFactory;
+    private final QuotaRootResolver quotaRootResolver;
+    private final QuotaManager quotaManager;
 
     @Inject
-    @VisibleForTesting public GetMailboxesMethod(MailboxManager mailboxManager, MailboxFactory mailboxFactory, MetricFactory metricFactory) {
+    @VisibleForTesting
+    public GetMailboxesMethod(MailboxManager mailboxManager, QuotaRootResolver quotaRootResolver, QuotaManager quotaManager, MailboxFactory mailboxFactory, MetricFactory metricFactory) {
         this.mailboxManager = mailboxManager;
         this.mailboxFactory = mailboxFactory;
         this.metricFactory = metricFactory;
+        this.quotaRootResolver = quotaRootResolver;
+        this.quotaManager = quotaManager;
     }
 
     @Override
@@ -126,15 +133,13 @@ public class GetMailboxesMethod implements Method {
     }
 
 
-
     private Stream<Mailbox> retrieveSpecificMailboxes(MailboxSession mailboxSession, ImmutableList<MailboxId> mailboxIds) {
         return mailboxIds
             .stream()
-            .map(mailboxId ->  mailboxFactory.builder()
+            .map(mailboxId -> mailboxFactory.builder()
                 .id(mailboxId)
                 .session(mailboxSession)
                 .usingPreloadedMailboxesMetadata(NO_PRELOADED_METADATA)
-                .usingPreloadedUserDefaultQuotas(NO_PRELOADED_QUOTAS)
                 .build()
             )
             .flatMap(OptionalUtils::toStream);
@@ -142,7 +147,7 @@ public class GetMailboxesMethod implements Method {
 
     private Stream<Mailbox> retrieveAllMailboxes(MailboxSession mailboxSession) throws MailboxException {
         List<MailboxMetaData> userMailboxes = getAllMailboxesMetaData(mailboxSession);
-        Quotas mailboxQuotas =  mailboxFactory.getUserDefaultQuotas(mailboxSession);
+        QuotaLoader quotaLoader = new QuotaLoaderWithDefaultPreloaded(quotaRootResolver, quotaManager, mailboxSession);
 
         return userMailboxes
             .stream()
@@ -151,17 +156,17 @@ public class GetMailboxesMethod implements Method {
                 .id(mailboxId)
                 .session(mailboxSession)
                 .usingPreloadedMailboxesMetadata(Optional.of(userMailboxes))
-                .usingPreloadedUserDefaultQuotas(Optional.of(mailboxQuotas))
+                .quotaLoader(quotaLoader)
                 .build())
             .flatMap(OptionalUtils::toStream);
     }
 
     private List<MailboxMetaData> getAllMailboxesMetaData(MailboxSession mailboxSession) throws MailboxException {
         return mailboxManager.search(
-                MailboxQuery.builder()
-                    .matchesAllMailboxNames()
-                    .build(),
-                mailboxSession);
+            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 d2506fb..2e88972 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
@@ -23,14 +23,14 @@ import java.util.Optional;
 
 import javax.inject.Inject;
 
-import org.apache.james.core.quota.QuotaValue;
 import org.apache.james.jmap.model.mailbox.Mailbox;
 import org.apache.james.jmap.model.mailbox.MailboxNamespace;
 import org.apache.james.jmap.model.mailbox.Quotas;
-import org.apache.james.jmap.model.mailbox.Quotas.QuotaId;
 import org.apache.james.jmap.model.mailbox.Rights;
 import org.apache.james.jmap.model.mailbox.Rights.Username;
 import org.apache.james.jmap.model.mailbox.SortOrder;
+import org.apache.james.jmap.utils.quotas.DefaultQuotaLoader;
+import org.apache.james.jmap.utils.quotas.QuotaLoader;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.MessageManager;
@@ -41,8 +41,6 @@ import org.apache.james.mailbox.model.MailboxCounters;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxMetaData;
 import org.apache.james.mailbox.model.MailboxPath;
-import org.apache.james.mailbox.model.Quota;
-import org.apache.james.mailbox.model.QuotaRoot;
 import org.apache.james.mailbox.quota.QuotaManager;
 import org.apache.james.mailbox.quota.QuotaRootResolver;
 
@@ -57,13 +55,14 @@ public class MailboxFactory {
 
     public static class MailboxBuilder {
         private final MailboxFactory mailboxFactory;
+        private QuotaLoader quotaLoader;
         private MailboxSession session;
         private MailboxId id;
         private Optional<List<MailboxMetaData>> userMailboxesMetadata = Optional.empty();
-        private Optional<Quotas> preloadedUserDefaultQuotas = Optional.empty();
 
-        private MailboxBuilder(MailboxFactory mailboxFactory) {
+        private MailboxBuilder(MailboxFactory mailboxFactory, QuotaLoader quotaLoader) {
             this.mailboxFactory = mailboxFactory;
+            this.quotaLoader = quotaLoader;
         }
 
         public MailboxBuilder id(MailboxId id) {
@@ -76,13 +75,13 @@ public class MailboxFactory {
             return this;
         }
 
-        public MailboxBuilder usingPreloadedMailboxesMetadata(Optional<List<MailboxMetaData>> userMailboxesMetadata) {
-            this.userMailboxesMetadata = userMailboxesMetadata;
+        public MailboxBuilder quotaLoader(QuotaLoader quotaLoader) {
+            this.quotaLoader = quotaLoader;
             return this;
         }
 
-        public MailboxBuilder usingPreloadedUserDefaultQuotas(Optional<Quotas> preloadedUserDefaultQuotas) {
-            this.preloadedUserDefaultQuotas = preloadedUserDefaultQuotas;
+        public MailboxBuilder usingPreloadedMailboxesMetadata(Optional<List<MailboxMetaData>> userMailboxesMetadata) {
+            this.userMailboxesMetadata = userMailboxesMetadata;
             return this;
         }
 
@@ -92,7 +91,7 @@ public class MailboxFactory {
 
             try {
                 MessageManager mailbox = mailboxFactory.mailboxManager.getMailbox(id, session);
-                return Optional.of(mailboxFactory.fromMessageManager(mailbox, userMailboxesMetadata, preloadedUserDefaultQuotas, session));
+                return Optional.of(mailboxFactory.fromMessageManager(mailbox, userMailboxesMetadata, quotaLoader, session));
             } catch (MailboxNotFoundException e) {
                 return Optional.empty();
             } catch (MailboxException e) {
@@ -109,12 +108,13 @@ public class MailboxFactory {
     }
 
     public MailboxBuilder builder() {
-        return new MailboxBuilder(this);
+        QuotaLoader defaultQuotaLoader = new DefaultQuotaLoader(quotaRootResolver, quotaManager);
+        return new MailboxBuilder(this, defaultQuotaLoader);
     }
 
     private Mailbox fromMessageManager(MessageManager messageManager,
                                        Optional<List<MailboxMetaData>> userMailboxesMetadata,
-                                       Optional<Quotas> preloadedDefaultUserQuotas,
+                                       QuotaLoader quotaLoader,
                                        MailboxSession mailboxSession) throws MailboxException {
         MailboxPath mailboxPath = messageManager.getMailboxPath();
         boolean isOwner = mailboxPath.belongsTo(mailboxSession);
@@ -125,7 +125,7 @@ public class MailboxFactory {
             .removeEntriesFor(Username.forMailboxPath(mailboxPath));
         Username username = Username.fromSession(mailboxSession);
 
-        Quotas quotas = getQuotas(mailboxPath, preloadedDefaultUserQuotas);
+        Quotas quotas = quotaLoader.getQuotas(mailboxPath);
 
         return Mailbox.builder()
             .id(messageManager.getId())
@@ -147,49 +147,6 @@ public class MailboxFactory {
             .build();
     }
 
-    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,
-            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()),
-                quotaValueToOptionalNumber(quota.getLimit()));
-    }
-
-    private Number quotaValueToNumber(QuotaValue<?> value) {
-        return Number.BOUND_SANITIZING_FACTORY.from(value.asLong());
-    }
-
-    private Optional<Number> quotaValueToOptionalNumber(QuotaValue<?> value) {
-        if (value.isUnlimited()) {
-            return Optional.empty();
-        }
-        return Optional.of(quotaValueToNumber(value));
-    }
-
     private MailboxNamespace getNamespace(MailboxPath mailboxPath, boolean isOwner) {
         if (isOwner) {
             return MailboxNamespace.personal();
@@ -197,7 +154,8 @@ public class MailboxFactory {
         return MailboxNamespace.delegated(mailboxPath.getUser());
     }
 
-    @VisibleForTesting String getName(MailboxPath mailboxPath, MailboxSession mailboxSession) {
+    @VisibleForTesting
+    String getName(MailboxPath mailboxPath, MailboxSession mailboxSession) {
         String name = mailboxPath.getName();
         if (name.contains(String.valueOf(mailboxSession.getPathDelimiter()))) {
             List<String> levels = Splitter.on(mailboxSession.getPathDelimiter()).splitToList(name);
@@ -206,8 +164,9 @@ public class MailboxFactory {
         return name;
     }
 
-    @VisibleForTesting Optional<MailboxId> getParentIdFromMailboxPath(MailboxPath mailboxPath, Optional<List<MailboxMetaData>> userMailboxesMetadata,
-                                                                      MailboxSession mailboxSession) throws MailboxException {
+    @VisibleForTesting
+    Optional<MailboxId> getParentIdFromMailboxPath(MailboxPath mailboxPath, Optional<List<MailboxMetaData>> userMailboxesMetadata,
+                                                   MailboxSession mailboxSession) throws MailboxException {
         List<MailboxPath> levels = mailboxPath.getHierarchyLevels(mailboxSession.getPathDelimiter());
         if (levels.size() <= 1) {
             return Optional.empty();
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/quotas/DefaultQuotaLoader.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/quotas/DefaultQuotaLoader.java
new file mode 100644
index 0000000..816d7cb
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/quotas/DefaultQuotaLoader.java
@@ -0,0 +1,52 @@
+/****************************************************************
+ * 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.utils.quotas;
+
+import javax.inject.Inject;
+
+import org.apache.james.jmap.model.mailbox.Quotas;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.QuotaRoot;
+import org.apache.james.mailbox.quota.QuotaManager;
+import org.apache.james.mailbox.quota.QuotaRootResolver;
+
+public class DefaultQuotaLoader extends QuotaLoader {
+
+    private final QuotaRootResolver quotaRootResolver;
+    private final QuotaManager quotaManager;
+
+    @Inject
+    public DefaultQuotaLoader(QuotaRootResolver quotaRootResolver, QuotaManager quotaManager) {
+        this.quotaRootResolver = quotaRootResolver;
+        this.quotaManager = quotaManager;
+    }
+
+    public Quotas getQuotas(MailboxPath mailboxPath) throws MailboxException {
+        QuotaRoot quotaRoot = quotaRootResolver.getQuotaRoot(mailboxPath);
+        Quotas.QuotaId quotaId = Quotas.QuotaId.fromQuotaRoot(quotaRoot);
+
+        return Quotas.from(
+            quotaId,
+            Quotas.Quota.from(
+                quotaToValue(quotaManager.getStorageQuota(quotaRoot)),
+                quotaToValue(quotaManager.getMessageQuota(quotaRoot))));
+    }
+
+}
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/quotas/QuotaLoader.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/quotas/QuotaLoader.java
new file mode 100644
index 0000000..2d16844
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/quotas/QuotaLoader.java
@@ -0,0 +1,50 @@
+/****************************************************************
+ * 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.utils.quotas;
+
+import java.util.Optional;
+
+import org.apache.james.core.quota.QuotaValue;
+import org.apache.james.jmap.model.Number;
+import org.apache.james.jmap.model.mailbox.Quotas;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.Quota;
+
+public abstract class QuotaLoader {
+
+    public abstract Quotas getQuotas(MailboxPath mailboxPath) throws MailboxException;
+
+    protected <T extends QuotaValue<T>> Quotas.Value<T> quotaToValue(Quota<T> quota) {
+        return new Quotas.Value<>(
+            quotaValueToNumber(quota.getUsed()),
+            quotaValueToOptionalNumber(quota.getLimit()));
+    }
+
+    protected Number quotaValueToNumber(QuotaValue<?> value) {
+        return Number.BOUND_SANITIZING_FACTORY.from(value.asLong());
+    }
+
+    protected Optional<Number> quotaValueToOptionalNumber(QuotaValue<?> value) {
+        if (value.isUnlimited()) {
+            return Optional.empty();
+        }
+        return Optional.of(quotaValueToNumber(value));
+    }
+}
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/quotas/QuotaLoaderWithDefaultPreloaded.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/quotas/QuotaLoaderWithDefaultPreloaded.java
new file mode 100644
index 0000000..abbda4f
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/quotas/QuotaLoaderWithDefaultPreloaded.java
@@ -0,0 +1,80 @@
+/****************************************************************
+ * 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.utils.quotas;
+
+import java.util.Optional;
+
+import org.apache.james.jmap.model.mailbox.Quotas;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.QuotaRoot;
+import org.apache.james.mailbox.quota.QuotaManager;
+import org.apache.james.mailbox.quota.QuotaRootResolver;
+
+public class QuotaLoaderWithDefaultPreloaded extends QuotaLoader {
+
+    private final QuotaRootResolver quotaRootResolver;
+    private final QuotaManager quotaManager;
+    private final Optional<Quotas> preloadedUserDefaultQuotas;
+    private final MailboxSession session;
+
+    public QuotaLoaderWithDefaultPreloaded(QuotaRootResolver quotaRootResolver,
+                                           QuotaManager quotaManager,
+                                           MailboxSession session) throws MailboxException {
+        this.quotaRootResolver = quotaRootResolver;
+        this.quotaManager = quotaManager;
+        this.session = session;
+        preloadedUserDefaultQuotas = Optional.of(getUserDefaultQuotas());
+
+    }
+
+    public Quotas getQuotas(MailboxPath mailboxPath) throws MailboxException {
+        QuotaRoot quotaRoot = quotaRootResolver.getQuotaRoot(mailboxPath);
+        Quotas.QuotaId quotaId = Quotas.QuotaId.fromQuotaRoot(quotaRoot);
+
+        if (containsQuotaId(preloadedUserDefaultQuotas, quotaId)) {
+            return preloadedUserDefaultQuotas.get();
+        }
+        return Quotas.from(
+            quotaId,
+            Quotas.Quota.from(
+                quotaToValue(quotaManager.getStorageQuota(quotaRoot)),
+                quotaToValue(quotaManager.getMessageQuota(quotaRoot))));
+    }
+
+    private boolean containsQuotaId(Optional<Quotas> preloadedUserDefaultQuotas, Quotas.QuotaId quotaId) {
+        return preloadedUserDefaultQuotas
+            .map(Quotas::getQuotas)
+            .map(quotaIdQuotaMap -> quotaIdQuotaMap.containsKey(quotaId))
+            .orElse(false);
+    }
+
+    private Quotas getUserDefaultQuotas() throws MailboxException {
+        QuotaRoot quotaRoot = quotaRootResolver.getQuotaRoot(MailboxPath.inbox(session));
+        Quotas.QuotaId quotaId = Quotas.QuotaId.fromQuotaRoot(quotaRoot);
+        return Quotas.from(
+            quotaId,
+            Quotas.Quota.from(
+                quotaToValue(quotaManager.getStorageQuota(quotaRoot)),
+                quotaToValue(quotaManager.getMessageQuota(quotaRoot))));
+
+    }
+
+}
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/GetMailboxesMethodTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/GetMailboxesMethodTest.java
index 3f53967..8a20c6c 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/GetMailboxesMethodTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/GetMailboxesMethodTest.java
@@ -37,7 +37,6 @@ import org.apache.james.jmap.model.MailboxFactory;
 import org.apache.james.jmap.model.Number;
 import org.apache.james.jmap.model.mailbox.Mailbox;
 import org.apache.james.jmap.model.mailbox.SortOrder;
-import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.MailboxSessionUtil;
 import org.apache.james.mailbox.MessageManager;
@@ -67,15 +66,17 @@ public class GetMailboxesMethodTest {
     private ClientId clientId;
     private MailboxFactory mailboxFactory;
 
+    private QuotaRootResolver quotaRootResolver;
+    private QuotaManager quotaManager;
     @Before
     public void setup() throws Exception {
         clientId = ClientId.of("#0");
         mailboxManager = InMemoryIntegrationResources.defaultResources().getMailboxManager();
-        QuotaRootResolver quotaRootResolver = mailboxManager.getQuotaComponents().getQuotaRootResolver();
-        QuotaManager quotaManager = mailboxManager.getQuotaComponents().getQuotaManager();
+        quotaRootResolver = mailboxManager.getQuotaComponents().getQuotaRootResolver();
+        quotaManager = mailboxManager.getQuotaComponents().getQuotaManager();
         mailboxFactory = new MailboxFactory(mailboxManager, quotaManager, quotaRootResolver);
 
-        getMailboxesMethod = new GetMailboxesMethod(mailboxManager, mailboxFactory, new DefaultMetricFactory());
+        getMailboxesMethod = new GetMailboxesMethod(mailboxManager, quotaRootResolver, quotaManager,  mailboxFactory, new DefaultMetricFactory());
     }
 
     @Test
@@ -84,9 +85,9 @@ public class GetMailboxesMethodTest {
                 .build();
 
         MailboxSession mailboxSession = mailboxManager.createSystemSession(USERNAME);
-        
+
         List<JmapResponse> getMailboxesResponse = getMailboxesMethod.process(getMailboxesRequest, clientId, mailboxSession).collect(Collectors.toList());
-        
+
         assertThat(getMailboxesResponse)
                 .hasSize(1)
                 .extracting(JmapResponse::getResponse)
@@ -95,22 +96,22 @@ public class GetMailboxesMethodTest {
                 .flatExtracting(GetMailboxesResponse::getList)
                 .isEmpty();
     }
-    
+
     @Test
     public void getMailboxesShouldNotFailWhenMailboxManagerErrors() throws Exception {
-        MailboxManager mockedMailboxManager = mock(MailboxManager.class);
+        StoreMailboxManager mockedMailboxManager = mock(StoreMailboxManager.class);
         when(mockedMailboxManager.list(any()))
             .thenReturn(ImmutableList.of(new MailboxPath("namespace", "user", "name")));
         when(mockedMailboxManager.getMailbox(any(MailboxPath.class), any()))
             .thenThrow(new MailboxException());
-        GetMailboxesMethod testee = new GetMailboxesMethod(mockedMailboxManager, mailboxFactory, new DefaultMetricFactory());
-        
+        GetMailboxesMethod testee = new GetMailboxesMethod(mockedMailboxManager, quotaRootResolver, quotaManager, mailboxFactory, new DefaultMetricFactory());
+
         GetMailboxesRequest getMailboxesRequest = GetMailboxesRequest.builder()
                 .build();
         MailboxSession session = MailboxSessionUtil.create(USERNAME);
-        
+
         List<JmapResponse> getMailboxesResponse = testee.process(getMailboxesRequest, clientId, session).collect(Collectors.toList());
-        
+
         assertThat(getMailboxesResponse)
                 .hasSize(1)
                 .extracting(JmapResponse::getResponse)
@@ -140,7 +141,7 @@ public class GetMailboxesMethodTest {
                 .build();
 
         List<JmapResponse> getMailboxesResponse = getMailboxesMethod.process(getMailboxesRequest, clientId, mailboxSession).collect(Collectors.toList());
-        
+
         assertThat(getMailboxesResponse)
                 .hasSize(1)
                 .extracting(JmapResponse::getResponse)
@@ -165,7 +166,7 @@ public class GetMailboxesMethodTest {
                 .build();
 
         List<JmapResponse> getMailboxesResponse = getMailboxesMethod.process(getMailboxesRequest, clientId, userSession).collect(Collectors.toList());
-        
+
         assertThat(getMailboxesResponse)
                 .hasSize(1)
                 .extracting(JmapResponse::getResponse)
@@ -379,7 +380,7 @@ public class GetMailboxesMethodTest {
         mailboxManager.createMailbox(MailboxPath.forUser(USERNAME, "Spam"), mailboxSession);
         mailboxManager.createMailbox(MailboxPath.forUser(USERNAME, "Templates"), mailboxSession);
         mailboxManager.createMailbox(MailboxPath.forUser(USERNAME, "WITHOUT ROLE"), mailboxSession);
-        
+
         GetMailboxesRequest getMailboxesRequest = GetMailboxesRequest.builder()
                 .build();
 
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MailboxFactoryTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MailboxFactoryTest.java
index 34e8e34..cdbaa54 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MailboxFactoryTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/MailboxFactoryTest.java
@@ -24,6 +24,8 @@ import java.util.Optional;
 
 import org.apache.james.jmap.model.mailbox.Mailbox;
 import org.apache.james.jmap.model.mailbox.MailboxNamespace;
+import org.apache.james.jmap.utils.quotas.DefaultQuotaLoader;
+import org.apache.james.jmap.utils.quotas.QuotaLoader;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.inmemory.InMemoryId;
 import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;


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


[james-project] 06/06: JAMES-2694 add package info for zip archive

Posted by ro...@apache.org.
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 0bb1bc6ce4e0b029cc8273acaff2ef7ae2bb8eb1
Author: Rémi Kowalski <rk...@linagora.com>
AuthorDate: Thu Apr 18 16:10:30 2019 +0200

    JAMES-2694 add package info for zip archive
---
 .../james/mailbox/backup/zip/package-info.java     | 52 ++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/package-info.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/package-info.java
new file mode 100644
index 0000000..151d562
--- /dev/null
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/package-info.java
@@ -0,0 +1,52 @@
+/****************************************************************
+ * 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.                                           *
+ ****************************************************************/
+
+/**
+ *  The zip archive format for the backup of an account
+ *
+ *  This archive contains the mailboxes of the account. And for each mailbox :
+ *   - its annotations
+ *   - its messages
+ *
+ *  This structure is repeated sequentially for each mailbox.
+ *  The order presented here is the order in which the entries are added to the zip file.
+ *  This is important and must be respected because during the restoration, the file is read iteratively in memory from an inputstream,
+ *  without storing the whole structure on memory nor on disk.
+ *
+ *  So we have by order of insertion mailbox1 followed by it's elements then mailbox2 and its elements ...
+ *
+ *  This archive contains the following entries for each mailbox of the user :
+ *<ul>
+ * <li><b>'mailboxName/'</b> : directory entry</li>
+ * <li>'mailboxName/annotations/' : directory entry, optional. Is present only if the mailbox contains some annotations</li>
+ * <li>'mailboxName/annotations/annotation1Key' : file entry which name is the key of the annotation,
+ *                                              the content of the annotation is stored in the content of the file</li>
+ * <li>'mailboxName/annotations/annotation2Key' : idem a mailbox may contains several annotations</li>
+ * <li>'messageId1' : file entry which name is the serialized {@link org.apache.james.mailbox.model.MessageId} of the message,
+ *                  the raw RFC822 message is stored in the content of the file</li>
+ * <li>'messageId2' : a mailbox may contains several messages.</li>
+ * <li><b>mailbox2Name</b></li>
+ * <li>...</li>
+ *</ul>
+ *
+ *
+ * @see the unit test {@link= org.apache.james.mailbox.backup.ZipperTest} for more information about this format
+ *
+ */
+package org.apache.james.mailbox.backup.zip;
\ No newline at end of file


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


[james-project] 05/06: JAMES-2694 shoud not restore in non empty account

Posted by ro...@apache.org.
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 57ce846b5be7a84dc0333339f2d76e51e328ed37
Author: Rémi Kowalski <rk...@linagora.com>
AuthorDate: Tue Apr 9 11:46:14 2019 +0200

    JAMES-2694 shoud not restore in non empty account
---
 .../james/mailbox/backup/DefaultMailboxBackup.java | 27 ++++++++++++---
 .../apache/james/mailbox/backup/MailboxBackup.java | 10 ++++--
 .../mailbox/backup/DefaultMailboxBackupTest.java   | 38 +++++++++++++++-------
 3 files changed, 58 insertions(+), 17 deletions(-)

diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/DefaultMailboxBackup.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/DefaultMailboxBackup.java
index 0496b40..355ec7e 100644
--- a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/DefaultMailboxBackup.java
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/DefaultMailboxBackup.java
@@ -28,6 +28,7 @@ import org.apache.james.core.User;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.MessageManager;
+import org.apache.james.mailbox.exception.BadCredentialsException;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.FetchGroupImpl;
 import org.apache.james.mailbox.model.Mailbox;
@@ -93,13 +94,31 @@ public class DefaultMailboxBackup implements MailboxBackup {
         archive(mailboxes, messages, destination);
     }
 
+    private boolean isAccountNonEmpty(User user) throws BadCredentialsException, MailboxException, IOException {
+        MailboxSession session = mailboxManager.createSystemSession(user.asString());
+        return getAccountContentForUser(session)
+            .stream()
+            .findFirst()
+            .isPresent();
+    }
+
     @Override
-    public Publisher<Void> restore(User user, InputStream source) {
-        return Mono.fromRunnable(Throwing.runnable(() -> archiveRestorer.restore(user, source)))
+    public Publisher<BackupStatus> restore(User user, InputStream source) {
+        try {
+            if (isAccountNonEmpty(user)) {
+                return Mono.just(BackupStatus.NON_EMPTY_RECEIVER_ACCOUNT);
+            }
+        } catch (Exception e) {
+            LOGGER.error("Error during account restoration for user : " + user, e);
+            return Mono.just(BackupStatus.FAILED);
+        }
+
+        return Mono.fromRunnable(Throwing.runnable(() -> archiveRestorer.restore(user, source)).sneakyThrow())
             .subscribeOn(Schedulers.elastic())
             .doOnError(e -> LOGGER.error("Error during account restoration for user : " + user, e))
-            .doOnTerminate(Throwing.runnable(source::close))
-            .then();
+            .doOnTerminate(Throwing.runnable(source::close).sneakyThrow())
+            .thenReturn(BackupStatus.DONE)
+            .onErrorReturn(BackupStatus.FAILED);
     }
 
     private Stream<MailAccountContent> getMailboxWithAnnotationsFromPath(MailboxSession session, MailboxPath path) {
diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailboxBackup.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailboxBackup.java
index 5f837b2..4770eed 100644
--- a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailboxBackup.java
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailboxBackup.java
@@ -28,16 +28,22 @@ import org.reactivestreams.Publisher;
 
 public interface MailboxBackup {
 
+    enum BackupStatus {
+        NON_EMPTY_RECEIVER_ACCOUNT,
+        FAILED,
+        DONE
+    }
+
     /**
      * @param user the user account to export
      */
     void backupAccount(User user, OutputStream destination) throws IOException, MailboxException;
 
     /**
-     * @param user the user in which account the restored elements will be stored.
+     * @param user   the user in which account the restored elements will be stored.
      * @param source the input stream to the archive containing the account elements.
      * @return a Publisher indicating when the action is completed
      */
-    Publisher<Void> restore(User user, InputStream source) throws IOException, MailboxException;
+    Publisher<BackupStatus> restore(User user, InputStream source) throws IOException, MailboxException;
 
 }
diff --git a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/DefaultMailboxBackupTest.java b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/DefaultMailboxBackupTest.java
index d1eff05..58f4958 100644
--- a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/DefaultMailboxBackupTest.java
+++ b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/DefaultMailboxBackupTest.java
@@ -66,7 +66,7 @@ class DefaultMailboxBackupTest implements MailboxMessageFixture {
         sessionOtherUser = mailboxManager.createSystemSession(OTHER_USER);
     }
 
-    private void createMailBoxWithMessages(MailboxSession session, MailboxPath mailboxPath, MessageManager.AppendCommand... messages) throws Exception {
+    private void createMailboxWithMessages(MailboxSession session, MailboxPath mailboxPath, MessageManager.AppendCommand... messages) throws Exception {
         MailboxId mailboxId = mailboxManager.createMailbox(mailboxPath, session).get();
         Arrays.stream(messages).forEach(Throwing.consumer(message ->
                 mailboxManager.getMailbox(mailboxId, session).appendMessage(message, session)
@@ -75,7 +75,7 @@ class DefaultMailboxBackupTest implements MailboxMessageFixture {
     }
 
     private void createMailbox(MailboxSession session, MailboxPath mailboxPath) throws Exception {
-        createMailBoxWithMessages(session, mailboxPath);
+        createMailboxWithMessages(session, mailboxPath);
     }
 
     @Test
@@ -116,7 +116,7 @@ class DefaultMailboxBackupTest implements MailboxMessageFixture {
     @Test
     void doBackupWithOneMessageShouldStoreAnArchiveWithTwoEntries() throws Exception {
         ByteArrayOutputStream destination = new ByteArrayOutputStream(BUFFER_SIZE);
-        createMailBoxWithMessages(sessionUser, MAILBOX_PATH_USER1_MAILBOX1, getMessage1AppendCommand());
+        createMailboxWithMessages(sessionUser, MAILBOX_PATH_USER1_MAILBOX1, getMessage1AppendCommand());
 
         backup.backupAccount(USER1, destination);
 
@@ -131,7 +131,7 @@ class DefaultMailboxBackupTest implements MailboxMessageFixture {
     @Test
     void doBackupWithTwoMailboxesAndOneMessageShouldStoreAnArchiveWithThreeEntries() throws Exception {
         ByteArrayOutputStream destination = new ByteArrayOutputStream(BUFFER_SIZE);
-        createMailBoxWithMessages(sessionUser, MAILBOX_PATH_USER1_MAILBOX1, getMessage1AppendCommand());
+        createMailboxWithMessages(sessionUser, MAILBOX_PATH_USER1_MAILBOX1, getMessage1AppendCommand());
         createMailbox(sessionUser, MAILBOX_PATH_USER1_MAILBOX2);
 
         backup.backupAccount(USER1, destination);
@@ -149,8 +149,8 @@ class DefaultMailboxBackupTest implements MailboxMessageFixture {
     void doBackupShouldOnlyArchiveTheMailboxOfTheUser() throws Exception {
         ByteArrayOutputStream destination = new ByteArrayOutputStream(BUFFER_SIZE);
 
-        createMailBoxWithMessages(sessionUser, MAILBOX_PATH_USER1_MAILBOX1, getMessage1AppendCommand());
-        createMailBoxWithMessages(sessionOtherUser, MAILBOX_PATH_OTHER_USER_MAILBOX1, getMessage1OtherUserAppendCommand());
+        createMailboxWithMessages(sessionUser, MAILBOX_PATH_USER1_MAILBOX1, getMessage1AppendCommand());
+        createMailboxWithMessages(sessionOtherUser, MAILBOX_PATH_OTHER_USER_MAILBOX1, getMessage1OtherUserAppendCommand());
 
         backup.backupAccount(USER1, destination);
         try (ZipAssert zipAssert = ZipAssert.assertThatZip(destination)) {
@@ -167,8 +167,8 @@ class DefaultMailboxBackupTest implements MailboxMessageFixture {
         backup.backupAccount(USER1, destination);
 
         InputStream source = new ByteArrayInputStream(destination.toByteArray());
-        Mono.from(backup.restore(USER2, source)).block();
-
+        MailboxBackup.BackupStatus backupStatus = Mono.from(backup.restore(USER2, source)).block();
+        assertThat(backupStatus).isEqualTo(MailboxBackup.BackupStatus.DONE);
         List<DefaultMailboxBackup.MailAccountContent> content = backup.getAccountContentForUser(sessionOtherUser);
 
         assertThat(content).isEmpty();
@@ -182,7 +182,8 @@ class DefaultMailboxBackupTest implements MailboxMessageFixture {
         backup.backupAccount(USER1, destination);
 
         InputStream source = new ByteArrayInputStream(destination.toByteArray());
-        Mono.from(backup.restore(USER2, source)).block();
+        MailboxBackup.BackupStatus backupStatus = Mono.from(backup.restore(USER2, source)).block();
+        assertThat(backupStatus).isEqualTo(MailboxBackup.BackupStatus.DONE);
 
         List<DefaultMailboxBackup.MailAccountContent> content = backup.getAccountContentForUser(sessionOtherUser);
 
@@ -194,6 +195,20 @@ class DefaultMailboxBackupTest implements MailboxMessageFixture {
     }
 
     @Test
+    void restoringAccountInNonEmptyAccountShouldNotBeDone() throws Exception {
+        createMailbox(sessionUser, MAILBOX_PATH_USER1_MAILBOX1);
+        createMailbox(sessionUser, MAILBOX_PATH_OTHER_USER_MAILBOX1);
+
+        ByteArrayOutputStream destination = new ByteArrayOutputStream(BUFFER_SIZE);
+        backup.backupAccount(USER1, destination);
+
+        InputStream source = new ByteArrayInputStream(destination.toByteArray());
+        MailboxBackup.BackupStatus backupStatus = Mono.from(backup.restore(USER2, source)).block();
+
+        assertThat(backupStatus).isEqualTo(MailboxBackup.BackupStatus.NON_EMPTY_RECEIVER_ACCOUNT);
+    }
+
+    @Test
     void backupAccountWithTwoMailboxesThenRestoringItInUser2AccountShouldCreateTwoMailboxes() throws Exception {
         createMailbox(sessionUser, MAILBOX_PATH_USER1_MAILBOX1);
         createMailbox(sessionUser, MAILBOX_PATH_USER1_MAILBOX2);
@@ -202,7 +217,9 @@ class DefaultMailboxBackupTest implements MailboxMessageFixture {
         backup.backupAccount(USER1, destination);
 
         InputStream source = new ByteArrayInputStream(destination.toByteArray());
-        Mono.from(backup.restore(USER2, source)).block();
+        MailboxBackup.BackupStatus backupStatus = Mono.from(backup.restore(USER2, source)).block();
+
+        assertThat(backupStatus).isEqualTo(MailboxBackup.BackupStatus.DONE);
 
         List<DefaultMailboxBackup.MailAccountContent> content = backup.getAccountContentForUser(sessionOtherUser);
 
@@ -216,7 +233,6 @@ class DefaultMailboxBackupTest implements MailboxMessageFixture {
         Mailbox mailbox2 = contentMailbox2.getMailboxWithAnnotations().mailbox;
         assertThat(mailbox2.getName()).isEqualTo(MAILBOX_2_NAME);
         assertThat(contentMailbox2.getMessages().count()).isEqualTo(0);
-
     }
 
     private MessageManager.AppendCommand getMessage1AppendCommand() throws IOException {


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