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 3805a8868913ef58bb6211ad388d830a1f2affa6
Author: RĂ©mi Kowalski <rkowal...@linagora.com>
AuthorDate: Fri Mar 8 11:49:23 2019 +0100

    JAMES-2681 rename Backup to Archive
---
 .../backup/{Backup.java => ArchiveService.java}    |   2 +-
 .../james/mailbox/backup/DefaultMailboxBackup.java | 129 ++++++++++++++++++
 .../org/apache/james/mailbox/backup/Zipper.java    |   2 +-
 .../mailbox/backup/DefaultMailboxBackupTest.java   | 148 +++++++++++++++++++++
 4 files changed, 279 insertions(+), 2 deletions(-)

diff --git 
a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/Backup.java 
b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/ArchiveService.java
similarity index 98%
rename from 
mailbox/backup/src/main/java/org/apache/james/mailbox/backup/Backup.java
rename to 
mailbox/backup/src/main/java/org/apache/james/mailbox/backup/ArchiveService.java
index e77871e..2789691 100644
--- a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/Backup.java
+++ 
b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/ArchiveService.java
@@ -25,7 +25,7 @@ import java.util.stream.Stream;
 
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
 
-public interface Backup {
+public interface ArchiveService {
 
     /**
      * @param mailboxes   list of mailboxes and their annotations to be stored 
in the archive
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
new file mode 100644
index 0000000..2bff492
--- /dev/null
+++ 
b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/DefaultMailboxBackup.java
@@ -0,0 +1,129 @@
+/****************************************************************
+ * 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.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.james.blob.api.BlobStore;
+import org.apache.james.core.User;
+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.BlobId;
+import org.apache.james.mailbox.model.FetchGroupImpl;
+import org.apache.james.mailbox.model.MailboxAnnotation;
+import org.apache.james.mailbox.model.MailboxPath;
+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.mailbox.store.StoreMessageManager;
+import org.apache.james.mailbox.store.mail.model.Mailbox;
+import org.apache.james.util.OptionalUtils;
+import org.apache.james.util.streams.Iterators;
+import org.reactivestreams.Publisher;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DefaultMailboxBackup implements MailboxBackup {
+
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(DefaultMailboxBackup.class);
+
+    protected class MailAccountContent {
+        final MailboxWithAnnotations mailboxWithAnnotations;
+        final Stream<MessageResult> messages;
+
+        MailAccountContent(MailboxWithAnnotations mailboxWithAnnotations, 
Stream<MessageResult> messages) {
+            this.mailboxWithAnnotations = mailboxWithAnnotations;
+            this.messages = messages;
+        }
+    }
+
+    public DefaultMailboxBackup(MailboxManager mailboxManager, ArchiveService 
archiveService, BlobStore store) {
+        this.mailboxManager = mailboxManager;
+        this.archiveService = archiveService;
+        this.store = store;
+    }
+
+    private final MailboxManager mailboxManager;
+    private final ArchiveService archiveService;
+    private final BlobStore store;
+
+    private Function<MailboxPath, Optional<MailAccountContent>> 
getMailboxWithAnnotationsFromPath(MailboxSession session) {
+        return path -> {
+            try {
+                StoreMessageManager messageManager = (StoreMessageManager) 
mailboxManager.getMailbox(path, session);
+                Mailbox mailbox = messageManager.getMailboxEntity();
+                List<MailboxAnnotation> annotations = 
mailboxManager.getAllAnnotations(path, session);
+                MailboxWithAnnotations mailboxWithAnnotations = new 
MailboxWithAnnotations(mailbox, annotations);
+                Stream<MessageResult> messages = 
Iterators.toStream(messageManager.getMessages(MessageRange.all(), 
FetchGroupImpl.FULL_CONTENT, session));
+                return Optional.of(new 
MailAccountContent(mailboxWithAnnotations, messages));
+            } catch (MailboxException e) {
+                LOGGER.error("Error while fetching Mailbox during backup", e);
+                return Optional.empty();
+            }
+        };
+    }
+
+    private List<MailAccountContent> getAllMailboxesForUser(MailboxSession 
session) throws MailboxException {
+        MailboxQuery queryUser = 
MailboxQuery.builder().username(session.getUser().asString()).build();
+        Stream<MailboxPath> paths = mailboxManager.search(queryUser, 
session).stream().map(mailboxMetaData -> mailboxMetaData.getPath());
+        List<MailAccountContent> mailboxes = paths
+            
.flatMap(getMailboxWithAnnotationsFromPath(session).andThen(OptionalUtils::toStream))
+            .collect(Collectors.toList());
+
+        return mailboxes;
+    }
+
+    private Publisher<BlobId> saveToStore(List<MailboxWithAnnotations> 
mailboxes, Stream<MessageResult> messages) throws IOException {
+        File tmp = File.createTempFile(UUID.randomUUID().toString(), ".tmp");
+        try (OutputStream out = new FileOutputStream(tmp)) {
+            archiveService.archive(mailboxes, messages, out);
+            try (InputStream in = new BufferedInputStream(new 
FileInputStream(tmp))) {
+                return store.save(in).map(b -> 
BlobId.fromString(b.asString()));
+            }
+        } finally {
+            tmp.delete();
+        }
+    }
+
+    private Stream<MessageResult> allMessagesForUser(List<MailAccountContent> 
mailboxes) {
+        return mailboxes.stream().flatMap(messages -> messages.messages);
+    }
+
+    @Override
+    public Publisher<BlobId> backupAccount(User user) throws IOException, 
MailboxException {
+        MailboxSession session = 
mailboxManager.createSystemSession(user.asString());
+        List<MailAccountContent> mailboxesWithMessages = 
getAllMailboxesForUser(session);
+        List<MailboxWithAnnotations> mailboxes = 
mailboxesWithMessages.stream().map(m -> 
m.mailboxWithAnnotations).collect(Collectors.toList());
+        Stream<MessageResult> messages = 
allMessagesForUser(mailboxesWithMessages);
+        return saveToStore(mailboxes, messages);
+    }
+}
diff --git 
a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/Zipper.java 
b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/Zipper.java
index 7f87a69..370dbb4 100644
--- a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/Zipper.java
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/Zipper.java
@@ -37,7 +37,7 @@ import 
org.apache.james.mailbox.store.mail.model.MailboxMessage;
 import com.github.fge.lambdas.Throwing;
 import com.google.common.base.Charsets;
 
-public class Zipper implements Backup {
+public class Zipper implements ArchiveService {
 
     private static final String ANNOTATION_DIRECTORY = "annotations";
     private static final boolean AUTO_FLUSH = true;
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
new file mode 100644
index 0000000..3f57508
--- /dev/null
+++ 
b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/DefaultMailboxBackupTest.java
@@ -0,0 +1,148 @@
+/****************************************************************
+ * 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.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.HashSet;
+
+import org.apache.commons.compress.archivers.zip.ZipFile;
+import org.apache.james.blob.api.BlobStore;
+import org.apache.james.blob.api.HashBlobId;
+import org.apache.james.blob.memory.MemoryBlobStore;
+import org.apache.james.core.User;
+import org.apache.james.junit.TemporaryFolderExtension;
+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.extension.PreDeletionHook;
+import org.apache.james.mailbox.inmemory.MemoryMailboxManagerProvider;
+import org.apache.james.mailbox.manager.ManagerTestResources;
+import org.apache.james.mailbox.model.BlobId;
+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 org.junit.jupiter.api.extension.ExtendWith;
+import org.reactivestreams.Publisher;
+import org.testcontainers.shaded.org.apache.commons.io.IOUtils;
+
+import com.github.fge.lambdas.Throwing;
+import reactor.core.publisher.Mono;
+
+@ExtendWith(TemporaryFolderExtension.class)
+class DefaultMailboxBackupTest implements MailboxMessageFixture {
+
+    private static final User USER1 = 
User.fromUsername(ManagerTestResources.USER);
+    private static final MailboxPath MAILBOX_PATH_USER1_MAILBOX1 = 
MailboxPath.forUser(ManagerTestResources.USER, MAILBOX_1_NAME);
+    private static final MailboxPath MAILBOX_PATH_OTHER_USER_MAILBOX1 = 
MailboxPath.forUser(ManagerTestResources.OTHER_USER, MAILBOX_OTHER_USER_NAME);
+    private static final HashBlobId.Factory BLOB_ID_FACTORY = new 
HashBlobId.Factory();
+    private static final HashSet<PreDeletionHook> PRE_DELETION_HOOKS = new 
HashSet<>();
+
+    private final ArchiveService archiveService = new Zipper();
+
+    private MailboxManager mailboxManager;
+    private BlobStore store;
+    private File destination;
+    private DefaultMailboxBackup backup;
+
+    @BeforeEach
+    void beforeEach(TemporaryFolderExtension.TemporaryFolder temporaryFolder) 
throws Exception {
+        destination = File.createTempFile("backup-test", ".zip", 
temporaryFolder.getTempDir());
+        mailboxManager = 
MemoryMailboxManagerProvider.provideMailboxManager(PRE_DELETION_HOOKS);
+        store = new MemoryBlobStore(new HashBlobId.Factory());
+        backup = new DefaultMailboxBackup(mailboxManager, archiveService, 
store);
+    }
+
+    private void readFromStoreAndCopyInFile(BlobId blobId) throws Exception {
+        InputStream content = 
store.read(BLOB_ID_FACTORY.from(blobId.asString()));
+        try (OutputStream out = new FileOutputStream(destination)) {
+            IOUtils.copy(content, out);
+        }
+    }
+
+    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 ->
+                mailboxManager.getMailbox(mailboxId, 
session).appendMessage(MessageManager.AppendCommand.from(message.getFullContent()),
 session)
+            )
+        );
+    }
+
+    private ZipAssert assertThatZipFromIdContainsOnly(Publisher<BlobId> 
blobIdPublisher, EntryChecks... onlyEntriesMatching) throws Exception {
+        BlobId blobId = Mono.from(blobIdPublisher).block();
+        readFromStoreAndCopyInFile(blobId);
+
+        try (ZipFile zipFile = new ZipFile(destination)) {
+            return 
ZipAssert.assertThatZip(zipFile).containsOnlyEntriesMatching(onlyEntriesMatching);
+        }
+    }
+
+    @Test
+    void doBackupWithoutMailboxShouldStoreEmptyBackup() throws Exception {
+        Publisher<BlobId> res = backup.backupAccount(USER1);
+
+        assertThatZipFromIdContainsOnly(res);
+    }
+
+    @Test
+    void doBackupWithoutMessageShouldStoreAnArchiveWithOnlyOneEntry() throws 
Exception {
+        MailboxSession session = 
mailboxManager.createSystemSession(ManagerTestResources.USER);
+        createMailBoxWithMessage(session, MAILBOX_PATH_USER1_MAILBOX1);
+
+        Publisher<BlobId> res = backup.backupAccount(USER1);
+
+        assertThatZipFromIdContainsOnly(res, 
EntryChecks.hasName(MAILBOX_1_NAME + "/").isDirectory());
+    }
+
+    @Test
+    void doBackupWithOneMessageShouldStoreAnArchiveWithTwoEntries() throws 
Exception {
+        MailboxSession session = 
mailboxManager.createSystemSession(ManagerTestResources.USER);
+        createMailBoxWithMessage(session, MAILBOX_PATH_USER1_MAILBOX1, 
MESSAGE_1);
+
+        Publisher<BlobId> res = backup.backupAccount(USER1);
+
+        assertThatZipFromIdContainsOnly(res,
+            EntryChecks.hasName(MAILBOX_1_NAME + "/").isDirectory(),
+            
EntryChecks.hasName(MESSAGE_ID_1.serialize()).hasStringContent(MESSAGE_CONTENT_1)
+        );
+    }
+
+    @Test
+    void doBackupShouldOnlyArchiveTheMailboxOfTheUser() throws Exception {
+        MailboxSession session = 
mailboxManager.createSystemSession(ManagerTestResources.USER);
+        MailboxSession otherSession = 
mailboxManager.createSystemSession(ManagerTestResources.OTHER_USER);
+
+        createMailBoxWithMessage(session, MAILBOX_PATH_USER1_MAILBOX1, 
MESSAGE_1);
+        createMailBoxWithMessage(otherSession, 
MAILBOX_PATH_OTHER_USER_MAILBOX1, MESSAGE_1_OTHER_USER);
+
+        Publisher<BlobId> res = backup.backupAccount(USER1);
+
+        assertThatZipFromIdContainsOnly(res,
+            EntryChecks.hasName(MAILBOX_1_NAME + "/").isDirectory(),
+            
EntryChecks.hasName(MESSAGE_ID_1.serialize()).hasStringContent(MESSAGE_CONTENT_1)
+        );
+    }
+}


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

Reply via email to