JAMES-2436 Basic storage of mailboxes as folders
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/9e0202ae Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/9e0202ae Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/9e0202ae Branch: refs/heads/master Commit: 9e0202aea21d9ae7b2a869f5c2fece3f59404b74 Parents: f7b9741 Author: Raphael Ouazana <[email protected]> Authored: Wed Jun 20 11:43:37 2018 +0200 Committer: Raphael Ouazana <[email protected]> Committed: Wed Jun 27 16:36:12 2018 +0200 ---------------------------------------------------------------------- .../org/apache/james/mailbox/backup/Backup.java | 5 ++- .../org/apache/james/mailbox/backup/Zipper.java | 14 ++++++- .../mailbox/backup/MailboxMessageFixture.java | 6 +++ .../mailbox/backup/ZipArchiveEntryAssert.java | 12 ++++++ .../apache/james/mailbox/backup/ZipAssert.java | 10 +++-- .../james/mailbox/backup/ZipAssertTest.java | 40 ++++++++++++++++++ .../apache/james/mailbox/backup/ZipperTest.java | 44 +++++++++++++++++--- 7 files changed, 120 insertions(+), 11 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/9e0202ae/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/Backup.java ---------------------------------------------------------------------- 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/Backup.java index 1a8d42a..81ebddb 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/Backup.java @@ -20,15 +20,18 @@ package org.apache.james.mailbox.backup; import java.io.IOException; import java.io.OutputStream; +import java.util.List; import java.util.stream.Stream; +import org.apache.james.mailbox.store.mail.model.Mailbox; import org.apache.james.mailbox.store.mail.model.MailboxMessage; public interface Backup { /** + * @param mailboxes list of mailboxes to be stored in the archive * @param messages a stream of MailboxMessages that will be consumed * @param destination an OutputStream in which the zip will be written */ - void archive(Stream<MailboxMessage> messages, OutputStream destination) throws IOException; + void archive(List<Mailbox> mailboxes, Stream<MailboxMessage> messages, OutputStream destination) throws IOException; } http://git-wip-us.apache.org/repos/asf/james-project/blob/9e0202ae/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/Zipper.java ---------------------------------------------------------------------- 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 9be38a5..b25a9db 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 @@ -21,12 +21,14 @@ package org.apache.james.mailbox.backup; import java.io.File; import java.io.IOException; import java.io.OutputStream; +import java.util.List; import java.util.stream.Stream; import org.apache.commons.compress.archivers.zip.ExtraFieldUtils; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; import org.apache.commons.io.IOUtils; +import org.apache.james.mailbox.store.mail.model.Mailbox; import org.apache.james.mailbox.store.mail.model.MailboxMessage; import com.github.fge.lambdas.Throwing; @@ -37,8 +39,11 @@ public class Zipper implements Backup { } @Override - public void archive(Stream<MailboxMessage> messages, OutputStream destination) throws IOException { + public void archive(List<Mailbox> mailboxes, Stream<MailboxMessage> messages, OutputStream destination) throws IOException { try (ZipArchiveOutputStream archiveOutputStream = new ZipArchiveOutputStream(destination)) { + for (Mailbox mailbox: mailboxes) { + storeInArchive(mailbox, archiveOutputStream); + } messages.forEach(Throwing.<MailboxMessage>consumer(message -> { storeInArchive(message, archiveOutputStream); }).sneakyThrow()); @@ -46,6 +51,13 @@ public class Zipper implements Backup { } } + private void storeInArchive(Mailbox mailbox, ZipArchiveOutputStream archiveOutputStream) throws IOException { + String name = mailbox.getName(); + ZipArchiveEntry archiveEntry = (ZipArchiveEntry) archiveOutputStream.createArchiveEntry(new Directory(name), name); + archiveOutputStream.putArchiveEntry(archiveEntry); + archiveOutputStream.closeArchiveEntry(); + } + private void storeInArchive(MailboxMessage message, ZipArchiveOutputStream archiveOutputStream) throws IOException { String entryId = message.getMessageId().serialize(); ZipArchiveEntry archiveEntry = (ZipArchiveEntry) archiveOutputStream.createArchiveEntry(new File(entryId), entryId); http://git-wip-us.apache.org/repos/asf/james-project/blob/9e0202ae/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java ---------------------------------------------------------------------- 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 1894be9..e313de5 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 @@ -27,10 +27,13 @@ import java.util.Date; import javax.mail.Flags; import javax.mail.util.SharedByteArrayInputStream; +import org.apache.james.mailbox.model.MailboxPath; import org.apache.james.mailbox.model.MessageId; import org.apache.james.mailbox.model.TestId; import org.apache.james.mailbox.model.TestMessageId; +import org.apache.james.mailbox.store.mail.model.Mailbox; import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder; +import org.apache.james.mailbox.store.mail.model.impl.SimpleMailbox; import org.apache.james.mailbox.store.mail.model.impl.SimpleMailboxMessage; public interface MailboxMessageFixture { @@ -49,6 +52,9 @@ public interface MailboxMessageFixture { long SIZE_1 = 1000; long SIZE_2 = 2000; + Mailbox MAILBOX_1 = new SimpleMailbox(MailboxPath.forUser("user", "mailbox1"), 42, TestId.of(1L)); + Mailbox MAILBOX_2 = new SimpleMailbox(MailboxPath.forUser("user", "mailbox2"), 43, TestId.of(2L)); + SimpleMailboxMessage MESSAGE_1 = SimpleMailboxMessage.builder() .messageId(MESSAGE_ID_1) .content(CONTENT_STREAM_1) http://git-wip-us.apache.org/repos/asf/james-project/blob/9e0202ae/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipArchiveEntryAssert.java ---------------------------------------------------------------------- diff --git a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipArchiveEntryAssert.java b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipArchiveEntryAssert.java index 2a6aae3..41d5c78 100644 --- a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipArchiveEntryAssert.java +++ b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipArchiveEntryAssert.java @@ -38,6 +38,10 @@ public class ZipArchiveEntryAssert extends AbstractAssert<ZipArchiveEntryAssert, return new ZipArchiveEntryAssert(zipFile, zipArchiveEntry); } + private static BasicErrorMessageFactory shouldBeADirectory(ZipArchiveEntry zipArchiveEntry) { + return new BasicErrorMessageFactory("%nExpecting %s to be a directory but was not", zipArchiveEntry); + } + private static BasicErrorMessageFactory shouldHaveName(ZipArchiveEntry zipArchiveEntry, String expected) { return new BasicErrorMessageFactory("%nExpecting %s to have name %s but was %s", zipArchiveEntry, expected, zipArchiveEntry.getName()); } @@ -59,6 +63,14 @@ public class ZipArchiveEntryAssert extends AbstractAssert<ZipArchiveEntryAssert, this.actual = zipArchiveEntry; } + public ZipArchiveEntryAssert isDirectory() { + isNotNull(); + if (!actual.isDirectory()) { + throwAssertionError(shouldBeADirectory(actual)); + } + return myself; + } + public ZipArchiveEntryAssert hasName(String name) { isNotNull(); if (!actual.getName().equals(name)) { http://git-wip-us.apache.org/repos/asf/james-project/blob/9e0202ae/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipAssert.java ---------------------------------------------------------------------- diff --git a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipAssert.java b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipAssert.java index c007421..911a809 100644 --- a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipAssert.java +++ b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipAssert.java @@ -61,8 +61,12 @@ public class ZipAssert extends AbstractAssert<ZipAssert, ZipFile> { check.compose(additionalCheck)); } - public EntryChecks hasStringContent(String stringConyent) { - return check(check.compose(assertion -> assertion.hasStringContent(stringConyent))); + public EntryChecks hasStringContent(String stringContent) { + return check(check.compose(assertion -> assertion.hasStringContent(stringContent))); + } + + public EntryChecks isDirectory() { + return check(check.compose(assertion -> assertion.isDirectory())); } public EntryChecks containsExtraFields(ZipExtraField... expectedExtraFields) { @@ -75,7 +79,7 @@ public class ZipAssert extends AbstractAssert<ZipAssert, ZipFile> { } private static BasicErrorMessageFactory shouldHaveSize(ZipFile zipFile, int expected, int actual) { - return new BasicErrorMessageFactory("%nExpecting %s to have side %s but was %s", zipFile, expected, actual); + return new BasicErrorMessageFactory("%nExpecting %s to have size %s but was %s", zipFile, expected, actual); } private static BasicErrorMessageFactory shouldBeEmpty(ZipFile zipFile) { http://git-wip-us.apache.org/repos/asf/james-project/blob/9e0202ae/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipAssertTest.java ---------------------------------------------------------------------- diff --git a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipAssertTest.java b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipAssertTest.java index 7075754..c726da8 100644 --- a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipAssertTest.java +++ b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipAssertTest.java @@ -42,6 +42,7 @@ import org.junit.jupiter.api.extension.ExtendWith; public class ZipAssertTest { public static final String ENTRY_NAME = "entryName"; public static final String ENTRY_NAME_2 = "entryName2"; + public static final String DIRECTORY_NAME = "folder/"; public static final String STRING_ENTRY_CONTENT = "abcdefghijkl"; public static final String STRING_ENTRY_CONTENT_2 = "mnopqrstuvwxyz"; public static final byte[] ENTRY_CONTENT = STRING_ENTRY_CONTENT.getBytes(StandardCharsets.UTF_8); @@ -149,6 +150,45 @@ public class ZipAssertTest { } @Test + public void isDirectoryShouldThrowWhenNotADirectory() throws Exception { + try (ZipArchiveOutputStream archiveOutputStream = new ZipArchiveOutputStream(destination)) { + + ZipArchiveEntry archiveEntry = (ZipArchiveEntry) archiveOutputStream.createArchiveEntry(new File("any"), ENTRY_NAME); + archiveOutputStream.putArchiveEntry(archiveEntry); + IOUtils.copy(new ByteArrayInputStream(ENTRY_CONTENT), archiveOutputStream); + archiveOutputStream.closeArchiveEntry(); + archiveOutputStream.finish(); + } + + try (ZipFile zipFile = new ZipFile(destination)) { + assertThatThrownBy(() -> assertThatZip(zipFile) + .containsOnlyEntriesMatching( + hasName(ENTRY_NAME) + .isDirectory())) + .isInstanceOf(AssertionError.class); + } + } + + @Test + public void isDirectoryShouldNotThrowWhenDirectory() throws Exception { + try (ZipArchiveOutputStream archiveOutputStream = new ZipArchiveOutputStream(destination)) { + + ZipArchiveEntry archiveEntry = (ZipArchiveEntry) archiveOutputStream.createArchiveEntry(new Directory("any"), DIRECTORY_NAME); + archiveOutputStream.putArchiveEntry(archiveEntry); + archiveOutputStream.closeArchiveEntry(); + archiveOutputStream.finish(); + } + + try (ZipFile zipFile = new ZipFile(destination)) { + assertThatCode(() -> assertThatZip(zipFile) + .containsOnlyEntriesMatching( + hasName(DIRECTORY_NAME) + .isDirectory())) + .doesNotThrowAnyException(); + } + } + + @Test public void containsExactlyEntriesMatchingShouldNotThrowWhenWrongOrder() throws Exception { try (ZipArchiveOutputStream archiveOutputStream = new ZipArchiveOutputStream(destination)) { http://git-wip-us.apache.org/repos/asf/james-project/blob/9e0202ae/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipperTest.java ---------------------------------------------------------------------- diff --git a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipperTest.java b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipperTest.java index aa465d3..accd629 100644 --- a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipperTest.java +++ b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipperTest.java @@ -18,6 +18,8 @@ ****************************************************************/ package org.apache.james.mailbox.backup; +import static org.apache.james.mailbox.backup.MailboxMessageFixture.MAILBOX_1; +import static org.apache.james.mailbox.backup.MailboxMessageFixture.MAILBOX_2; import static org.apache.james.mailbox.backup.MailboxMessageFixture.MESSAGE_1; import static org.apache.james.mailbox.backup.MailboxMessageFixture.MESSAGE_2; import static org.apache.james.mailbox.backup.MailboxMessageFixture.MESSAGE_CONTENT_1; @@ -25,19 +27,23 @@ import static org.apache.james.mailbox.backup.MailboxMessageFixture.MESSAGE_CONT import static org.apache.james.mailbox.backup.MailboxMessageFixture.MESSAGE_ID_1; import static org.apache.james.mailbox.backup.MailboxMessageFixture.MESSAGE_ID_2; import static org.apache.james.mailbox.backup.MailboxMessageFixture.SIZE_1; -import static org.apache.james.mailbox.backup.ZipAssert.EntryChecks.hasName; import static org.apache.james.mailbox.backup.ZipAssert.assertThatZip; +import static org.apache.james.mailbox.backup.ZipAssert.EntryChecks.hasName; import java.io.ByteArrayOutputStream; +import java.util.List; import java.util.stream.Stream; import org.apache.commons.compress.archivers.zip.ZipFile; import org.apache.commons.compress.utils.SeekableInMemoryByteChannel; +import org.apache.james.mailbox.store.mail.model.Mailbox; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -class ZipperTest { +import com.google.common.collect.ImmutableList; +class ZipperTest { + private static final List<Mailbox> NO_MAILBOXES = ImmutableList.of(); private Zipper testee; private ByteArrayOutputStream output; @@ -49,7 +55,7 @@ class ZipperTest { @Test void archiveShouldWriteEmptyValidArchiveWhenNoMessage() throws Exception { - testee.archive(Stream.of(), output); + testee.archive(NO_MAILBOXES, Stream.of(), output); try (ZipFile zipFile = new ZipFile(toSeekableByteChannel(output))) { assertThatZip(zipFile).hasNoEntry(); } @@ -57,7 +63,7 @@ class ZipperTest { @Test void archiveShouldWriteOneMessageWhenOne() throws Exception { - testee.archive(Stream.of(MESSAGE_1), output); + testee.archive(NO_MAILBOXES, Stream.of(MESSAGE_1), output); try (ZipFile zipFile = new ZipFile(toSeekableByteChannel(output))) { assertThatZip(zipFile) @@ -69,7 +75,7 @@ class ZipperTest { @Test void archiveShouldWriteTwoMessagesWhenTwo() throws Exception { - testee.archive(Stream.of(MESSAGE_1, MESSAGE_2), output); + testee.archive(NO_MAILBOXES, Stream.of(MESSAGE_1, MESSAGE_2), output); try (ZipFile zipFile = new ZipFile(toSeekableByteChannel(output))) { assertThatZip(zipFile) @@ -83,7 +89,7 @@ class ZipperTest { @Test void archiveShouldWriteSizeMetadata() throws Exception { - testee.archive(Stream.of(MESSAGE_1), output); + testee.archive(NO_MAILBOXES, Stream.of(MESSAGE_1), output); try (ZipFile zipFile = new ZipFile(toSeekableByteChannel(output))) { assertThatZip(zipFile) @@ -93,6 +99,32 @@ class ZipperTest { } } + @Test + void archiveShouldWriteOneMailboxWhenPresent() throws Exception { + testee.archive(ImmutableList.of(MAILBOX_1), Stream.of(), output); + + try (ZipFile zipFile = new ZipFile(toSeekableByteChannel(output))) { + assertThatZip(zipFile) + .containsOnlyEntriesMatching( + hasName(MAILBOX_1.getName() + "/") + .isDirectory()); + } + } + + @Test + void archiveShouldWriteMailboxesWhenPresent() throws Exception { + testee.archive(ImmutableList.of(MAILBOX_1, MAILBOX_2), Stream.of(), output); + + try (ZipFile zipFile = new ZipFile(toSeekableByteChannel(output))) { + assertThatZip(zipFile) + .containsOnlyEntriesMatching( + hasName(MAILBOX_1.getName() + "/") + .isDirectory(), + hasName(MAILBOX_2.getName() + "/") + .isDirectory()); + } + } + private SeekableInMemoryByteChannel toSeekableByteChannel(ByteArrayOutputStream output) { return new SeekableInMemoryByteChannel(output.toByteArray()); } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
