You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by bt...@apache.org on 2019/03/26 04:39:31 UTC

[james-project] branch master updated (c2ace25 -> 15aa698)

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

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


    from c2ace25  Fix Eclipse and checkstyle warnings
     new 84ef261  MAILBOX-385 Adding size field to DeletedMessage
     new e2bf45b  MAILBOX-385 DeletedMessageZipper impl
     new ac8d2eb  MAILBOX-385 Get rid of DeletedMessageWithContent
     new 0d6b733  MAILBOX-385 Rework DeletedMessageZipperTest
     new ab6cf30  MAILBOX-385 ZipAssert should handle outputStream conversion
     new bce0b04  MAILBOX-385 DeletedMessageZipperTest: nested class + method move
     new 3183f7f  JAMES-2682 Prevent infinite loop with Sieve error notifications
     new 9bb878b  JAMES-2682 Sieve should just do nothing when handling Sieve errors
     new 975b9bc  JAMES-2682 Fix checkstyle
     new 15aa698  JAMES-2666 Rename SwarmGenericContainer into DockerGenericContainer

The 10 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:
 .../es/ClientProviderImplConnectionTest.java       |   6 +-
 mailbox/backup/pom.xml                             |   1 -
 .../org/apache/james/mailbox/backup/ZipAssert.java |  15 +-
 .../apache/james/mailbox/backup/ZipperTest.java    |  70 +++----
 mailbox/plugin/deleted-messages-vault/pom.xml      |  18 ++
 .../org/apache/james/vault/DeletedMessage.java     |  41 +++-
 .../james/vault/DeletedMessageConverter.java       |   1 +
 .../apache/james/vault/DeletedMessageZipper.java   |  86 ++++++++
 .../james/vault/DeletedMessageConverterTest.java   |   8 +-
 .../apache/james/vault/DeletedMessageFixture.java  |   5 +-
 .../org/apache/james/vault/DeletedMessageTest.java |  18 ++
 .../james/vault/DeletedMessageVaultHookTest.java   |  30 ++-
 .../vault/DeletedMessageVaultSearchContract.java   |   7 +-
 .../james/vault/DeletedMessageZipperTest.java      | 219 +++++++++++++++++++++
 .../apache/james/mailbox/store/MessageBuilder.java |   7 +-
 .../apache/james/mailbox/tika/TikaContainer.java   |   6 +-
 pom.xml                                            |  16 ++
 .../apache/james/DockerElasticSearchExtension.java |   6 +-
 .../james/JamesServerWithRetryConnectionTest.java  |   4 +-
 .../metric/es/DockerElasticSearch2Extension.java   |   8 +-
 .../metric/es/DockerElasticSearch6Extension.java   |   8 +-
 .../apache/james/metric/es/ESReporterContract.java |   8 +-
 .../james/user/ldap/LdapGenericContainer.java      |  10 +-
 .../mailets/AmqpForwardAttachmentTest.java         |   4 +-
 .../transport/mailets/ContactExtractorTest.java    |   4 +-
 .../mailets/ICSAttachmentWorkflowTest.java         |   4 +-
 .../james/transport/mailets/SpamAssassinTest.java  |   4 +-
 .../james/transport/mailets/amqp/AmqpRule.java     |   6 +-
 .../mailets/jsieve/delivery/SieveExecutor.java     |  10 +-
 .../mailets/delivery/SieveIntegrationTest.java     |  12 ++
 .../java/org/apache/james/vault/MailConverter.java |  24 +++
 .../java/org/apache/james/jmap/ContainerTest.java  |   4 +-
 .../ReindexingWithEventDeadLettersTest.java        |   4 +-
 .../routes/DeletedMessagesVaultRoutesTest.java     |   5 +-
 ...cContainer.java => DockerGenericContainer.java} |  22 +--
 .../main/java/org/apache/james/utils/FakeSmtp.java |  14 +-
 36 files changed, 583 insertions(+), 132 deletions(-)
 create mode 100644 mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessageZipper.java
 create mode 100644 mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageZipperTest.java
 rename server/testing/src/main/java/org/apache/james/util/docker/{SwarmGenericContainer.java => DockerGenericContainer.java} (88%)


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


[james-project] 05/10: MAILBOX-385 ZipAssert should handle outputStream conversion

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit ab6cf304acf2917080f037dd67271be13c3396e3
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri Mar 22 11:24:47 2019 +0700

    MAILBOX-385 ZipAssert should handle outputStream conversion
    
    This technical operation is duplicated in each and every zip test
    
    Note that ZipAssert thus need to be closeable
---
 .../org/apache/james/mailbox/backup/ZipAssert.java | 15 ++++-
 .../apache/james/mailbox/backup/ZipperTest.java    | 70 ++++++++--------------
 .../james/vault/DeletedMessageZipperTest.java      | 17 ++----
 3 files changed, 44 insertions(+), 58 deletions(-)

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 cf1c41e..7c46fad 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
@@ -21,6 +21,8 @@ package org.apache.james.mailbox.backup;
 
 import static org.apache.james.mailbox.backup.ZipArchiveEntryAssert.assertThatZipEntry;
 
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
@@ -29,12 +31,13 @@ import java.util.List;
 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
 import org.apache.commons.compress.archivers.zip.ZipExtraField;
 import org.apache.commons.compress.archivers.zip.ZipFile;
+import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
 import org.assertj.core.api.AbstractAssert;
 import org.assertj.core.error.BasicErrorMessageFactory;
 
 import com.github.steveash.guavate.Guavate;
 
-public class ZipAssert extends AbstractAssert<ZipAssert, ZipFile> {
+public class ZipAssert extends AbstractAssert<ZipAssert, ZipFile> implements AutoCloseable {
     interface EntryCheck {
         default EntryCheck compose(EntryCheck other) {
             return assertion -> other.test(this.test(assertion));
@@ -74,10 +77,14 @@ public class ZipAssert extends AbstractAssert<ZipAssert, ZipFile> {
         }
     }
 
-    public static ZipAssert assertThatZip(ZipFile zipFile) {
+    static ZipAssert assertThatZip(ZipFile zipFile) {
         return new ZipAssert(zipFile);
     }
 
+    public static ZipAssert assertThatZip(ByteArrayOutputStream outputStream) throws IOException {
+        return assertThatZip(new ZipFile(new SeekableInMemoryByteChannel(outputStream.toByteArray())));
+    }
+
     private static BasicErrorMessageFactory shouldHaveSize(ZipFile zipFile, int expected, int actual) {
         return new BasicErrorMessageFactory("%nExpecting %s to have size %s but was %s", zipFile, expected, actual);
     }
@@ -119,4 +126,8 @@ public class ZipAssert extends AbstractAssert<ZipAssert, ZipFile> {
         return myself;
     }
 
+    @Override
+    public void close() throws Exception {
+        zipFile.close();
+    }
 }
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 e6da066..a7c4ea0 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
@@ -46,8 +46,6 @@ 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.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
@@ -71,8 +69,8 @@ class ZipperTest {
     @Test
     void archiveShouldWriteEmptyValidArchiveWhenNoMessage() throws Exception {
         testee.archive(NO_MAILBOXES, Stream.of(), output);
-        try (ZipFile zipFile = new ZipFile(toSeekableByteChannel(output))) {
-            assertThatZip(zipFile).hasNoEntry();
+        try (ZipAssert zipAssert = assertThatZip(output)) {
+            zipAssert.hasNoEntry();
         }
     }
 
@@ -80,9 +78,8 @@ class ZipperTest {
     void archiveShouldWriteOneMessageWhenOne() throws Exception {
         testee.archive(NO_MAILBOXES, Stream.of(MESSAGE_1), output);
 
-        try (ZipFile zipFile = new ZipFile(toSeekableByteChannel(output))) {
-            assertThatZip(zipFile)
-                .containsOnlyEntriesMatching(
+        try (ZipAssert zipAssert = assertThatZip(output)) {
+            zipAssert.containsOnlyEntriesMatching(
                     hasName(MESSAGE_ID_1.serialize())
                         .hasStringContent(MESSAGE_CONTENT_1));
         }
@@ -92,9 +89,8 @@ class ZipperTest {
     void archiveShouldWriteTwoMessagesWhenTwo() throws Exception {
         testee.archive(NO_MAILBOXES, Stream.of(MESSAGE_1, MESSAGE_2), output);
 
-        try (ZipFile zipFile = new ZipFile(toSeekableByteChannel(output))) {
-            assertThatZip(zipFile)
-                .containsOnlyEntriesMatching(
+        try (ZipAssert zipAssert = assertThatZip(output)) {
+            zipAssert.containsOnlyEntriesMatching(
                     hasName(MESSAGE_ID_1.serialize())
                         .hasStringContent(MESSAGE_CONTENT_1),
                     hasName(MESSAGE_ID_2.serialize())
@@ -106,9 +102,8 @@ class ZipperTest {
     void archiveShouldWriteMetadata() throws Exception {
         testee.archive(NO_MAILBOXES, Stream.of(MESSAGE_1), output);
 
-        try (ZipFile zipFile = new ZipFile(toSeekableByteChannel(output))) {
-            assertThatZip(zipFile)
-                .containsOnlyEntriesMatching(
+        try (ZipAssert zipAssert = assertThatZip(output)) {
+            zipAssert.containsOnlyEntriesMatching(
                     hasName(MESSAGE_ID_1.serialize())
                         .containsExtraFields(new SizeExtraField(SIZE_1))
                         .containsExtraFields(new UidExtraField(MESSAGE_UID_1_VALUE))
@@ -123,9 +118,8 @@ class ZipperTest {
     void archiveShouldWriteOneMailboxWhenPresent() throws Exception {
         testee.archive(ImmutableList.of(MAILBOX_1_WITHOUT_ANNOTATION), Stream.of(), output);
 
-        try (ZipFile zipFile = new ZipFile(toSeekableByteChannel(output))) {
-            assertThatZip(zipFile)
-                .containsOnlyEntriesMatching(
+        try (ZipAssert zipAssert = assertThatZip(output)) {
+            zipAssert.containsOnlyEntriesMatching(
                     hasName(MAILBOX_1.getName() + "/")
                         .isDirectory());
         }
@@ -135,9 +129,8 @@ class ZipperTest {
     void archiveShouldWriteMailboxesWhenPresent() throws Exception {
         testee.archive(ImmutableList.of(MAILBOX_1_WITHOUT_ANNOTATION, MAILBOX_2_WITHOUT_ANNOTATION), Stream.of(), output);
 
-        try (ZipFile zipFile = new ZipFile(toSeekableByteChannel(output))) {
-            assertThatZip(zipFile)
-                .containsOnlyEntriesMatching(
+        try (ZipAssert zipAssert = assertThatZip(output)) {
+            zipAssert.containsOnlyEntriesMatching(
                     hasName(MAILBOX_1.getName() + "/")
                         .isDirectory(),
                     hasName(MAILBOX_2.getName() + "/")
@@ -149,9 +142,8 @@ class ZipperTest {
     void archiveShouldWriteMailboxHierarchyWhenPresent() throws Exception {
         testee.archive(ImmutableList.of(MAILBOX_1_WITHOUT_ANNOTATION, MAILBOX_1_SUB_1_WITHOUT_ANNOTATION, MAILBOX_2_WITHOUT_ANNOTATION), Stream.of(), output);
 
-        try (ZipFile zipFile = new ZipFile(toSeekableByteChannel(output))) {
-            assertThatZip(zipFile)
-                .containsOnlyEntriesMatching(
+        try (ZipAssert zipAssert = assertThatZip(output)) {
+            zipAssert.containsOnlyEntriesMatching(
                     hasName(MAILBOX_1.getName() + "/")
                         .isDirectory(),
                     hasName(MAILBOX_1_SUB_1.getName() + "/")
@@ -165,9 +157,8 @@ class ZipperTest {
     void archiveShouldWriteMailboxHierarchyWhenMissingParent() throws Exception {
         testee.archive(ImmutableList.of(MAILBOX_1_SUB_1_WITHOUT_ANNOTATION, MAILBOX_2_WITHOUT_ANNOTATION), Stream.of(), output);
 
-        try (ZipFile zipFile = new ZipFile(toSeekableByteChannel(output))) {
-            assertThatZip(zipFile)
-                .containsOnlyEntriesMatching(
+        try (ZipAssert zipAssert = assertThatZip(output)) {
+            zipAssert.containsOnlyEntriesMatching(
                     hasName(MAILBOX_1_SUB_1.getName() + "/")
                         .isDirectory(),
                     hasName(MAILBOX_2.getName() + "/")
@@ -179,9 +170,8 @@ class ZipperTest {
     void archiveShouldWriteMailboxMetadataWhenPresent() throws Exception {
         testee.archive(ImmutableList.of(MAILBOX_1_WITHOUT_ANNOTATION), Stream.of(), output);
 
-        try (ZipFile zipFile = new ZipFile(toSeekableByteChannel(output))) {
-            assertThatZip(zipFile)
-                .containsOnlyEntriesMatching(
+        try (ZipAssert zipAssert = assertThatZip(output)) {
+            zipAssert.containsOnlyEntriesMatching(
                     hasName(MAILBOX_1.getName() + "/")
                         .containsExtraFields(
                             new MailboxIdExtraField(MAILBOX_1.getMailboxId()),
@@ -193,9 +183,8 @@ class ZipperTest {
     void archiveShouldWriteMailBoxWithoutAnAnnotationSubDirWhenEmpty() throws Exception {
         testee.archive(ImmutableList.of(MAILBOX_1_WITHOUT_ANNOTATION), Stream.of(), output);
 
-        try (ZipFile zipFile = new ZipFile(toSeekableByteChannel(output))) {
-            assertThatZip(zipFile)
-                .containsOnlyEntriesMatching(
+        try (ZipAssert zipAssert = assertThatZip(output)) {
+            zipAssert.containsOnlyEntriesMatching(
                     hasName(MAILBOX_1.getName() + "/")
                 );
         }
@@ -205,9 +194,8 @@ class ZipperTest {
     void archiveShouldWriteMailboxAnnotationsInASubDirWhenPresent() throws Exception {
         testee.archive(ImmutableList.of(new MailboxWithAnnotations(MAILBOX_1, WITH_ANNOTATION_1)), Stream.of(), output);
 
-        try (ZipFile zipFile = new ZipFile(toSeekableByteChannel(output))) {
-            assertThatZip(zipFile)
-                .containsOnlyEntriesMatching(
+        try (ZipAssert zipAssert = assertThatZip(output)) {
+            zipAssert.containsOnlyEntriesMatching(
                     hasName(MAILBOX_1.getName() + "/"),
                     hasName(MAILBOX_1.getName() + "/annotations/").isDirectory(),
                     hasName(MAILBOX_1.getName() + "/annotations/" + ANNOTATION_1.getKey().asString())
@@ -219,9 +207,8 @@ class ZipperTest {
     void archiveShouldWriteMailboxAnnotationsInASubDirWhenTwoPresent() throws Exception {
         testee.archive(ImmutableList.of(new MailboxWithAnnotations(MAILBOX_1, WITH_ANNOTATION_1_AND_2)), Stream.of(), output);
 
-        try (ZipFile zipFile = new ZipFile(toSeekableByteChannel(output))) {
-            assertThatZip(zipFile)
-                .containsOnlyEntriesMatching(
+        try (ZipAssert zipAssert = assertThatZip(output)) {
+            zipAssert.containsOnlyEntriesMatching(
                     hasName(MAILBOX_1.getName() + "/"),
                     hasName(MAILBOX_1.getName() + "/annotations/").isDirectory(),
                     hasName(MAILBOX_1.getName() + "/annotations/" + ANNOTATION_1.getKey().asString())
@@ -236,9 +223,8 @@ class ZipperTest {
     void archiveShouldWriteMailboxAnnotationsInASubDirWhenTwoPresentWithTheSameName() throws Exception {
         testee.archive(ImmutableList.of(new MailboxWithAnnotations(MAILBOX_1, ImmutableList.of(ANNOTATION_1, ANNOTATION_1_BIS))), Stream.of(), output);
 
-        try (ZipFile zipFile = new ZipFile(toSeekableByteChannel(output))) {
-            assertThatZip(zipFile)
-                .containsOnlyEntriesMatching(
+        try (ZipAssert zipAssert = assertThatZip(output)) {
+            zipAssert.containsOnlyEntriesMatching(
                     hasName(MAILBOX_1.getName() + "/"),
                     hasName(MAILBOX_1.getName() + "/annotations/").isDirectory(),
                     hasName(MAILBOX_1.getName() + "/annotations/" + ANNOTATION_1.getKey().asString())
@@ -248,8 +234,4 @@ class ZipperTest {
                 );
         }
     }
-
-    private SeekableInMemoryByteChannel toSeekableByteChannel(ByteArrayOutputStream output) {
-        return new SeekableInMemoryByteChannel(output.toByteArray());
-    }
 }
diff --git a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageZipperTest.java b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageZipperTest.java
index 9ae108f..3f59798 100644
--- a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageZipperTest.java
+++ b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageZipperTest.java
@@ -49,10 +49,9 @@ import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Stream;
 
 import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
-import org.apache.commons.compress.archivers.zip.ZipFile;
-import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
 import org.apache.james.mailbox.backup.MessageIdExtraField;
 import org.apache.james.mailbox.backup.SizeExtraField;
+import org.apache.james.mailbox.backup.ZipAssert;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.mockito.stubbing.Answer;
@@ -75,9 +74,8 @@ class DeletedMessageZipperTest {
 
         zipper.zip(CONTENT_LOADER, Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2), outputStream);
 
-        try (ZipFile zipFile = zipFile(outputStream)) {
-            assertThatZip(zipFile)
-                .containsOnlyEntriesMatching(
+        try (ZipAssert zipAssert = assertThatZip(outputStream)) {
+            zipAssert.containsOnlyEntriesMatching(
                     hasName(MESSAGE_ID.serialize()).hasStringContent(MESSAGE_CONTENT),
                     hasName(MESSAGE_ID_2.serialize()).hasStringContent(MESSAGE_CONTENT));
         }
@@ -89,9 +87,8 @@ class DeletedMessageZipperTest {
 
         zipper.zip(CONTENT_LOADER, Stream.of(DELETED_MESSAGE), outputStream);
 
-        try (ZipFile zipFile = zipFile(outputStream)) {
-            assertThatZip(zipFile)
-                .containsOnlyEntriesMatching(
+        try (ZipAssert zipAssert = assertThatZip(outputStream)) {
+            zipAssert.containsOnlyEntriesMatching(
                     hasName(MESSAGE_ID.serialize())
                         .containsExtraFields(new MessageIdExtraField(MESSAGE_ID))
                         .containsExtraFields(new SizeExtraField(CONTENT.length)));
@@ -194,10 +191,6 @@ class DeletedMessageZipperTest {
         verify(zipOutputStreamReference.get(), times(1)).close();
     }
 
-    private ZipFile zipFile(ByteArrayOutputStream output) throws IOException {
-        return new ZipFile(new SeekableInMemoryByteChannel(output.toByteArray()));
-    }
-
     private DeletedMessageZipper.DeletedMessageContentLoader spyLoadedContents(Collection<InputStream> loadedContents) {
         Answer<InputStream> spyedContent = invocationOnMock -> {
             InputStream result = spy(new ByteArrayInputStream(CONTENT));


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


[james-project] 07/10: JAMES-2682 Prevent infinite loop with Sieve error notifications

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 3183f7f9be683e765ca34702156313943c3880df
Author: Pablo Pita <pa...@gmail.com>
AuthorDate: Sat Mar 16 15:10:47 2019 +0100

    JAMES-2682 Prevent infinite loop with Sieve error notifications
---
 .../transport/mailets/jsieve/delivery/SieveExecutor.java  | 15 ++++++++++++++-
 .../transport/mailets/delivery/SieveIntegrationTest.java  | 10 ++++++++++
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/delivery/SieveExecutor.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/delivery/SieveExecutor.java
index bd50190..ebb78ce 100644
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/delivery/SieveExecutor.java
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/delivery/SieveExecutor.java
@@ -21,6 +21,7 @@
 package org.apache.james.transport.mailets.jsieve.delivery;
 
 import java.io.IOException;
+import java.util.Optional;
 
 import javax.mail.MessagingException;
 
@@ -36,6 +37,9 @@ import org.apache.jsieve.SieveFactory;
 import org.apache.jsieve.exception.SieveException;
 import org.apache.jsieve.parser.generated.ParseException;
 import org.apache.jsieve.parser.generated.TokenMgrError;
+import org.apache.mailet.Attribute;
+import org.apache.mailet.AttributeName;
+import org.apache.mailet.AttributeValue;
 import org.apache.mailet.Mail;
 import org.apache.mailet.MailetContext;
 import org.slf4j.Logger;
@@ -46,6 +50,7 @@ import com.google.common.collect.ImmutableList;
 
 public class SieveExecutor {
     private static final Logger LOGGER = LoggerFactory.getLogger(SieveExecutor.class);
+    public static final AttributeName SIEVE_NOTIFICATION = AttributeName.of("SieveNotification");
 
     public static Builder builder() {
         return new Builder();
@@ -114,7 +119,14 @@ public class SieveExecutor {
     public boolean execute(MailAddress recipient, Mail mail) throws MessagingException {
         Preconditions.checkNotNull(recipient, "Recipient for mail to be spooled cannot be null.");
         Preconditions.checkNotNull(mail.getMessage(), "Mail message to be spooled cannot be null.");
-
+        Optional<Attribute> oSieveNotification = mail.getAttribute(SIEVE_NOTIFICATION);
+        if (oSieveNotification.isPresent()) {
+            AttributeValue<Boolean> attrValue = (AttributeValue<Boolean>) oSieveNotification.get().getValue();
+            if (attrValue.value()) {
+                throw new MessagingException("Do not process Sieve error notification emails");
+            }
+        }
+        
         return sieveMessage(recipient, mail);
     }
 
@@ -150,6 +162,7 @@ public class SieveExecutor {
     }
 
     protected void handleFailure(MailAddress recipient, Mail aMail, Exception ex) throws MessagingException, IOException {
+        aMail.setAttribute(new Attribute(SIEVE_NOTIFICATION, AttributeValue.of(true)));
         mailetContext.sendMail(recipient, ImmutableList.of(recipient), SieveFailureMessageComposer.composeMessage(aMail, ex, recipient.toString()));
     }
 }
diff --git a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/delivery/SieveIntegrationTest.java b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/delivery/SieveIntegrationTest.java
index 9c5ea36..a287734 100644
--- a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/delivery/SieveIntegrationTest.java
+++ b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/delivery/SieveIntegrationTest.java
@@ -36,6 +36,7 @@ import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.sieverepository.api.exception.ScriptNotFoundException;
 import org.apache.james.transport.mailets.Sieve;
 import org.apache.james.transport.mailets.jsieve.ResourceLocator;
+import org.apache.james.transport.mailets.jsieve.delivery.SieveExecutor;
 import org.apache.james.user.api.UsersRepository;
 import org.apache.james.util.MimeMessageUtil;
 import org.apache.mailet.Attribute;
@@ -937,6 +938,15 @@ public class SieveIntegrationTest {
             .build();
         assertThat(fakeMailContext.getSentMails()).containsExactly(expectedSentMail);
     }
+    
+    @Test(expected = MessagingException.class)
+    public void sieveErrorNotificationEmailsShouldNotBeProcessed() throws Exception {
+        prepareTestUsingScript("org/apache/james/transport/mailets/delivery/keep.script");
+
+        FakeMail mail = createMail();
+        mail.setAttribute(new Attribute(SieveExecutor.SIEVE_NOTIFICATION, AttributeValue.of(true)));
+        testee.service(mail);
+    }
 
     private void prepareTestUsingScript(final String script) throws Exception {
         prepareTestUsingScriptAndDates(script, DATE_DEFAULT, DATE_DEFAULT);


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


[james-project] 10/10: JAMES-2666 Rename SwarmGenericContainer into DockerGenericContainer

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 15aa6985fa7f7c48dddd4a1356763a25c0c7b72e
Author: Rene Cordier <rc...@linagora.com>
AuthorDate: Tue Mar 19 11:43:38 2019 +0700

    JAMES-2666 Rename SwarmGenericContainer into DockerGenericContainer
---
 .../es/ClientProviderImplConnectionTest.java       |  6 +++---
 .../apache/james/mailbox/tika/TikaContainer.java   |  6 +++---
 .../apache/james/DockerElasticSearchExtension.java |  6 +++---
 .../james/JamesServerWithRetryConnectionTest.java  |  4 ++--
 .../metric/es/DockerElasticSearch2Extension.java   |  8 ++++----
 .../metric/es/DockerElasticSearch6Extension.java   |  8 ++++----
 .../apache/james/metric/es/ESReporterContract.java |  8 ++++----
 .../james/user/ldap/LdapGenericContainer.java      | 10 +++++-----
 .../mailets/AmqpForwardAttachmentTest.java         |  4 ++--
 .../transport/mailets/ContactExtractorTest.java    |  4 ++--
 .../mailets/ICSAttachmentWorkflowTest.java         |  4 ++--
 .../james/transport/mailets/SpamAssassinTest.java  |  4 ++--
 .../james/transport/mailets/amqp/AmqpRule.java     |  6 +++---
 .../java/org/apache/james/jmap/ContainerTest.java  |  4 ++--
 .../ReindexingWithEventDeadLettersTest.java        |  4 ++--
 ...cContainer.java => DockerGenericContainer.java} | 22 +++++++++++-----------
 .../main/java/org/apache/james/utils/FakeSmtp.java | 14 +++++++-------
 17 files changed, 61 insertions(+), 61 deletions(-)

diff --git a/backends-common/elasticsearch/src/test/java/org/apache/james/backends/es/ClientProviderImplConnectionTest.java b/backends-common/elasticsearch/src/test/java/org/apache/james/backends/es/ClientProviderImplConnectionTest.java
index ec3adf9..87d6f52 100644
--- a/backends-common/elasticsearch/src/test/java/org/apache/james/backends/es/ClientProviderImplConnectionTest.java
+++ b/backends-common/elasticsearch/src/test/java/org/apache/james/backends/es/ClientProviderImplConnectionTest.java
@@ -22,7 +22,7 @@ package org.apache.james.backends.es;
 import java.util.Optional;
 import java.util.concurrent.TimeUnit;
 
-import org.apache.james.util.docker.SwarmGenericContainer;
+import org.apache.james.util.docker.DockerGenericContainer;
 import org.awaitility.Awaitility;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.index.query.QueryBuilders;
@@ -39,12 +39,12 @@ public class ClientProviderImplConnectionTest {
     private static final int ES_APPLICATIVE_PORT = 9300;
 
     @Rule
-    public SwarmGenericContainer es1 = new SwarmGenericContainer(DOCKER_ES_IMAGE)
+    public DockerGenericContainer es1 = new DockerGenericContainer(DOCKER_ES_IMAGE)
         .withAffinityToContainer()
         .withExposedPorts(ES_APPLICATIVE_PORT);
 
     @Rule
-    public SwarmGenericContainer es2 = new SwarmGenericContainer(DOCKER_ES_IMAGE)
+    public DockerGenericContainer es2 = new DockerGenericContainer(DOCKER_ES_IMAGE)
         .withAffinityToContainer()
         .withExposedPorts(ES_APPLICATIVE_PORT);
 
diff --git a/mailbox/tika/src/test/java/org/apache/james/mailbox/tika/TikaContainer.java b/mailbox/tika/src/test/java/org/apache/james/mailbox/tika/TikaContainer.java
index aa2c0fe..89e23fc 100644
--- a/mailbox/tika/src/test/java/org/apache/james/mailbox/tika/TikaContainer.java
+++ b/mailbox/tika/src/test/java/org/apache/james/mailbox/tika/TikaContainer.java
@@ -21,9 +21,9 @@ package org.apache.james.mailbox.tika;
 import java.time.Duration;
 import java.util.concurrent.TimeUnit;
 
+import org.apache.james.util.docker.DockerGenericContainer;
 import org.apache.james.util.docker.Images;
 import org.apache.james.util.docker.RateLimiters;
-import org.apache.james.util.docker.SwarmGenericContainer;
 import org.junit.rules.ExternalResource;
 import org.testcontainers.containers.wait.strategy.Wait;
 
@@ -34,10 +34,10 @@ public class TikaContainer extends ExternalResource {
     private static final int DEFAULT_TIKA_PORT = 9998;
     private static final int DEFAULT_TIMEOUT_IN_MS = Ints.checkedCast(TimeUnit.MINUTES.toMillis(3));
 
-    private final SwarmGenericContainer tika;
+    private final DockerGenericContainer tika;
 
     public TikaContainer() {
-        tika = new SwarmGenericContainer(Images.TIKA)
+        tika = new DockerGenericContainer(Images.TIKA)
                 .withExposedPorts(DEFAULT_TIKA_PORT)
                 .waitingFor(Wait.forHttp("/tika").withRateLimiter(RateLimiters.TWENTIES_PER_SECOND))
                 .withStartupTimeout(Duration.ofSeconds(30));
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/DockerElasticSearchExtension.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/DockerElasticSearchExtension.java
index a25e34c..bfc755e 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/DockerElasticSearchExtension.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/DockerElasticSearchExtension.java
@@ -21,7 +21,7 @@ package org.apache.james;
 
 import org.apache.james.backends.es.ElasticSearchConfiguration;
 import org.apache.james.util.Host;
-import org.apache.james.util.docker.SwarmGenericContainer;
+import org.apache.james.util.docker.DockerGenericContainer;
 import org.junit.jupiter.api.extension.ExtensionContext;
 
 import com.google.inject.Module;
@@ -30,9 +30,9 @@ public class DockerElasticSearchExtension implements GuiceModuleTestExtension {
     public static final int ELASTIC_SEARCH_PORT = 9300;
     public static final int ELASTIC_SEARCH_HTTP_PORT = 9200;
 
-    private final SwarmGenericContainer elasticSearchContainer;
+    private final DockerGenericContainer elasticSearchContainer;
 
-    public DockerElasticSearchExtension(SwarmGenericContainer elasticSearchContainer) {
+    public DockerElasticSearchExtension(DockerGenericContainer elasticSearchContainer) {
         this.elasticSearchContainer = elasticSearchContainer;
     }
 
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesServerWithRetryConnectionTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesServerWithRetryConnectionTest.java
index 685f89a..85263de 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesServerWithRetryConnectionTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesServerWithRetryConnectionTest.java
@@ -39,8 +39,8 @@ import org.apache.james.mailbox.store.search.PDFTextExtractor;
 import org.apache.james.modules.TestJMAPServerModule;
 import org.apache.james.modules.protocols.ImapGuiceProbe;
 import org.apache.james.util.concurrent.NamedThreadFactory;
+import org.apache.james.util.docker.DockerGenericContainer;
 import org.apache.james.util.docker.Images;
-import org.apache.james.util.docker.SwarmGenericContainer;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -50,7 +50,7 @@ class JamesServerWithRetryConnectionTest {
     private static final int LIMIT_TO_10_MESSAGES = 10;
     private static final long WAITING_TIME = TimeUnit.MILLISECONDS.convert(10, TimeUnit.SECONDS);
 
-    private static SwarmGenericContainer elasticSearchContainer = new SwarmGenericContainer(Images.ELASTICSEARCH_2)
+    private static DockerGenericContainer elasticSearchContainer = new DockerGenericContainer(Images.ELASTICSEARCH_2)
         .withExposedPorts(ELASTIC_SEARCH_HTTP_PORT, ELASTIC_SEARCH_PORT);
     private static final DockerCassandraRule cassandraRule = new DockerCassandraRule();
 
diff --git a/server/container/metrics/metrics-es-reporter/src/test/java/org/apache/james/metric/es/DockerElasticSearch2Extension.java b/server/container/metrics/metrics-es-reporter/src/test/java/org/apache/james/metric/es/DockerElasticSearch2Extension.java
index 3a0b076..691db66 100644
--- a/server/container/metrics/metrics-es-reporter/src/test/java/org/apache/james/metric/es/DockerElasticSearch2Extension.java
+++ b/server/container/metrics/metrics-es-reporter/src/test/java/org/apache/james/metric/es/DockerElasticSearch2Extension.java
@@ -18,9 +18,9 @@
  ****************************************************************/
 package org.apache.james.metric.es;
 
+import org.apache.james.util.docker.DockerGenericContainer;
 import org.apache.james.util.docker.Images;
 import org.apache.james.util.docker.RateLimiters;
-import org.apache.james.util.docker.SwarmGenericContainer;
 import org.junit.jupiter.api.extension.AfterEachCallback;
 import org.junit.jupiter.api.extension.BeforeEachCallback;
 import org.junit.jupiter.api.extension.ExtensionContext;
@@ -30,10 +30,10 @@ import org.junit.jupiter.api.extension.ParameterResolver;
 import org.testcontainers.containers.wait.strategy.HostPortWaitStrategy;
 
 public class DockerElasticSearch2Extension implements ParameterResolver, BeforeEachCallback, AfterEachCallback {
-    private final SwarmGenericContainer elasticSearchContainer;
+    private final DockerGenericContainer elasticSearchContainer;
 
     private DockerElasticSearch2Extension() {
-        this.elasticSearchContainer = new SwarmGenericContainer(Images.ELASTICSEARCH_2)
+        this.elasticSearchContainer = new DockerGenericContainer(Images.ELASTICSEARCH_2)
             .withAffinityToContainer()
             .withExposedPorts(ESReporterContract.ES_HTTP_PORT)
             .waitingFor(new HostPortWaitStrategy().withRateLimiter(RateLimiters.TWENTIES_PER_SECOND));
@@ -51,7 +51,7 @@ public class DockerElasticSearch2Extension implements ParameterResolver, BeforeE
 
     @Override
     public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
-        return (parameterContext.getParameter().getType() == SwarmGenericContainer.class);
+        return (parameterContext.getParameter().getType() == DockerGenericContainer.class);
     }
 
     @Override
diff --git a/server/container/metrics/metrics-es-reporter/src/test/java/org/apache/james/metric/es/DockerElasticSearch6Extension.java b/server/container/metrics/metrics-es-reporter/src/test/java/org/apache/james/metric/es/DockerElasticSearch6Extension.java
index ab63089..fb58eaf 100644
--- a/server/container/metrics/metrics-es-reporter/src/test/java/org/apache/james/metric/es/DockerElasticSearch6Extension.java
+++ b/server/container/metrics/metrics-es-reporter/src/test/java/org/apache/james/metric/es/DockerElasticSearch6Extension.java
@@ -18,9 +18,9 @@
  ****************************************************************/
 package org.apache.james.metric.es;
 
+import org.apache.james.util.docker.DockerGenericContainer;
 import org.apache.james.util.docker.Images;
 import org.apache.james.util.docker.RateLimiters;
-import org.apache.james.util.docker.SwarmGenericContainer;
 import org.junit.jupiter.api.extension.AfterEachCallback;
 import org.junit.jupiter.api.extension.BeforeEachCallback;
 import org.junit.jupiter.api.extension.ExtensionContext;
@@ -30,10 +30,10 @@ import org.junit.jupiter.api.extension.ParameterResolver;
 import org.testcontainers.containers.wait.strategy.HostPortWaitStrategy;
 
 public class DockerElasticSearch6Extension implements ParameterResolver, BeforeEachCallback, AfterEachCallback {
-    private final SwarmGenericContainer elasticSearchContainer;
+    private final DockerGenericContainer elasticSearchContainer;
 
     private DockerElasticSearch6Extension() {
-        this.elasticSearchContainer = new SwarmGenericContainer(Images.ELASTICSEARCH_6)
+        this.elasticSearchContainer = new DockerGenericContainer(Images.ELASTICSEARCH_6)
             .withEnv("discovery.type", "single-node")
             .withAffinityToContainer()
             .withExposedPorts(ESReporterContract.ES_HTTP_PORT)
@@ -52,7 +52,7 @@ public class DockerElasticSearch6Extension implements ParameterResolver, BeforeE
 
     @Override
     public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
-        return (parameterContext.getParameter().getType() == SwarmGenericContainer.class);
+        return (parameterContext.getParameter().getType() == DockerGenericContainer.class);
     }
 
     @Override
diff --git a/server/container/metrics/metrics-es-reporter/src/test/java/org/apache/james/metric/es/ESReporterContract.java b/server/container/metrics/metrics-es-reporter/src/test/java/org/apache/james/metric/es/ESReporterContract.java
index 83ac4ed..3b0335f 100644
--- a/server/container/metrics/metrics-es-reporter/src/test/java/org/apache/james/metric/es/ESReporterContract.java
+++ b/server/container/metrics/metrics-es-reporter/src/test/java/org/apache/james/metric/es/ESReporterContract.java
@@ -32,7 +32,7 @@ import org.apache.james.metrics.api.TimeMetric;
 import org.apache.james.metrics.dropwizard.DropWizardMetricFactory;
 import org.apache.james.metrics.es.ESMetricReporter;
 import org.apache.james.metrics.es.ESReporterConfiguration;
-import org.apache.james.util.docker.SwarmGenericContainer;
+import org.apache.james.util.docker.DockerGenericContainer;
 import org.awaitility.Duration;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
@@ -54,7 +54,7 @@ abstract class ESReporterContract {
     private Timer timer;
 
     @BeforeEach
-    void setUp(SwarmGenericContainer esContainer) {
+    void setUp(DockerGenericContainer esContainer) {
         RestAssured.baseURI = String.format("http://%s:%d", esContainer.getHostIp(), esContainer.getMappedPort(ES_HTTP_PORT));
         await().atMost(Duration.ONE_MINUTE)
             .untilAsserted(() -> elasticSearchStarted());
@@ -80,7 +80,7 @@ abstract class ESReporterContract {
     }
 
     @Test
-    void esMetricReporterShouldProduceDocumentsOnAnElasticsearchContainer(SwarmGenericContainer esContainer) {
+    void esMetricReporterShouldProduceDocumentsOnAnElasticsearchContainer(DockerGenericContainer esContainer) {
         Metric metric = new DropWizardMetricFactory(registry).generate("probe");
         TimerTask timerTask = new TimerTask() {
             @Override
@@ -95,7 +95,7 @@ abstract class ESReporterContract {
     }
 
     @Test
-    void esMetricReporterShouldProduceDocumentsOnAnElasticsearchContainerWhenRecordingTimeMetric(SwarmGenericContainer esContainer) {
+    void esMetricReporterShouldProduceDocumentsOnAnElasticsearchContainerWhenRecordingTimeMetric(DockerGenericContainer esContainer) {
         TimeMetric metric = new DropWizardMetricFactory(registry).timer("itstime");
         TimerTask timerTask = new TimerTask() {
             @Override
diff --git a/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/LdapGenericContainer.java b/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/LdapGenericContainer.java
index 40ee62d..f2a53d7 100644
--- a/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/LdapGenericContainer.java
+++ b/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/LdapGenericContainer.java
@@ -18,8 +18,8 @@
  ****************************************************************/
 package org.apache.james.user.ldap;
 
+import org.apache.james.util.docker.DockerGenericContainer;
 import org.apache.james.util.docker.RateLimiters;
-import org.apache.james.util.docker.SwarmGenericContainer;
 import org.junit.rules.ExternalResource;
 import org.testcontainers.containers.wait.strategy.HostPortWaitStrategy;
 import org.testcontainers.images.builder.ImageFromDockerfile;
@@ -59,8 +59,8 @@ public class LdapGenericContainer extends ExternalResource {
             return new LdapGenericContainer(createContainer());
         }
 
-        private SwarmGenericContainer createContainer() {
-            return new SwarmGenericContainer(
+        private DockerGenericContainer createContainer() {
+            return new DockerGenericContainer(
                 new ImageFromDockerfile()
                     .withFileFromClasspath("populate.ldif", "ldif-files/populate.ldif")
                     .withFileFromClasspath("Dockerfile", "ldif-files/Dockerfile"))
@@ -73,9 +73,9 @@ public class LdapGenericContainer extends ExternalResource {
         }
     }
 
-    private final SwarmGenericContainer container;
+    private final DockerGenericContainer container;
 
-    private LdapGenericContainer(SwarmGenericContainer container) {
+    private LdapGenericContainer(DockerGenericContainer container) {
         this.container = container;
     }
 
diff --git a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/AmqpForwardAttachmentTest.java b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/AmqpForwardAttachmentTest.java
index b1ff14d..aec7593 100644
--- a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/AmqpForwardAttachmentTest.java
+++ b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/AmqpForwardAttachmentTest.java
@@ -39,9 +39,9 @@ import org.apache.james.modules.protocols.SmtpGuiceProbe;
 import org.apache.james.probe.DataProbe;
 import org.apache.james.transport.mailets.amqp.AmqpRule;
 import org.apache.james.transport.matchers.All;
+import org.apache.james.util.docker.DockerGenericContainer;
 import org.apache.james.util.docker.Images;
 import org.apache.james.util.docker.RateLimiters;
-import org.apache.james.util.docker.SwarmGenericContainer;
 import org.apache.james.utils.DataProbeImpl;
 import org.apache.james.utils.IMAPMessageReader;
 import org.apache.james.utils.SMTPMessageSender;
@@ -64,7 +64,7 @@ public class AmqpForwardAttachmentTest {
     
     private static final byte[] TEST_ATTACHMENT_CONTENT = "Test attachment content".getBytes(StandardCharsets.UTF_8);
 
-    public SwarmGenericContainer rabbitMqContainer = new SwarmGenericContainer(Images.RABBITMQ)
+    public DockerGenericContainer rabbitMqContainer = new DockerGenericContainer(Images.RABBITMQ)
         .withAffinityToContainer()
         .waitingFor(new HostPortWaitStrategy()
             .withRateLimiter(RateLimiters.TWENTIES_PER_SECOND));
diff --git a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/ContactExtractorTest.java b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/ContactExtractorTest.java
index 216296a..9f49150 100644
--- a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/ContactExtractorTest.java
+++ b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/ContactExtractorTest.java
@@ -39,9 +39,9 @@ import org.apache.james.modules.protocols.SmtpGuiceProbe;
 import org.apache.james.transport.mailets.amqp.AmqpRule;
 import org.apache.james.transport.matchers.All;
 import org.apache.james.transport.matchers.SMTPAuthSuccessful;
+import org.apache.james.util.docker.DockerGenericContainer;
 import org.apache.james.util.docker.Images;
 import org.apache.james.util.docker.RateLimiters;
-import org.apache.james.util.docker.SwarmGenericContainer;
 import org.apache.james.utils.DataProbeImpl;
 import org.apache.james.utils.IMAPMessageReader;
 import org.apache.james.utils.SMTPMessageSender;
@@ -65,7 +65,7 @@ public class ContactExtractorTest {
     public static final String EXCHANGE = "collector:email";
     public static final String ROUTING_KEY = "";
 
-    public SwarmGenericContainer rabbit = new SwarmGenericContainer(Images.RABBITMQ)
+    public DockerGenericContainer rabbit = new DockerGenericContainer(Images.RABBITMQ)
         .waitingFor(new HostPortWaitStrategy().withRateLimiter(RateLimiters.TWENTIES_PER_SECOND));
     public AmqpRule amqpRule = new AmqpRule(rabbit, EXCHANGE, ROUTING_KEY);
     public TemporaryFolder folder = new TemporaryFolder();
diff --git a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/ICSAttachmentWorkflowTest.java b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/ICSAttachmentWorkflowTest.java
index 0231813..681dc0a 100644
--- a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/ICSAttachmentWorkflowTest.java
+++ b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/ICSAttachmentWorkflowTest.java
@@ -44,9 +44,9 @@ import org.apache.james.probe.DataProbe;
 import org.apache.james.transport.mailets.amqp.AmqpRule;
 import org.apache.james.transport.matchers.All;
 import org.apache.james.util.MimeMessageUtil;
+import org.apache.james.util.docker.DockerGenericContainer;
 import org.apache.james.util.docker.Images;
 import org.apache.james.util.docker.RateLimiters;
-import org.apache.james.util.docker.SwarmGenericContainer;
 import org.apache.james.utils.DataProbeImpl;
 import org.apache.james.utils.IMAPMessageReader;
 import org.apache.james.utils.SMTPMessageSender;
@@ -429,7 +429,7 @@ public class ICSAttachmentWorkflowTest {
             "";
 
     @ClassRule
-    public static SwarmGenericContainer rabbitMqContainer = new SwarmGenericContainer(Images.RABBITMQ)
+    public static DockerGenericContainer rabbitMqContainer = new DockerGenericContainer(Images.RABBITMQ)
         .withAffinityToContainer()
         .waitingFor(new HostPortWaitStrategy().withRateLimiter(RateLimiters.TWENTIES_PER_SECOND));
     @Rule
diff --git a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java
index a812472..52fc782 100644
--- a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java
+++ b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java
@@ -40,9 +40,9 @@ import org.apache.james.modules.protocols.ImapGuiceProbe;
 import org.apache.james.modules.protocols.SmtpGuiceProbe;
 import org.apache.james.spamassassin.SpamAssassinResult;
 import org.apache.james.transport.matchers.All;
+import org.apache.james.util.docker.DockerGenericContainer;
 import org.apache.james.util.docker.Images;
 import org.apache.james.util.docker.RateLimiters;
-import org.apache.james.util.docker.SwarmGenericContainer;
 import org.apache.james.utils.DataProbeImpl;
 import org.apache.james.utils.IMAPMessageReader;
 import org.apache.james.utils.SMTPMessageSender;
@@ -59,7 +59,7 @@ public class SpamAssassinTest {
     private static final String SPAM_CONTENT = "XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X";
 
     @ClassRule
-    public static SwarmGenericContainer spamAssassinContainer = new SwarmGenericContainer(Images.SPAMASSASSIN)
+    public static DockerGenericContainer spamAssassinContainer = new DockerGenericContainer(Images.SPAMASSASSIN)
         .withExposedPorts(783)
         .withAffinityToContainer()
         .waitingFor(new HostPortWaitStrategy().withRateLimiter(RateLimiters.TWENTIES_PER_SECOND));
diff --git a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/amqp/AmqpRule.java b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/amqp/AmqpRule.java
index 1527888..c3bda87 100644
--- a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/amqp/AmqpRule.java
+++ b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/amqp/AmqpRule.java
@@ -25,7 +25,7 @@ import java.util.Optional;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
-import org.apache.james.util.docker.SwarmGenericContainer;
+import org.apache.james.util.docker.DockerGenericContainer;
 import org.awaitility.Awaitility;
 import org.junit.rules.ExternalResource;
 
@@ -39,7 +39,7 @@ public class AmqpRule extends ExternalResource {
 
     private static final boolean AUTO_ACK = true;
 
-    private final SwarmGenericContainer rabbitMqContainer;
+    private final DockerGenericContainer rabbitMqContainer;
     private final String exchangeName;
     private final String routingKey;
     private Channel channel;
@@ -47,7 +47,7 @@ public class AmqpRule extends ExternalResource {
     private Connection connection;
     private String amqpUri;
 
-    public AmqpRule(SwarmGenericContainer rabbitMqContainer, String exchangeName, String routingKey) {
+    public AmqpRule(DockerGenericContainer rabbitMqContainer, String exchangeName, String routingKey) {
         this.rabbitMqContainer = rabbitMqContainer;
         this.exchangeName = exchangeName;
         this.routingKey = routingKey;
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/ContainerTest.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/ContainerTest.java
index d95a891..b7674ca 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/ContainerTest.java
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/ContainerTest.java
@@ -26,9 +26,9 @@ import java.net.URISyntaxException;
 import org.apache.http.client.fluent.Request;
 import org.apache.http.client.fluent.Response;
 import org.apache.http.client.utils.URIBuilder;
+import org.apache.james.util.docker.DockerGenericContainer;
 import org.apache.james.util.docker.Images;
 import org.apache.james.util.docker.RateLimiters;
-import org.apache.james.util.docker.SwarmGenericContainer;
 import org.junit.Rule;
 import org.junit.Test;
 import org.testcontainers.containers.wait.strategy.HttpWaitStrategy;
@@ -36,7 +36,7 @@ import org.testcontainers.containers.wait.strategy.HttpWaitStrategy;
 public class ContainerTest {
 
     @Rule
-    public SwarmGenericContainer container = new SwarmGenericContainer(Images.NGINX)
+    public DockerGenericContainer container = new DockerGenericContainer(Images.NGINX)
         .withAffinityToContainer()
         .withExposedPorts(80)
         .waitingFor(new HttpWaitStrategy()
diff --git a/server/protocols/jmap-integration-testing/rabbitmq-jmap-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/ReindexingWithEventDeadLettersTest.java b/server/protocols/jmap-integration-testing/rabbitmq-jmap-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/ReindexingWithEventDeadLettersTest.java
index 490cbcd..93413ac 100644
--- a/server/protocols/jmap-integration-testing/rabbitmq-jmap-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/ReindexingWithEventDeadLettersTest.java
+++ b/server/protocols/jmap-integration-testing/rabbitmq-jmap-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/ReindexingWithEventDeadLettersTest.java
@@ -47,8 +47,8 @@ import org.apache.james.modules.RabbitMQExtension;
 import org.apache.james.modules.SwiftBlobStoreExtension;
 import org.apache.james.modules.TestJMAPServerModule;
 import org.apache.james.modules.objectstorage.PayloadCodecFactory;
+import org.apache.james.util.docker.DockerGenericContainer;
 import org.apache.james.util.docker.Images;
-import org.apache.james.util.docker.SwarmGenericContainer;
 import org.apache.james.utils.DataProbeImpl;
 import org.apache.james.utils.JmapGuiceProbe;
 import org.apache.james.utils.WebAdminGuiceProbe;
@@ -75,7 +75,7 @@ class ReindexingWithEventDeadLettersTest {
         .atMost(Duration.ONE_MINUTE)
         .await();
 
-    private static SwarmGenericContainer elasticSearchContainer = new SwarmGenericContainer(Images.ELASTICSEARCH_2)
+    private static DockerGenericContainer elasticSearchContainer = new DockerGenericContainer(Images.ELASTICSEARCH_2)
         .withExposedPorts(ELASTIC_SEARCH_HTTP_PORT, ELASTIC_SEARCH_PORT);
 
     private static final JamesServerBuilder.ServerProvider CONFIGURATION_BUILDER = configuration -> GuiceJamesServer
diff --git a/server/testing/src/main/java/org/apache/james/util/docker/SwarmGenericContainer.java b/server/testing/src/main/java/org/apache/james/util/docker/DockerGenericContainer.java
similarity index 88%
rename from server/testing/src/main/java/org/apache/james/util/docker/SwarmGenericContainer.java
rename to server/testing/src/main/java/org/apache/james/util/docker/DockerGenericContainer.java
index 2c4ccc1..62401fb 100644
--- a/server/testing/src/main/java/org/apache/james/util/docker/SwarmGenericContainer.java
+++ b/server/testing/src/main/java/org/apache/james/util/docker/DockerGenericContainer.java
@@ -40,15 +40,15 @@ import com.github.dockerjava.api.command.InspectContainerResponse;
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableList;
 
-public class SwarmGenericContainer implements TestRule {
-    private static final Logger LOGGER = LoggerFactory.getLogger(SwarmGenericContainer.class);
+public class DockerGenericContainer implements TestRule {
+    private static final Logger LOGGER = LoggerFactory.getLogger(DockerGenericContainer.class);
     private static final String DOCKER_CONTAINER = "DOCKER_CONTAINER";
     private static final String NO_DOCKER_ENVIRONMENT = "Could not find a valid Docker environment.";
     private static final String SKIPPING_TEST_CAUTION = "Skipping all docker tests as no Docker environment was found";
 
     private GenericContainer<?> container;
 
-    public SwarmGenericContainer(String dockerImageName) {
+    public DockerGenericContainer(String dockerImageName) {
         try {
             this.container = new GenericContainer<>(dockerImageName);
         } catch (IllegalStateException e) {
@@ -56,7 +56,7 @@ public class SwarmGenericContainer implements TestRule {
         }
     }
 
-    public SwarmGenericContainer(ImageFromDockerfile imageFromDockerfile) {
+    public DockerGenericContainer(ImageFromDockerfile imageFromDockerfile) {
         try {
             this.container = new GenericContainer<>(imageFromDockerfile);
         } catch (IllegalStateException e) {
@@ -71,7 +71,7 @@ public class SwarmGenericContainer implements TestRule {
         }
     }
 
-    public SwarmGenericContainer withAffinityToContainer() {
+    public DockerGenericContainer withAffinityToContainer() {
         String containerEnv = System.getenv(DOCKER_CONTAINER);
         if (Strings.isNullOrEmpty(containerEnv)) {
             LOGGER.warn("'DOCKER_CONTAINER' environment variable not found, dockering without affinity");
@@ -83,32 +83,32 @@ public class SwarmGenericContainer implements TestRule {
         return this;
     }
 
-    public SwarmGenericContainer withEnv(String key, String value) {
+    public DockerGenericContainer withEnv(String key, String value) {
         container.addEnv(key, value);
         return this;
     }
 
-    public SwarmGenericContainer withExposedPorts(Integer... ports) {
+    public DockerGenericContainer withExposedPorts(Integer... ports) {
         container.withExposedPorts(ports);
         return this;
     }
 
-    public SwarmGenericContainer portBinding(int hostPort, int dockerPort) {
+    public DockerGenericContainer portBinding(int hostPort, int dockerPort) {
         container.setPortBindings(ImmutableList.of("0.0.0.0:" + hostPort + ":" + dockerPort));
         return this;
     }
 
-    public SwarmGenericContainer waitingFor(WaitStrategy waitStrategy) {
+    public DockerGenericContainer waitingFor(WaitStrategy waitStrategy) {
         container.waitingFor(waitStrategy);
         return this;
     }
 
-    public SwarmGenericContainer withStartupTimeout(Duration startupTimeout) {
+    public DockerGenericContainer withStartupTimeout(Duration startupTimeout) {
         container.withStartupTimeout(startupTimeout);
         return this;
     }
 
-    public SwarmGenericContainer withCommands(String... commands) {
+    public DockerGenericContainer withCommands(String... commands) {
         container.withCommand(commands);
         return this;
     }
diff --git a/server/testing/src/main/java/org/apache/james/utils/FakeSmtp.java b/server/testing/src/main/java/org/apache/james/utils/FakeSmtp.java
index 8aa4571..c94e742 100644
--- a/server/testing/src/main/java/org/apache/james/utils/FakeSmtp.java
+++ b/server/testing/src/main/java/org/apache/james/utils/FakeSmtp.java
@@ -26,9 +26,9 @@ import static io.restassured.config.RestAssuredConfig.newConfig;
 import java.nio.charset.StandardCharsets;
 import java.util.function.Function;
 
+import org.apache.james.util.docker.DockerGenericContainer;
 import org.apache.james.util.docker.Images;
 import org.apache.james.util.docker.RateLimiters;
-import org.apache.james.util.docker.SwarmGenericContainer;
 import org.awaitility.core.ConditionFactory;
 import org.junit.rules.TestRule;
 import org.junit.runner.Description;
@@ -45,14 +45,14 @@ import io.restassured.specification.ResponseSpecification;
 public class FakeSmtp implements TestRule {
 
     public static FakeSmtp withSmtpPort(Integer smtpPort) {
-        SwarmGenericContainer container = fakeSmtpContainer()
+        DockerGenericContainer container = fakeSmtpContainer()
             .withCommands("node", "cli", "--listen", "80", "--smtp", smtpPort.toString());
 
         return new FakeSmtp(container, smtpPort);
     }
 
-    private static SwarmGenericContainer fakeSmtpContainer() {
-        return new SwarmGenericContainer(Images.FAKE_SMTP)
+    private static DockerGenericContainer fakeSmtpContainer() {
+        return new DockerGenericContainer(Images.FAKE_SMTP)
             .withAffinityToContainer()
             .waitingFor(new HostPortWaitStrategy()
             .withRateLimiter(RateLimiters.TWENTIES_PER_SECOND));
@@ -60,14 +60,14 @@ public class FakeSmtp implements TestRule {
 
     private static final int SMTP_PORT = 25;
     private static final ResponseSpecification RESPONSE_SPECIFICATION = new ResponseSpecBuilder().build();
-    private final SwarmGenericContainer container;
+    private final DockerGenericContainer container;
     private final Integer smtpPort;
 
     public FakeSmtp() {
         this(fakeSmtpContainer().withExposedPorts(SMTP_PORT), SMTP_PORT);
     }
 
-    private FakeSmtp(SwarmGenericContainer container, Integer smtpPort) {
+    private FakeSmtp(DockerGenericContainer container, Integer smtpPort) {
         this.smtpPort = smtpPort;
         this.container = container;
     }
@@ -99,7 +99,7 @@ public class FakeSmtp implements TestRule {
             .build();
     }
 
-    public SwarmGenericContainer getContainer() {
+    public DockerGenericContainer getContainer() {
         return container;
     }
 


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


[james-project] 09/10: JAMES-2682 Fix checkstyle

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 975b9bc32b3e8d8269ccd816e4e59e341b8fa478
Author: Pablo Pita <pa...@gmail.com>
AuthorDate: Mon Mar 18 20:20:15 2019 +0100

    JAMES-2682 Fix checkstyle
---
 .../james/transport/mailets/jsieve/delivery/SieveExecutor.java      | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/delivery/SieveExecutor.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/delivery/SieveExecutor.java
index 3fed2ff..cdcc51d 100644
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/delivery/SieveExecutor.java
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/delivery/SieveExecutor.java
@@ -21,7 +21,6 @@
 package org.apache.james.transport.mailets.jsieve.delivery;
 
 import java.io.IOException;
-import java.util.Optional;
 
 import javax.mail.MessagingException;
 
@@ -121,10 +120,7 @@ public class SieveExecutor {
         Preconditions.checkNotNull(recipient, "Recipient for mail to be spooled cannot be null.");
         Preconditions.checkNotNull(mail.getMessage(), "Mail message to be spooled cannot be null.");
         boolean isSieveNotification = AttributeUtils.getValueAndCastFromMail(mail, SIEVE_NOTIFICATION, Boolean.class).orElse(false);
-        if (isSieveNotification) {
-           	return false;
-        }
-        return sieveMessage(recipient, mail);
+        return !isSieveNotification ? sieveMessage(recipient, mail) : false;
     }
 
     protected boolean sieveMessage(MailAddress recipient, Mail aMail) throws MessagingException {


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


[james-project] 01/10: MAILBOX-385 Adding size field to DeletedMessage

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 84ef261b3b45db0e64b4693374cf9df7fe19581d
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Thu Mar 14 11:15:40 2019 +0700

    MAILBOX-385 Adding size field to DeletedMessage
    
    To be used in the Zipper size extra field latter. This step avoids to
    calculate deleted message content size from the InputStream, we can get
    it directly from the DeletedMessage.
---
 .../org/apache/james/vault/DeletedMessage.java     | 38 +++++++++++++++++-----
 .../james/vault/DeletedMessageConverter.java       |  1 +
 .../james/vault/DeletedMessageConverterTest.java   |  8 +++--
 .../apache/james/vault/DeletedMessageFixture.java  |  4 ++-
 .../org/apache/james/vault/DeletedMessageTest.java |  2 ++
 .../james/vault/DeletedMessageVaultHookTest.java   | 30 ++++++++++++-----
 .../vault/DeletedMessageVaultSearchContract.java   |  7 +++-
 .../apache/james/mailbox/store/MessageBuilder.java |  7 +++-
 .../java/org/apache/james/vault/MailConverter.java | 24 ++++++++++++++
 .../routes/DeletedMessagesVaultRoutesTest.java     | 19 +++++------
 10 files changed, 108 insertions(+), 32 deletions(-)

diff --git a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessage.java b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessage.java
index dd320d6..110c191 100644
--- a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessage.java
+++ b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessage.java
@@ -94,6 +94,11 @@ public class DeletedMessage {
             }
         }
 
+        @FunctionalInterface
+        public interface RequireSize<T> {
+            T size(long size);
+        }
+
         interface Steps {
             interface RequireMailboxContext<T> extends RequireMessageId<RequireOriginMailboxes<RequireUser<T>>> {}
 
@@ -101,7 +106,7 @@ public class DeletedMessage {
 
             interface RequireDates<T> extends RequireDeliveryDate<RequireDeletionDate<T>> {}
 
-            interface RequireMetadata<T> extends RequireMailboxContext<RequireDates<RequireEnvelope<RequireHasAttachment<T>>>> {}
+            interface RequireMetadata<T> extends RequireMailboxContext<RequireDates<RequireEnvelope<RequireHasAttachment<RequireSize<T>>>>> {}
         }
 
         public static class FinalStage {
@@ -113,10 +118,11 @@ public class DeletedMessage {
             private final MaybeSender sender;
             private final List<MailAddress> recipients;
             private final boolean hasAttachment;
+            private final long size;
             private Optional<String> subject;
 
             FinalStage(MessageId messageId, List<MailboxId> originMailboxes, User owner, ZonedDateTime deliveryDate,
-                       ZonedDateTime deletionDate, MaybeSender sender, List<MailAddress> recipients, boolean hasAttachment) {
+                       ZonedDateTime deletionDate, MaybeSender sender, List<MailAddress> recipients, boolean hasAttachment, long size) {
                 this.messageId = messageId;
                 this.originMailboxes = originMailboxes;
                 this.owner = owner;
@@ -125,6 +131,7 @@ public class DeletedMessage {
                 this.sender = sender;
                 this.recipients = recipients;
                 this.hasAttachment = hasAttachment;
+                this.size = size;
                 this.subject = Optional.empty();
             }
 
@@ -140,14 +147,14 @@ public class DeletedMessage {
 
             public DeletedMessage build() {
                 return new DeletedMessage(messageId, originMailboxes, owner, deliveryDate, deletionDate, sender,
-                    recipients, subject, hasAttachment);
+                    recipients, subject, hasAttachment, size);
             }
         }
     }
 
     public static RequireMetadata<FinalStage> builder() {
-        return messageId -> originMailboxes -> user -> deliveryDate -> deletionDate -> sender -> recipients -> hasAttachment ->
-            new Builder.FinalStage(messageId, originMailboxes, user, deliveryDate, deletionDate, sender, ImmutableList.copyOf(recipients), hasAttachment);
+        return messageId -> originMailboxes -> user -> deliveryDate -> deletionDate -> sender -> recipients -> hasAttachment -> size ->
+            new Builder.FinalStage(messageId, originMailboxes, user, deliveryDate, deletionDate, sender, ImmutableList.copyOf(recipients), hasAttachment, size);
     }
 
     private final MessageId messageId;
@@ -159,10 +166,11 @@ public class DeletedMessage {
     private final List<MailAddress> recipients;
     private final Optional<String> subject;
     private final boolean hasAttachment;
+    private final long size;
 
     public DeletedMessage(MessageId messageId, List<MailboxId> originMailboxes, User owner,
                           ZonedDateTime deliveryDate, ZonedDateTime deletionDate, MaybeSender sender, List<MailAddress> recipients,
-                          Optional<String> subject, boolean hasAttachment) {
+                          Optional<String> subject, boolean hasAttachment, long size) {
         this.messageId = messageId;
         this.originMailboxes = originMailboxes;
         this.owner = owner;
@@ -172,6 +180,7 @@ public class DeletedMessage {
         this.recipients = recipients;
         this.subject = subject;
         this.hasAttachment = hasAttachment;
+        this.size = size;
     }
 
     public MessageId getMessageId() {
@@ -210,6 +219,10 @@ public class DeletedMessage {
         return hasAttachment;
     }
 
+    public long getSize() {
+        return size;
+    }
+
     @Override
     public final boolean equals(Object o) {
         if (o instanceof DeletedMessage) {
@@ -223,7 +236,8 @@ public class DeletedMessage {
                 && Objects.equals(this.deletionDate, that.deletionDate)
                 && Objects.equals(this.sender, that.sender)
                 && Objects.equals(this.recipients, that.recipients)
-                && Objects.equals(this.subject, that.subject);
+                && Objects.equals(this.subject, that.subject)
+                && Objects.equals(this.size, that.size);
         }
         return false;
     }
@@ -231,7 +245,7 @@ public class DeletedMessage {
     @Override
     public final int hashCode() {
         return Objects.hash(messageId, originMailboxes, owner, deliveryDate, deletionDate, sender, recipients,
-            subject, hasAttachment);
+            subject, hasAttachment, size);
     }
 
     @Override
@@ -239,6 +253,14 @@ public class DeletedMessage {
         return MoreObjects.toStringHelper(this)
             .add("owner", owner)
             .add("messageId", messageId)
+            .add("originMailboxes", originMailboxes)
+            .add("owner", owner)
+            .add("deliveryDate", deliveryDate)
+            .add("deletionDate", deletionDate)
+            .add("sender", sender)
+            .add("recipients", recipients)
+            .add("subject", subject)
+            .add("size", size)
             .toString();
     }
 }
diff --git a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessageConverter.java b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessageConverter.java
index 6360fa7..105929b 100644
--- a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessageConverter.java
+++ b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessageConverter.java
@@ -61,6 +61,7 @@ class DeletedMessageConverter {
             .sender(retrieveSender(mimeMessage))
             .recipients(retrieveRecipients(mimeMessage))
             .hasAttachment(!message.getAttachments().isEmpty())
+            .size(message.getBodyOctets() + message.getHeaderOctets())
             .subject(mimeMessage.map(Message::getSubject))
             .build();
     }
diff --git a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageConverterTest.java b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageConverterTest.java
index 9cea8d0..ee1c501 100644
--- a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageConverterTest.java
+++ b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageConverterTest.java
@@ -19,6 +19,7 @@
 
 package org.apache.james.vault;
 
+import static org.apache.james.vault.DeletedMessageFixture.CONTENT;
 import static org.apache.james.vault.DeletedMessageFixture.DELETED_MESSAGE;
 import static org.apache.james.vault.DeletedMessageFixture.DELETED_MESSAGE_WITH_SUBJECT;
 import static org.apache.james.vault.DeletedMessageFixture.DELETION_DATE;
@@ -91,11 +92,14 @@ class DeletedMessageConverterTest {
     }
 
     private MailboxMessage buildMessage(MessageBuilder messageBuilder, Collection<MessageAttachment> attachments) throws Exception {
-        MailboxMessage mailboxMessage = messageBuilder.build(MESSAGE_ID);
+        MailboxMessage mailboxMessage = messageBuilder
+            .size(CONTENT.length)
+            .build(MESSAGE_ID);
         return SimpleMailboxMessage.fromWithoutAttachments(mailboxMessage)
             .mailboxId(mailboxMessage.getMailboxId())
             .internalDate(Date.from(DELIVERY_DATE.toInstant()))
-            .addAttachments(attachments).build();
+            .addAttachments(attachments)
+            .build();
     }
 
     @BeforeEach
diff --git a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageFixture.java b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageFixture.java
index d2e5c31..ee3016c 100644
--- a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageFixture.java
+++ b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageFixture.java
@@ -57,6 +57,7 @@ public interface DeletedMessageFixture {
         .sender(MaybeSender.of(SENDER))
         .recipients(RECIPIENT1, RECIPIENT2)
         .hasAttachment(false)
+        .size(CONTENT.length)
         .build();
     Supplier<DeletedMessage.Builder.FinalStage> FINAL_STAGE = () -> DeletedMessage.builder()
         .messageId(MESSAGE_ID)
@@ -66,7 +67,8 @@ public interface DeletedMessageFixture {
         .deletionDate(DELETION_DATE)
         .sender(MaybeSender.of(SENDER))
         .recipients(RECIPIENT1, RECIPIENT2)
-        .hasAttachment(false);
+        .hasAttachment(false)
+        .size(CONTENT.length);
     DeletedMessage DELETED_MESSAGE_WITH_SUBJECT = FINAL_STAGE.get()
         .subject(SUBJECT)
         .build();
diff --git a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageTest.java b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageTest.java
index 049b561..e6e35bf 100644
--- a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageTest.java
+++ b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageTest.java
@@ -19,6 +19,7 @@
 
 package org.apache.james.vault;
 
+import static org.apache.james.vault.DeletedMessageFixture.CONTENT;
 import static org.apache.james.vault.DeletedMessageFixture.DELETED_MESSAGE;
 import static org.apache.james.vault.DeletedMessageFixture.DELETED_MESSAGE_WITH_SUBJECT;
 import static org.apache.james.vault.DeletedMessageFixture.DELETION_DATE;
@@ -58,6 +59,7 @@ class DeletedMessageTest {
                 soft.assertThat(DELETED_MESSAGE.getSender()).isEqualTo(MaybeSender.of(SENDER));
                 soft.assertThat(DELETED_MESSAGE.getRecipients()).containsOnly(RECIPIENT1, RECIPIENT2);
                 soft.assertThat(DELETED_MESSAGE.hasAttachment()).isFalse();
+                soft.assertThat(DELETED_MESSAGE.getSize()).isEqualTo(CONTENT.length);
                 soft.assertThat(DELETED_MESSAGE.getSubject()).isEmpty();
             }
         );
diff --git a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageVaultHookTest.java b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageVaultHookTest.java
index 20e2201..26c3ca4 100644
--- a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageVaultHookTest.java
+++ b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageVaultHookTest.java
@@ -36,12 +36,15 @@ import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.MessageIdManager;
 import org.apache.james.mailbox.MessageManager;
+import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
 import org.apache.james.mailbox.model.ComposedMessageId;
+import org.apache.james.mailbox.model.FetchGroupImpl;
 import org.apache.james.mailbox.model.MailboxACL;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MessageId;
+import org.apache.james.mailbox.model.MessageRange;
 import org.apache.james.mailbox.model.SearchQuery;
 import org.apache.james.mime4j.dom.Message;
 import org.apache.james.vault.memory.MemoryDeletedMessagesVault;
@@ -58,6 +61,7 @@ class DeletedMessageVaultHookTest {
     private static final String TEST_ADDRESS = "test@james.com";
     private static final User ALICE = User.fromUsername(ALICE_ADDRESS);
     private static final User BOB = User.fromUsername(BOB_ADDRESS);
+    private static final String MESSAGE_BODY = "testmail";
 
     private static final MailboxPath MAILBOX_ALICE_ONE = MailboxPath.forUser(ALICE_ADDRESS, "ALICE_ONE");
     private static final MailboxPath MAILBOX_BOB_ONE = MailboxPath.forUser(BOB_ADDRESS, "BOB_ONE");
@@ -71,7 +75,7 @@ class DeletedMessageVaultHookTest {
     private MailboxSession bobSession;
     private SearchQuery searchQuery;
 
-    private DeletedMessage buildDeletedMessage(List<MailboxId> mailboxIds, MessageId messageId, User user) throws Exception {
+    private DeletedMessage buildDeletedMessage(List<MailboxId> mailboxIds, MessageId messageId, User user, long messageSize) throws Exception {
         return DeletedMessage.builder()
             .messageId(messageId)
             .originMailboxes(mailboxIds)
@@ -81,6 +85,7 @@ class DeletedMessageVaultHookTest {
             .sender(MaybeSender.getMailSender(ALICE_ADDRESS))
             .recipients(new MailAddress(TEST_ADDRESS))
             .hasAttachment(false)
+            .size(messageSize)
             .subject("test")
             .build();
     }
@@ -114,7 +119,7 @@ class DeletedMessageVaultHookTest {
 
         mailContent = Message.Builder.of()
             .setSubject("test")
-            .setBody("testmail", StandardCharsets.UTF_8)
+            .setBody(MESSAGE_BODY, StandardCharsets.UTF_8)
             .setSender(ALICE_ADDRESS)
             .setTo(TEST_ADDRESS)
             .setDate(INTERNAL_DATE)
@@ -131,11 +136,13 @@ class DeletedMessageVaultHookTest {
     void notifyDeleteShouldAppendMessageVault() throws Exception {
         MailboxId aliceMailbox = mailboxManager.createMailbox(MAILBOX_ALICE_ONE, aliceSession).get();
         MessageManager messageManager = mailboxManager.getMailbox(aliceMailbox, aliceSession);
-        MessageId messageId = appendMessage(messageManager).getMessageId();
+        ComposedMessageId composedId = appendMessage(messageManager);
+        MessageId messageId = composedId.getMessageId();
+        long messageSize = messageSize(messageManager, composedId);
 
         messageIdManager.delete(ImmutableList.of(messageId), aliceSession);
 
-        DeletedMessage deletedMessage = buildDeletedMessage(ImmutableList.of(aliceMailbox), messageId, ALICE);
+        DeletedMessage deletedMessage = buildDeletedMessage(ImmutableList.of(aliceMailbox), messageId, ALICE, messageSize);
         assertThat(messageVault.search(ALICE, Query.ALL).blockFirst())
             .isEqualTo(deletedMessage);
     }
@@ -155,9 +162,9 @@ class DeletedMessageVaultHookTest {
         MessageManager bobMessageManager = mailboxManager.getMailbox(aliceMailbox, bobSession);
         ComposedMessageId composedMessageId = appendMessage(aliceMessageManager);
         MessageId messageId = composedMessageId.getMessageId();
+        long messageSize = messageSize(bobMessageManager, composedMessageId);
 
-
-        DeletedMessage deletedMessage = buildDeletedMessage(ImmutableList.of(aliceMailbox), messageId, ALICE);
+        DeletedMessage deletedMessage = buildDeletedMessage(ImmutableList.of(aliceMailbox), messageId, ALICE, messageSize);
         bobMessageManager.delete(ImmutableList.copyOf(bobMessageManager.search(searchQuery, bobSession)), bobSession);
 
         assertThat(messageVault.search(ALICE, Query.ALL).blockFirst())
@@ -203,7 +210,8 @@ class DeletedMessageVaultHookTest {
 
         messageIdManager.setInMailboxes(messageId, ImmutableList.of(bobMailbox), bobSession);
 
-        DeletedMessage deletedMessage = buildDeletedMessage(ImmutableList.of(bobMailbox), messageId, BOB);
+        long messageSize = messageSize(bobMessageManager, composedMessageId);
+        DeletedMessage deletedMessage = buildDeletedMessage(ImmutableList.of(bobMailbox), messageId, BOB, messageSize);
         bobMessageManager.delete(ImmutableList.copyOf(bobMessageManager.search(searchQuery, bobSession)), bobSession);
 
         assertThat(messageVault.search(BOB, Query.ALL).blockFirst())
@@ -252,7 +260,8 @@ class DeletedMessageVaultHookTest {
 
         messageIdManager.setInMailboxes(messageId, ImmutableList.of(aliceMailbox, bobMailbox), bobSession);
 
-        DeletedMessage deletedMessage = buildDeletedMessage(ImmutableList.of(bobMailbox), messageId, BOB);
+        long messageSize = messageSize(bobMessageManager, composedMessageId);
+        DeletedMessage deletedMessage = buildDeletedMessage(ImmutableList.of(bobMailbox), messageId, BOB, messageSize);
         bobMessageManager.delete(ImmutableList.copyOf(bobMessageManager.search(searchQuery, bobSession)), bobSession);
 
         assertThat(messageVault.search(BOB, Query.ALL).blockFirst())
@@ -283,4 +292,9 @@ class DeletedMessageVaultHookTest {
             .isEmpty();
     }
 
+    private long messageSize(MessageManager messageManager, ComposedMessageId composedMessageId) throws MailboxException {
+        return messageManager.getMessages(MessageRange.one(composedMessageId.getUid()), FetchGroupImpl.MINIMAL, aliceSession)
+            .next()
+            .getSize();
+    }
 }
diff --git a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageVaultSearchContract.java b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageVaultSearchContract.java
index 11822d7..051de74 100644
--- a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageVaultSearchContract.java
+++ b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageVaultSearchContract.java
@@ -573,6 +573,7 @@ public interface DeletedMessageVaultSearchContract {
             .sender(MaybeSender.of(SENDER))
             .recipients(recipients)
             .hasAttachment(false)
+            .size(CONTENT.length)
             .build();
 
         return storeDeletedMessage(deletedMessage, USER);
@@ -588,6 +589,7 @@ public interface DeletedMessageVaultSearchContract {
             .sender(sender)
             .recipients(RECIPIENT1, RECIPIENT2)
             .hasAttachment(false)
+            .size(CONTENT.length)
             .build();
 
         return storeDeletedMessage(deletedMessage, USER);
@@ -603,6 +605,7 @@ public interface DeletedMessageVaultSearchContract {
             .sender(MaybeSender.of(SENDER))
             .recipients(RECIPIENT1, RECIPIENT2)
             .hasAttachment(hasAttachment)
+            .size(CONTENT.length)
             .build();
 
         return storeDeletedMessage(deletedMessage, USER);
@@ -618,6 +621,7 @@ public interface DeletedMessageVaultSearchContract {
             .sender(MaybeSender.of(SENDER))
             .recipients(RECIPIENT1, RECIPIENT2)
             .hasAttachment(true)
+            .size(CONTENT.length)
             .build();
 
         return storeDeletedMessage(deletedMessage, USER);
@@ -661,6 +665,7 @@ public interface DeletedMessageVaultSearchContract {
             .deletionDate(deletionDate)
             .sender(MaybeSender.of(SENDER))
             .recipients(RECIPIENT1)
-            .hasAttachment(false);
+            .hasAttachment(false)
+            .size(CONTENT.length);
     }
 }
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/MessageBuilder.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/MessageBuilder.java
index 640c932..9476326 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/MessageBuilder.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/MessageBuilder.java
@@ -48,7 +48,12 @@ public class MessageBuilder {
     public MailboxMessage build(MessageId messageId) throws Exception {
         return new SimpleMailboxMembership(messageId, mailboxId, uid, -1,  internalDate, size, flags, body, headers);
     }
-    
+
+    public MessageBuilder size(int size) {
+        this.size = size;
+        return this;
+    }
+
     public void header(String field, String value) {
         headers.put(field, value);
     }
diff --git a/server/mailrepository/deleted-messages-vault-repository/src/main/java/org/apache/james/vault/MailConverter.java b/server/mailrepository/deleted-messages-vault-repository/src/main/java/org/apache/james/vault/MailConverter.java
index cfd6d41..b4aa43a 100644
--- a/server/mailrepository/deleted-messages-vault-repository/src/main/java/org/apache/james/vault/MailConverter.java
+++ b/server/mailrepository/deleted-messages-vault-repository/src/main/java/org/apache/james/vault/MailConverter.java
@@ -34,15 +34,20 @@ import org.apache.james.core.User;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MessageId;
 import org.apache.james.server.core.MailImpl;
+import org.apache.james.util.MimeMessageUtil;
 import org.apache.mailet.AttributeName;
 import org.apache.mailet.AttributeUtils;
 import org.apache.mailet.AttributeValue;
 import org.apache.mailet.Mail;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.github.steveash.guavate.Guavate;
 import com.google.common.collect.ImmutableList;
 
 class MailConverter {
+    private static final Logger LOGGER = LoggerFactory.getLogger(MailConverter.class);
+
     static final AttributeName ORIGIN_MAILBOXES_ATTRIBUTE_NAME = AttributeName.of("originMailboxes");
     static final AttributeName HAS_ATTACHMENT_ATTRIBUTE_NAME = AttributeName.of("hasAttachment");
     static final AttributeName OWNER_ATTRIBUTE_NAME = AttributeName.of("owner");
@@ -84,10 +89,29 @@ class MailConverter {
             .sender(mail.getMaybeSender())
             .recipients(mail.getRecipients())
             .hasAttachment(retrieveHasAttachment(mail))
+            .size(getMessageSize(mail))
             .subject(retrieveSubject(mail))
             .build();
     }
 
+    private long getMessageSize(Mail mail) {
+        try {
+            return mail.getMessageSize();
+        } catch (MessagingException e) {
+            LOGGER.warn("can not get message size from message {}, fallback to use MimeMessageUtil.asBytes()", mail.getName(), e);
+            return getMimeMessageSize(mail);
+        }
+    }
+
+    private int getMimeMessageSize(Mail mail) {
+        try {
+            MimeMessage mimeMessage = mail.getMessage();
+            return MimeMessageUtil.asBytes(mimeMessage).length;
+        } catch (Exception e) {
+            throw new RuntimeException("can not calculate mime message size from mail " + mail.getName(), e);
+        }
+    }
+
     private ImmutableList<AttributeValue<?>> serializedMailboxIds(DeletedMessage deletedMessage) {
         return deletedMessage.getOriginMailboxes().stream()
             .map(MailboxId::serialize)
diff --git a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java
index 56b977a..cf7ac0a 100644
--- a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java
@@ -799,9 +799,7 @@ class DeletedMessagesVaultRoutesTest {
 
             @Test
             void restoreShouldAppendMessageToMailboxWhenMatchingNoAttachment() throws Exception {
-                DeletedMessage deletedMessage = messageWithAttachmentBuilder()
-                    .hasAttachment(false)
-                    .build();
+                DeletedMessage deletedMessage = buildMessageWithHasAttachment(false);
                 storeDeletedMessage(deletedMessage);
 
                 String query =
@@ -834,9 +832,7 @@ class DeletedMessagesVaultRoutesTest {
 
             @Test
             void restoreShouldAppendMessageToMailboxWhenMatchingHasAttachment() throws Exception {
-                DeletedMessage deletedMessage = messageWithAttachmentBuilder()
-                    .hasAttachment()
-                    .build();
+                DeletedMessage deletedMessage = buildMessageWithHasAttachment(true);
                 storeDeletedMessage(deletedMessage);
 
                 String query =
@@ -869,9 +865,7 @@ class DeletedMessagesVaultRoutesTest {
 
             @Test
             void restoreShouldNotAppendMessageToMailboxWhenMatchingHasNoAttachment() throws Exception {
-                DeletedMessage deletedMessage = messageWithAttachmentBuilder()
-                    .hasAttachment(false)
-                    .build();
+                DeletedMessage deletedMessage = buildMessageWithHasAttachment(false);
                 storeDeletedMessage(deletedMessage);
 
                 String query =
@@ -1616,7 +1610,7 @@ class DeletedMessagesVaultRoutesTest {
         return ImmutableList.copyOf(messageManager.getMessages(MessageRange.all(), FetchGroupImpl.MINIMAL, session));
     }
 
-    private DeletedMessage.Builder.RequireHasAttachment<DeletedMessage.Builder.FinalStage> messageWithAttachmentBuilder() {
+    private DeletedMessage buildMessageWithHasAttachment(boolean hasAttachment) {
         return DeletedMessage.builder()
             .messageId(InMemoryMessageId.of(MESSAGE_ID_GENERATOR.incrementAndGet()))
             .originMailboxes(MAILBOX_ID_1)
@@ -1624,7 +1618,10 @@ class DeletedMessagesVaultRoutesTest {
             .deliveryDate(DELIVERY_DATE)
             .deletionDate(DELETION_DATE)
             .sender(MaybeSender.of(SENDER))
-            .recipients(RECIPIENT1, RECIPIENT2);
+            .recipients(RECIPIENT1, RECIPIENT2)
+            .hasAttachment(hasAttachment)
+            .size(CONTENT.length)
+            .build();
     }
 
     private DeletedMessage storeDeletedMessage(DeletedMessage deletedMessage) {


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


[james-project] 02/10: MAILBOX-385 DeletedMessageZipper impl

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit e2bf45be00994739841c46b417c4d8ca6de33b1d
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Thu Mar 14 11:49:19 2019 +0700

    MAILBOX-385 DeletedMessageZipper impl
---
 mailbox/backup/pom.xml                             |   1 -
 mailbox/plugin/deleted-messages-vault/pom.xml      |  18 ++
 .../org/apache/james/vault/DeletedMessage.java     |   3 +
 .../james/vault/DeletedMessageConverter.java       |   2 +-
 .../james/vault/DeletedMessageWithContent.java     |  59 +++++
 .../apache/james/vault/DeletedMessageZipper.java   | 104 +++++++++
 .../apache/james/vault/DeletedMessageFixture.java  |   5 +-
 .../org/apache/james/vault/DeletedMessageTest.java |  16 ++
 .../james/vault/DeletedMessageZipperTest.java      | 241 +++++++++++++++++++++
 pom.xml                                            |  16 ++
 .../routes/DeletedMessagesVaultRoutesTest.java     |  22 +-
 11 files changed, 475 insertions(+), 12 deletions(-)

diff --git a/mailbox/backup/pom.xml b/mailbox/backup/pom.xml
index 57409e7..cdd122e 100644
--- a/mailbox/backup/pom.xml
+++ b/mailbox/backup/pom.xml
@@ -63,7 +63,6 @@
         <dependency>
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-compress</artifactId>
-            <version>1.18</version>
         </dependency>
         <dependency>
             <groupId>org.assertj</groupId>
diff --git a/mailbox/plugin/deleted-messages-vault/pom.xml b/mailbox/plugin/deleted-messages-vault/pom.xml
index 0d09332..97e2aea 100644
--- a/mailbox/plugin/deleted-messages-vault/pom.xml
+++ b/mailbox/plugin/deleted-messages-vault/pom.xml
@@ -67,6 +67,16 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>backup</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>backup</artifactId>
+            <scope>test</scope>
+            <type>test-jar</type>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>james-server-core</artifactId>
         </dependency>
         <dependency>
@@ -79,6 +89,10 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-compress</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.assertj</groupId>
             <artifactId>assertj-core</artifactId>
             <scope>test</scope>
@@ -93,5 +107,9 @@
             <artifactId>junit-platform-launcher</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+        </dependency>
     </dependencies>
 </project>
\ No newline at end of file
diff --git a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessage.java b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessage.java
index 110c191..0f549cc 100644
--- a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessage.java
+++ b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessage.java
@@ -34,6 +34,7 @@ import org.apache.james.vault.DeletedMessage.Builder.FinalStage;
 import org.apache.james.vault.DeletedMessage.Builder.Steps.RequireMetadata;
 
 import com.google.common.base.MoreObjects;
+import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 public class DeletedMessage {
@@ -171,6 +172,8 @@ public class DeletedMessage {
     public DeletedMessage(MessageId messageId, List<MailboxId> originMailboxes, User owner,
                           ZonedDateTime deliveryDate, ZonedDateTime deletionDate, MaybeSender sender, List<MailAddress> recipients,
                           Optional<String> subject, boolean hasAttachment, long size) {
+        Preconditions.checkArgument(size > 0, "'size' is required to be a strictly positive number");
+
         this.messageId = messageId;
         this.originMailboxes = originMailboxes;
         this.owner = owner;
diff --git a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessageConverter.java b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessageConverter.java
index 105929b..af03284 100644
--- a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessageConverter.java
+++ b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessageConverter.java
@@ -61,7 +61,7 @@ class DeletedMessageConverter {
             .sender(retrieveSender(mimeMessage))
             .recipients(retrieveRecipients(mimeMessage))
             .hasAttachment(!message.getAttachments().isEmpty())
-            .size(message.getBodyOctets() + message.getHeaderOctets())
+            .size(message.getFullContentOctets())
             .subject(mimeMessage.map(Message::getSubject))
             .build();
     }
diff --git a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessageWithContent.java b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessageWithContent.java
new file mode 100644
index 0000000..b8ce977
--- /dev/null
+++ b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessageWithContent.java
@@ -0,0 +1,59 @@
+/****************************************************************
+ * 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.vault;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * This class carries a {@link org.apache.james.vault.DeletedMessage}
+ * and its data inside an InputStream.
+ *
+ * The InputStream is created and maintained by the callers.
+ */
+public class DeletedMessageWithContent implements AutoCloseable {
+
+    private final DeletedMessage deletedMessage;
+    private final InputStream content;
+
+    public DeletedMessageWithContent(DeletedMessage deletedMessage, InputStream content) {
+        this.deletedMessage = deletedMessage;
+        this.content = content;
+    }
+
+    public DeletedMessage getDeletedMessage() {
+        return deletedMessage;
+    }
+
+    /**
+     * Returns the original InputStream passed to the constructor.
+     * Thus, if the InputStream is already closed by the callers, it cannot be reused
+     *
+     * @return content
+     */
+    public InputStream getContent() {
+        return content;
+    }
+
+    @Override
+    public void close() throws IOException {
+        content.close();
+    }
+}
diff --git a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessageZipper.java b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessageZipper.java
new file mode 100644
index 0000000..4f00e46
--- /dev/null
+++ b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessageZipper.java
@@ -0,0 +1,104 @@
+/****************************************************************
+ * 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.vault;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Optional;
+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.backup.MessageIdExtraField;
+import org.apache.james.mailbox.backup.SizeExtraField;
+import org.apache.james.mailbox.model.MessageId;
+import org.apache.james.util.OptionalUtils;
+import org.reactivestreams.Publisher;
+
+import com.github.fge.lambdas.Throwing;
+import com.google.common.annotations.VisibleForTesting;
+
+import reactor.core.publisher.Mono;
+
+public class DeletedMessageZipper {
+
+    interface DeletedMessageContentLoader {
+        Publisher<InputStream> load(DeletedMessage deletedMessage);
+    }
+
+    DeletedMessageZipper() {
+        ExtraFieldUtils.register(MessageIdExtraField.class);
+        ExtraFieldUtils.register(SizeExtraField.class);
+    }
+
+    public void zip(DeletedMessageContentLoader contentLoader, Stream<DeletedMessage> deletedMessages,
+                    OutputStream outputStream) throws IOException {
+        try (ZipArchiveOutputStream zipOutputStream = newZipArchiveOutputStream(outputStream)) {
+            deletedMessages
+                .map(message -> messageWithContent(message, contentLoader))
+                .flatMap(OptionalUtils::toStream)
+                .forEach(Throwing.<DeletedMessageWithContent>consumer(
+                    messageWithContent -> putMessageToEntry(zipOutputStream, messageWithContent)).sneakyThrow());
+
+            zipOutputStream.finish();
+        }
+    }
+
+    @VisibleForTesting
+    Optional<DeletedMessageWithContent> messageWithContent(DeletedMessage message, DeletedMessageContentLoader loader) {
+        return Mono.from(loader.load(message))
+            .map(messageContent -> new DeletedMessageWithContent(message, messageContent))
+            .blockOptional();
+    }
+
+    @VisibleForTesting
+    ZipArchiveOutputStream newZipArchiveOutputStream(OutputStream outputStream) {
+        return new ZipArchiveOutputStream(outputStream);
+    }
+
+    @VisibleForTesting
+    void putMessageToEntry(ZipArchiveOutputStream zipOutputStream, DeletedMessageWithContent message) throws IOException {
+        try (DeletedMessageWithContent closableMessage = message) {
+            ZipArchiveEntry archiveEntry = createEntry(zipOutputStream, message);
+            zipOutputStream.putArchiveEntry(archiveEntry);
+
+            IOUtils.copy(message.getContent(), zipOutputStream);
+
+            zipOutputStream.closeArchiveEntry();
+        }
+    }
+
+    @VisibleForTesting
+    ZipArchiveEntry createEntry(ZipArchiveOutputStream zipOutputStream,
+                                        DeletedMessageWithContent fullMessage) throws IOException {
+        DeletedMessage message = fullMessage.getDeletedMessage();
+        MessageId messageId = message.getMessageId();
+
+        ZipArchiveEntry archiveEntry = (ZipArchiveEntry) zipOutputStream.createArchiveEntry(new File(messageId.serialize()), messageId.serialize());
+        archiveEntry.addExtraField(new MessageIdExtraField(messageId.serialize()));
+        archiveEntry.addExtraField(new SizeExtraField(message.getSize()));
+
+        return archiveEntry;
+    }
+}
diff --git a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageFixture.java b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageFixture.java
index ee3016c..73c72fb 100644
--- a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageFixture.java
+++ b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageFixture.java
@@ -59,7 +59,7 @@ public interface DeletedMessageFixture {
         .hasAttachment(false)
         .size(CONTENT.length)
         .build();
-    Supplier<DeletedMessage.Builder.FinalStage> FINAL_STAGE = () -> DeletedMessage.builder()
+    DeletedMessage.Builder.RequireSize<DeletedMessage.Builder.FinalStage> SIZE_STAGE = DeletedMessage.builder()
         .messageId(MESSAGE_ID)
         .originMailboxes(MAILBOX_ID_1, MAILBOX_ID_2)
         .user(USER)
@@ -67,7 +67,8 @@ public interface DeletedMessageFixture {
         .deletionDate(DELETION_DATE)
         .sender(MaybeSender.of(SENDER))
         .recipients(RECIPIENT1, RECIPIENT2)
-        .hasAttachment(false)
+        .hasAttachment(false);
+    Supplier<DeletedMessage.Builder.FinalStage> FINAL_STAGE = () -> SIZE_STAGE
         .size(CONTENT.length);
     DeletedMessage DELETED_MESSAGE_WITH_SUBJECT = FINAL_STAGE.get()
         .subject(SUBJECT)
diff --git a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageTest.java b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageTest.java
index e6e35bf..57880e4 100644
--- a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageTest.java
+++ b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageTest.java
@@ -27,12 +27,14 @@ import static org.apache.james.vault.DeletedMessageFixture.DELIVERY_DATE;
 import static org.apache.james.vault.DeletedMessageFixture.MAILBOX_ID_1;
 import static org.apache.james.vault.DeletedMessageFixture.MAILBOX_ID_2;
 import static org.apache.james.vault.DeletedMessageFixture.MESSAGE_ID;
+import static org.apache.james.vault.DeletedMessageFixture.SIZE_STAGE;
 import static org.apache.james.vault.DeletedMessageFixture.SUBJECT;
 import static org.apache.james.vault.DeletedMessageFixture.USER;
 import static org.apache.mailet.base.MailAddressFixture.RECIPIENT1;
 import static org.apache.mailet.base.MailAddressFixture.RECIPIENT2;
 import static org.apache.mailet.base.MailAddressFixture.SENDER;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import org.apache.james.core.MaybeSender;
 import org.assertj.core.api.SoftAssertions;
@@ -69,4 +71,18 @@ class DeletedMessageTest {
     void buildShouldReturnDeletedMessageWithSubject() {
         assertThat(DELETED_MESSAGE_WITH_SUBJECT.getSubject()).contains(SUBJECT);
     }
+
+    @Test
+    void buildShouldThrowWhenPassingZeroSize() {
+        assertThatThrownBy(() -> SIZE_STAGE.size(0L).build())
+            .isInstanceOf(IllegalArgumentException.class)
+            .hasMessage("'size' is required to be a strictly positive number");
+    }
+
+    @Test
+    void buildShouldThrowWhenPassingNegativeSize() {
+        assertThatThrownBy(() -> SIZE_STAGE.size(-1L).build())
+            .isInstanceOf(IllegalArgumentException.class)
+            .hasMessage("'size' is required to be a strictly positive number");
+    }
 }
\ No newline at end of file
diff --git a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageZipperTest.java b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageZipperTest.java
new file mode 100644
index 0000000..6614eaf
--- /dev/null
+++ b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageZipperTest.java
@@ -0,0 +1,241 @@
+/****************************************************************
+ * 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.vault;
+
+import static org.apache.james.mailbox.backup.ZipAssert.EntryChecks.hasName;
+import static org.apache.james.mailbox.backup.ZipAssert.assertThatZip;
+import static org.apache.james.vault.DeletedMessageFixture.CONTENT;
+import static org.apache.james.vault.DeletedMessageFixture.DELETED_MESSAGE;
+import static org.apache.james.vault.DeletedMessageFixture.DELETED_MESSAGE_2;
+import static org.apache.james.vault.DeletedMessageFixture.MESSAGE_ID;
+import static org.apache.james.vault.DeletedMessageFixture.MESSAGE_ID_2;
+import static org.apache.james.vault.DeletedMessageZipper.DeletedMessageContentLoader;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
+import org.apache.commons.compress.archivers.zip.ZipFile;
+import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
+import org.apache.james.mailbox.backup.MessageIdExtraField;
+import org.apache.james.mailbox.backup.SizeExtraField;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import com.github.fge.lambdas.Throwing;
+
+import reactor.core.publisher.Mono;
+
+class DeletedMessageZipperTest {
+
+    private class ZipArchiveStreamCaptor implements Answer<ZipArchiveOutputStream> {
+
+        ZipArchiveOutputStream captured;
+
+        @Override
+        public ZipArchiveOutputStream answer(InvocationOnMock invocation) throws Throwable {
+            ZipArchiveOutputStream zipArchiveOutputStream = (ZipArchiveOutputStream) invocation.callRealMethod();
+            captured = spy(zipArchiveOutputStream);
+            return captured;
+        }
+    }
+
+    private class LoadedResourcesStreamCaptor implements Answer<Optional<DeletedMessageWithContent>> {
+
+        List<DeletedMessageWithContent> captured = new ArrayList<>();
+
+        @Override
+        public Optional<DeletedMessageWithContent> answer(InvocationOnMock invocation) throws Throwable {
+            Optional<DeletedMessageWithContent> messageWithContent = (Optional<DeletedMessageWithContent>) invocation.callRealMethod();
+            return messageWithContent.map(this::returnSpied);
+        }
+
+        private DeletedMessageWithContent returnSpied(DeletedMessageWithContent message) {
+            DeletedMessageWithContent spied = spy(message);
+            captured.add(spied);
+            return spied;
+        }
+    }
+
+    private static final DeletedMessageContentLoader CONTENT_LOADER = message -> Mono.just(new ByteArrayInputStream(CONTENT));
+    private static final String MESSAGE_CONTENT = new String(CONTENT, StandardCharsets.UTF_8);
+    private DeletedMessageZipper zipper;
+
+    @BeforeEach
+    void beforeEach() {
+        zipper = spy(new DeletedMessageZipper());
+    }
+
+    @Test
+    void zipShouldPutEntriesToOutputStream() throws Exception {
+        ByteArrayOutputStream messageContents = zip(Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2));
+        try (ZipFile zipFile = zipFile(messageContents)) {
+            assertThatZip(zipFile)
+                .containsOnlyEntriesMatching(
+                    hasName(MESSAGE_ID.serialize()).hasStringContent(MESSAGE_CONTENT),
+                    hasName(MESSAGE_ID_2.serialize()).hasStringContent(MESSAGE_CONTENT));
+        }
+    }
+
+    @Test
+    void zipShouldPutExtraFields() throws Exception {
+        ByteArrayOutputStream messageContents = zip(Stream.of(DELETED_MESSAGE));
+        try (ZipFile zipFile = zipFile(messageContents)) {
+            assertThatZip(zipFile)
+                .containsOnlyEntriesMatching(
+                    hasName(MESSAGE_ID.serialize())
+                        .containsExtraFields(new MessageIdExtraField(MESSAGE_ID))
+                        .containsExtraFields(new SizeExtraField(CONTENT.length)));
+        }
+    }
+
+    @Test
+    void constructorShouldNotFailWhenCalledMultipleTimes() {
+        assertThatCode(() -> {
+                new DeletedMessageZipper();
+                new DeletedMessageZipper();
+            }).doesNotThrowAnyException();
+    }
+
+    @Test
+    void zipShouldCloseAllResourcesStreamWhenFinishZipping() throws Exception {
+        LoadedResourcesStreamCaptor captor = new LoadedResourcesStreamCaptor();
+        doAnswer(captor)
+            .when(zipper).messageWithContent(any(), any());
+
+        zip(Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2));
+
+        List<DeletedMessageWithContent> loadedResources = captor.captured;
+        assertThat(loadedResources)
+            .hasSize(2);
+        loadedResources.stream()
+            .forEach(Throwing.consumer(spiedMessage -> verify(spiedMessage, times(1)).close()));
+    }
+
+    @Test
+    void zipShouldTerminateZipArchiveStreamWhenFinishZipping() throws Exception {
+        ZipArchiveStreamCaptor captor = new ZipArchiveStreamCaptor();
+        doAnswer(captor)
+            .when(zipper).newZipArchiveOutputStream(any());
+
+        zip(Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2));
+
+        ZipArchiveOutputStream captured = captor.captured;
+        verify(captured, times(1)).finish();
+        verify(captured, times(1)).close();
+    }
+
+    @Test
+    void zipShouldThrowWhenCreateEntryGetException() throws Exception {
+        doThrow(new IOException("mocked exception"))
+            .when(zipper).createEntry(any(), any());
+
+        assertThatThrownBy(() -> zip(Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2)))
+            .isInstanceOf(IOException.class);
+    }
+
+    @Test
+    void zipShouldThrowWhenPutMessageToEntryGetException() throws Exception {
+        doThrow(new IOException("mocked exception"))
+            .when(zipper).putMessageToEntry(any(), any());
+
+        assertThatThrownBy(() -> zip(Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2)))
+            .isInstanceOf(IOException.class);
+    }
+
+    @Test
+    void zipShouldStopLoadingResourcesWhenGettingException() throws Exception {
+        doThrow(new IOException("mocked exception"))
+            .when(zipper).createEntry(any(), any());
+
+        LoadedResourcesStreamCaptor captor = new LoadedResourcesStreamCaptor();
+        doAnswer(captor)
+            .when(zipper).messageWithContent(any(), any());
+
+        assertThatThrownBy(() -> zip(Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2)))
+            .isInstanceOf(IOException.class);
+
+        List<DeletedMessageWithContent> loadedResources = captor.captured;
+        assertThat(loadedResources)
+            .hasSize(1);
+        loadedResources.stream()
+            .forEach(Throwing.consumer(spiedMessage -> verify(spiedMessage, times(1)).close()));
+    }
+
+    @Test
+    void zipShouldCloseParameterOutputStreamWhenGettingException() throws Exception {
+        doThrow(new IOException("mocked exception"))
+            .when(zipper).putMessageToEntry(any(), any());
+
+        ByteArrayOutputStream outputStream = spy(new ByteArrayOutputStream());
+        assertThatThrownBy(() -> zipper.zip(CONTENT_LOADER, Stream.of(DELETED_MESSAGE), outputStream))
+            .isInstanceOf(IOException.class);
+
+        verify(outputStream, times(1)).close();
+    }
+
+    @Test
+    void zipShouldTerminateZipArchiveStreamWhenGettingException() throws Exception {
+        doThrow(new IOException("mocked exception"))
+            .when(zipper).putMessageToEntry(any(), any());
+
+        ZipArchiveStreamCaptor captor = new ZipArchiveStreamCaptor();
+        doAnswer(captor)
+            .when(zipper).newZipArchiveOutputStream(any());
+
+        assertThatThrownBy(() -> zip(Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2)))
+            .isInstanceOf(IOException.class);
+
+        ZipArchiveOutputStream captured = captor.captured;
+        verify(captured, times(1)).finish();
+        verify(captured, times(1)).close();
+    }
+
+    private ByteArrayOutputStream zip(Stream<DeletedMessage> deletedMessages, DeletedMessageZipper zipper) throws IOException {
+        ByteArrayOutputStream zipOutputStream = new ByteArrayOutputStream();
+        zipper.zip(CONTENT_LOADER, deletedMessages, zipOutputStream);
+        return zipOutputStream;
+    }
+
+    private ByteArrayOutputStream zip(Stream<DeletedMessage> deletedMessages) throws IOException {
+        return zip(deletedMessages, zipper);
+    }
+
+    private ZipFile zipFile(ByteArrayOutputStream output) throws IOException {
+        return new ZipFile(new SeekableInMemoryByteChannel(output.toByteArray()));
+    }
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index bac9810..bed7ab4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1044,6 +1044,17 @@
             </dependency>
             <dependency>
                 <groupId>${james.groupId}</groupId>
+                <artifactId>backup</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>${james.groupId}</groupId>
+                <artifactId>backup</artifactId>
+                <version>${project.version}</version>
+                <type>test-jar</type>
+            </dependency>
+            <dependency>
+                <groupId>${james.groupId}</groupId>
                 <artifactId>james-core</artifactId>
                 <version>${project.version}</version>
             </dependency>
@@ -2155,6 +2166,11 @@
             </dependency>
             <dependency>
                 <groupId>org.apache.commons</groupId>
+                <artifactId>commons-compress</artifactId>
+                <version>1.18</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.commons</groupId>
                 <artifactId>commons-lang3</artifactId>
                 <version>3.7</version>
             </dependency>
diff --git a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java
index cf7ac0a..793edb9 100644
--- a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java
@@ -799,7 +799,10 @@ class DeletedMessagesVaultRoutesTest {
 
             @Test
             void restoreShouldAppendMessageToMailboxWhenMatchingNoAttachment() throws Exception {
-                DeletedMessage deletedMessage = buildMessageWithHasAttachment(false);
+                DeletedMessage deletedMessage = messageWithAttachmentBuilder()
+                    .hasAttachment(false)
+                    .size(CONTENT.length)
+                    .build();
                 storeDeletedMessage(deletedMessage);
 
                 String query =
@@ -832,7 +835,10 @@ class DeletedMessagesVaultRoutesTest {
 
             @Test
             void restoreShouldAppendMessageToMailboxWhenMatchingHasAttachment() throws Exception {
-                DeletedMessage deletedMessage = buildMessageWithHasAttachment(true);
+                DeletedMessage deletedMessage = messageWithAttachmentBuilder()
+                    .hasAttachment()
+                    .size(CONTENT.length)
+                    .build();
                 storeDeletedMessage(deletedMessage);
 
                 String query =
@@ -865,7 +871,10 @@ class DeletedMessagesVaultRoutesTest {
 
             @Test
             void restoreShouldNotAppendMessageToMailboxWhenMatchingHasNoAttachment() throws Exception {
-                DeletedMessage deletedMessage = buildMessageWithHasAttachment(false);
+                DeletedMessage deletedMessage = messageWithAttachmentBuilder()
+                    .hasAttachment(false)
+                    .size(CONTENT.length)
+                    .build();
                 storeDeletedMessage(deletedMessage);
 
                 String query =
@@ -1610,7 +1619,7 @@ class DeletedMessagesVaultRoutesTest {
         return ImmutableList.copyOf(messageManager.getMessages(MessageRange.all(), FetchGroupImpl.MINIMAL, session));
     }
 
-    private DeletedMessage buildMessageWithHasAttachment(boolean hasAttachment) {
+    private DeletedMessage.Builder.RequireHasAttachment<DeletedMessage.Builder.RequireSize<DeletedMessage.Builder.FinalStage>> messageWithAttachmentBuilder() {
         return DeletedMessage.builder()
             .messageId(InMemoryMessageId.of(MESSAGE_ID_GENERATOR.incrementAndGet()))
             .originMailboxes(MAILBOX_ID_1)
@@ -1618,10 +1627,7 @@ class DeletedMessagesVaultRoutesTest {
             .deliveryDate(DELIVERY_DATE)
             .deletionDate(DELETION_DATE)
             .sender(MaybeSender.of(SENDER))
-            .recipients(RECIPIENT1, RECIPIENT2)
-            .hasAttachment(hasAttachment)
-            .size(CONTENT.length)
-            .build();
+            .recipients(RECIPIENT1, RECIPIENT2);
     }
 
     private DeletedMessage storeDeletedMessage(DeletedMessage deletedMessage) {


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


[james-project] 03/10: MAILBOX-385 Get rid of DeletedMessageWithContent

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit ac8d2ebe97c04b6ae68e38a17a1ee2622a7d54dc
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri Mar 22 11:23:29 2019 +0700

    MAILBOX-385 Get rid of DeletedMessageWithContent
---
 .../james/vault/DeletedMessageWithContent.java     | 59 ----------------------
 .../apache/james/vault/DeletedMessageZipper.java   | 42 +++++----------
 2 files changed, 12 insertions(+), 89 deletions(-)

diff --git a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessageWithContent.java b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessageWithContent.java
deleted file mode 100644
index b8ce977..0000000
--- a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessageWithContent.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/****************************************************************
- * 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.vault;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * This class carries a {@link org.apache.james.vault.DeletedMessage}
- * and its data inside an InputStream.
- *
- * The InputStream is created and maintained by the callers.
- */
-public class DeletedMessageWithContent implements AutoCloseable {
-
-    private final DeletedMessage deletedMessage;
-    private final InputStream content;
-
-    public DeletedMessageWithContent(DeletedMessage deletedMessage, InputStream content) {
-        this.deletedMessage = deletedMessage;
-        this.content = content;
-    }
-
-    public DeletedMessage getDeletedMessage() {
-        return deletedMessage;
-    }
-
-    /**
-     * Returns the original InputStream passed to the constructor.
-     * Thus, if the InputStream is already closed by the callers, it cannot be reused
-     *
-     * @return content
-     */
-    public InputStream getContent() {
-        return content;
-    }
-
-    @Override
-    public void close() throws IOException {
-        content.close();
-    }
-}
diff --git a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessageZipper.java b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessageZipper.java
index 4f00e46..cad293f 100644
--- a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessageZipper.java
+++ b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/DeletedMessageZipper.java
@@ -23,7 +23,6 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.util.Optional;
 import java.util.stream.Stream;
 
 import org.apache.commons.compress.archivers.zip.ExtraFieldUtils;
@@ -33,18 +32,14 @@ import org.apache.commons.io.IOUtils;
 import org.apache.james.mailbox.backup.MessageIdExtraField;
 import org.apache.james.mailbox.backup.SizeExtraField;
 import org.apache.james.mailbox.model.MessageId;
-import org.apache.james.util.OptionalUtils;
-import org.reactivestreams.Publisher;
 
 import com.github.fge.lambdas.Throwing;
+import com.github.fge.lambdas.consumers.ThrowingConsumer;
 import com.google.common.annotations.VisibleForTesting;
 
-import reactor.core.publisher.Mono;
-
 public class DeletedMessageZipper {
-
     interface DeletedMessageContentLoader {
-        Publisher<InputStream> load(DeletedMessage deletedMessage);
+        InputStream load(DeletedMessage deletedMessage);
     }
 
     DeletedMessageZipper() {
@@ -52,51 +47,38 @@ public class DeletedMessageZipper {
         ExtraFieldUtils.register(SizeExtraField.class);
     }
 
-    public void zip(DeletedMessageContentLoader contentLoader, Stream<DeletedMessage> deletedMessages,
-                    OutputStream outputStream) throws IOException {
+    public void zip(DeletedMessageContentLoader contentLoader, Stream<DeletedMessage> deletedMessages, OutputStream outputStream) throws IOException {
         try (ZipArchiveOutputStream zipOutputStream = newZipArchiveOutputStream(outputStream)) {
-            deletedMessages
-                .map(message -> messageWithContent(message, contentLoader))
-                .flatMap(OptionalUtils::toStream)
-                .forEach(Throwing.<DeletedMessageWithContent>consumer(
-                    messageWithContent -> putMessageToEntry(zipOutputStream, messageWithContent)).sneakyThrow());
+            ThrowingConsumer<DeletedMessage> putInZip = message -> putMessageToEntry(zipOutputStream, message, contentLoader);
+
+            deletedMessages.forEach(Throwing.consumer(putInZip).sneakyThrow());
 
             zipOutputStream.finish();
         }
     }
 
     @VisibleForTesting
-    Optional<DeletedMessageWithContent> messageWithContent(DeletedMessage message, DeletedMessageContentLoader loader) {
-        return Mono.from(loader.load(message))
-            .map(messageContent -> new DeletedMessageWithContent(message, messageContent))
-            .blockOptional();
-    }
-
-    @VisibleForTesting
     ZipArchiveOutputStream newZipArchiveOutputStream(OutputStream outputStream) {
         return new ZipArchiveOutputStream(outputStream);
     }
 
     @VisibleForTesting
-    void putMessageToEntry(ZipArchiveOutputStream zipOutputStream, DeletedMessageWithContent message) throws IOException {
-        try (DeletedMessageWithContent closableMessage = message) {
-            ZipArchiveEntry archiveEntry = createEntry(zipOutputStream, message);
-            zipOutputStream.putArchiveEntry(archiveEntry);
+    void putMessageToEntry(ZipArchiveOutputStream zipOutputStream, DeletedMessage message, DeletedMessageContentLoader contentLoader) throws IOException {
+        try (InputStream content = contentLoader.load(message)) {
+            zipOutputStream.putArchiveEntry(createEntry(zipOutputStream, message));
 
-            IOUtils.copy(message.getContent(), zipOutputStream);
+            IOUtils.copy(content, zipOutputStream);
 
             zipOutputStream.closeArchiveEntry();
         }
     }
 
     @VisibleForTesting
-    ZipArchiveEntry createEntry(ZipArchiveOutputStream zipOutputStream,
-                                        DeletedMessageWithContent fullMessage) throws IOException {
-        DeletedMessage message = fullMessage.getDeletedMessage();
+    ZipArchiveEntry createEntry(ZipArchiveOutputStream zipOutputStream, DeletedMessage message) throws IOException {
         MessageId messageId = message.getMessageId();
 
         ZipArchiveEntry archiveEntry = (ZipArchiveEntry) zipOutputStream.createArchiveEntry(new File(messageId.serialize()), messageId.serialize());
-        archiveEntry.addExtraField(new MessageIdExtraField(messageId.serialize()));
+        archiveEntry.addExtraField(new MessageIdExtraField(messageId));
         archiveEntry.addExtraField(new SizeExtraField(message.getSize()));
 
         return archiveEntry;


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


[james-project] 06/10: MAILBOX-385 DeletedMessageZipperTest: nested class + method move

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit bce0b04b4cf36ad14597eb716414259a2003a9c7
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri Mar 22 11:39:54 2019 +0700

    MAILBOX-385 DeletedMessageZipperTest: nested class + method move
---
 .../james/vault/DeletedMessageZipperTest.java      | 191 +++++++++++----------
 1 file changed, 99 insertions(+), 92 deletions(-)

diff --git a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageZipperTest.java b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageZipperTest.java
index 3f59798..2c8bfdf 100644
--- a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageZipperTest.java
+++ b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageZipperTest.java
@@ -53,6 +53,7 @@ import org.apache.james.mailbox.backup.MessageIdExtraField;
 import org.apache.james.mailbox.backup.SizeExtraField;
 import org.apache.james.mailbox.backup.ZipAssert;
 import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.stubbing.Answer;
 
@@ -68,127 +69,133 @@ class DeletedMessageZipperTest {
         zipper = spy(new DeletedMessageZipper());
     }
 
-    @Test
-    void zipShouldPutEntriesToOutputStream() throws Exception {
-        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-
-        zipper.zip(CONTENT_LOADER, Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2), outputStream);
-
-        try (ZipAssert zipAssert = assertThatZip(outputStream)) {
-            zipAssert.containsOnlyEntriesMatching(
-                    hasName(MESSAGE_ID.serialize()).hasStringContent(MESSAGE_CONTENT),
-                    hasName(MESSAGE_ID_2.serialize()).hasStringContent(MESSAGE_CONTENT));
+    @Nested
+    class NormalBehaviourTest {
+        @Test
+        void constructorShouldNotFailWhenCalledMultipleTimes() {
+            assertThatCode(() -> {
+                new DeletedMessageZipper();
+                new DeletedMessageZipper();
+            }).doesNotThrowAnyException();
         }
-    }
 
-    @Test
-    void zipShouldPutExtraFields() throws Exception {
-        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        @Test
+        void zipShouldPutEntriesToOutputStream() throws Exception {
+            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
 
-        zipper.zip(CONTENT_LOADER, Stream.of(DELETED_MESSAGE), outputStream);
+            zipper.zip(CONTENT_LOADER, Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2), outputStream);
 
-        try (ZipAssert zipAssert = assertThatZip(outputStream)) {
-            zipAssert.containsOnlyEntriesMatching(
-                    hasName(MESSAGE_ID.serialize())
-                        .containsExtraFields(new MessageIdExtraField(MESSAGE_ID))
-                        .containsExtraFields(new SizeExtraField(CONTENT.length)));
+            try (ZipAssert zipAssert = assertThatZip(outputStream)) {
+                zipAssert.containsOnlyEntriesMatching(
+                        hasName(MESSAGE_ID.serialize()).hasStringContent(MESSAGE_CONTENT),
+                        hasName(MESSAGE_ID_2.serialize()).hasStringContent(MESSAGE_CONTENT));
+            }
         }
-    }
 
-    @Test
-    void constructorShouldNotFailWhenCalledMultipleTimes() {
-        assertThatCode(() -> {
-                new DeletedMessageZipper();
-                new DeletedMessageZipper();
-            }).doesNotThrowAnyException();
-    }
+        @Test
+        void zipShouldPutExtraFields() throws Exception {
+            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
 
-    @Test
-    void zipShouldCloseAllResourcesStreamWhenFinishZipping() throws Exception {
-        Collection<InputStream> loadedContents = new ConcurrentLinkedQueue<>();
+            zipper.zip(CONTENT_LOADER, Stream.of(DELETED_MESSAGE), outputStream);
 
-        zipper.zip(spyLoadedContents(loadedContents), Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2), new ByteArrayOutputStream());
+            try (ZipAssert zipAssert = assertThatZip(outputStream)) {
+                zipAssert.containsOnlyEntriesMatching(
+                        hasName(MESSAGE_ID.serialize())
+                            .containsExtraFields(new MessageIdExtraField(MESSAGE_ID))
+                            .containsExtraFields(new SizeExtraField(CONTENT.length)));
+            }
+        }
 
-        assertThat(loadedContents)
-            .hasSize(2)
-            .allSatisfy(Throwing.consumer(content -> verify(content, times(1)).close()));
-    }
+        @Test
+        void zipShouldTerminateZipArchiveStreamWhenFinishZipping() throws Exception {
+            AtomicReference<ZipArchiveOutputStream> zipOutputStreamReference = new AtomicReference<>();
+            when(zipper.newZipArchiveOutputStream(any())).thenAnswer(spyZipOutPutStream(zipOutputStreamReference));
 
-    @Test
-    void zipShouldTerminateZipArchiveStreamWhenFinishZipping() throws Exception {
-        AtomicReference<ZipArchiveOutputStream> zipOutputStreamReference = new AtomicReference<>();
-        when(zipper.newZipArchiveOutputStream(any())).thenAnswer(spyZipOutPutStream(zipOutputStreamReference));
+            zipper.zip(CONTENT_LOADER, Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2), new ByteArrayOutputStream());
 
-        zipper.zip(CONTENT_LOADER, Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2), new ByteArrayOutputStream());
+            verify(zipOutputStreamReference.get(), times(1)).finish();
+            verify(zipOutputStreamReference.get(), times(1)).close();
+        }
 
-        verify(zipOutputStreamReference.get(), times(1)).finish();
-        verify(zipOutputStreamReference.get(), times(1)).close();
-    }
+        @Test
+        void zipShouldCloseAllResourcesStreamWhenFinishZipping() throws Exception {
+            Collection<InputStream> loadedContents = new ConcurrentLinkedQueue<>();
 
-    @Test
-    void zipShouldThrowWhenCreateEntryGetException() throws Exception {
-        doThrow(new IOException("mocked exception")).when(zipper).createEntry(any(), any());
+            zipper.zip(spyLoadedContents(loadedContents), Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2), new ByteArrayOutputStream());
 
-        assertThatThrownBy(() -> zipper.zip(CONTENT_LOADER, Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2), new ByteArrayOutputStream()))
-            .isInstanceOf(IOException.class);
+            assertThat(loadedContents)
+                .hasSize(2)
+                .allSatisfy(Throwing.consumer(content -> verify(content, times(1)).close()));
+        }
     }
 
-    @Test
-    void zipShouldThrowWhenPutMessageToEntryGetException() throws Exception {
-        doThrow(new IOException("mocked exception")).when(zipper).putMessageToEntry(any(), any(), any());
+    @Nested
+    class FailingBehaviourTest {
+        @Test
+        void zipShouldThrowWhenCreateEntryGetException() throws Exception {
+            doThrow(new IOException("mocked exception")).when(zipper).createEntry(any(), any());
 
-        assertThatThrownBy(() -> zipper.zip(CONTENT_LOADER, Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2), new ByteArrayOutputStream()))
-            .isInstanceOf(IOException.class);
-    }
+            assertThatThrownBy(() -> zipper.zip(CONTENT_LOADER, Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2), new ByteArrayOutputStream()))
+                .isInstanceOf(IOException.class);
+        }
 
-    @Test
-    void zipShouldStopLoadingResourcesWhenGettingException() throws Exception {
-        doThrow(new IOException("mocked exception")).when(zipper).createEntry(any(), any());
-        DeletedMessageContentLoader contentLoader = spy(new DeletedMessageContentLoader() {
-            // lambdas are final and thus can't be spied
-            @Override
-            public InputStream load(DeletedMessage deletedMessage) {
-                return new ByteArrayInputStream(CONTENT);
-            }
-        });
+        @Test
+        void zipShouldThrowWhenPutMessageToEntryGetException() throws Exception {
+            doThrow(new IOException("mocked exception")).when(zipper).putMessageToEntry(any(), any(), any());
 
-        try {
-            zipper.zip(contentLoader, Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2), new ByteArrayOutputStream());
-        } catch (Exception e) {
-            // ignored
+            assertThatThrownBy(() -> zipper.zip(CONTENT_LOADER, Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2), new ByteArrayOutputStream()))
+                .isInstanceOf(IOException.class);
         }
 
-        verify(contentLoader, times(1)).load(any());
-    }
+        @Test
+        void zipShouldTerminateZipArchiveStreamWhenGettingException() throws Exception {
+            doThrow(new IOException("mocked exception")).when(zipper).putMessageToEntry(any(), any(), any());
+            AtomicReference<ZipArchiveOutputStream> zipOutputStreamReference = new AtomicReference<>();
+            when(zipper.newZipArchiveOutputStream(any())).thenAnswer(spyZipOutPutStream(zipOutputStreamReference));
 
-    @Test
-    void zipShouldCloseParameterOutputStreamWhenGettingException() throws Exception {
-        doThrow(new IOException("mocked exception")).when(zipper).putMessageToEntry(any(), any(), any());
-        ByteArrayOutputStream outputStream = spy(new ByteArrayOutputStream());
+            try {
+                zipper.zip(CONTENT_LOADER, Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2), new ByteArrayOutputStream());
+            } catch (Exception e) {
+                // ignored
+            }
 
-        try {
-            zipper.zip(CONTENT_LOADER, Stream.of(DELETED_MESSAGE), outputStream);
-        } catch (Exception e) {
-            // ignored
+            verify(zipOutputStreamReference.get(), times(1)).finish();
+            verify(zipOutputStreamReference.get(), times(1)).close();
         }
 
-        verify(outputStream, times(1)).close();
-    }
+        @Test
+        void zipShouldCloseParameterOutputStreamWhenGettingException() throws Exception {
+            doThrow(new IOException("mocked exception")).when(zipper).putMessageToEntry(any(), any(), any());
+            ByteArrayOutputStream outputStream = spy(new ByteArrayOutputStream());
 
-    @Test
-    void zipShouldTerminateZipArchiveStreamWhenGettingException() throws Exception {
-        doThrow(new IOException("mocked exception")).when(zipper).putMessageToEntry(any(), any(), any());
-        AtomicReference<ZipArchiveOutputStream> zipOutputStreamReference = new AtomicReference<>();
-        when(zipper.newZipArchiveOutputStream(any())).thenAnswer(spyZipOutPutStream(zipOutputStreamReference));
+            try {
+                zipper.zip(CONTENT_LOADER, Stream.of(DELETED_MESSAGE), outputStream);
+            } catch (Exception e) {
+                // ignored
+            }
 
-        try {
-            zipper.zip(CONTENT_LOADER, Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2), new ByteArrayOutputStream());
-        } catch (Exception e) {
-            // ignored
+            verify(outputStream, times(1)).close();
         }
 
-        verify(zipOutputStreamReference.get(), times(1)).finish();
-        verify(zipOutputStreamReference.get(), times(1)).close();
+        @Test
+        void zipShouldStopLoadingResourcesWhenGettingException() throws Exception {
+            doThrow(new IOException("mocked exception")).when(zipper).createEntry(any(), any());
+            DeletedMessageContentLoader contentLoader = spy(new DeletedMessageContentLoader() {
+                // lambdas are final and thus can't be spied
+                @Override
+                public InputStream load(DeletedMessage deletedMessage) {
+                    return new ByteArrayInputStream(CONTENT);
+                }
+            });
+
+            try {
+                zipper.zip(contentLoader, Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2), new ByteArrayOutputStream());
+            } catch (Exception e) {
+                // ignored
+            }
+
+            verify(contentLoader, times(1)).load(any());
+        }
     }
 
     private DeletedMessageZipper.DeletedMessageContentLoader spyLoadedContents(Collection<InputStream> loadedContents) {


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


[james-project] 04/10: MAILBOX-385 Rework DeletedMessageZipperTest

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 0d6b733b88c1509baa966ca0143a010e9510183a
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri Mar 22 11:33:23 2019 +0700

    MAILBOX-385 Rework DeletedMessageZipperTest
    
     - Do not extract the method being asserted
     - Indent following the given/when/then pattern
     - Avoid relying on complex capture logic - prefer spies that are easier to use
     - Avoid using assertThatThrowBy for ignoring exception - reserve it for assertions
    
    We put a big deal to allow a method-by-method reviewable diff.
---
 .../james/vault/DeletedMessageZipperTest.java      | 184 +++++++++------------
 1 file changed, 81 insertions(+), 103 deletions(-)

diff --git a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageZipperTest.java b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageZipperTest.java
index 6614eaf..9ae108f 100644
--- a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageZipperTest.java
+++ b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageZipperTest.java
@@ -31,19 +31,21 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatCode;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
+import java.util.Collection;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Stream;
 
 import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
@@ -53,45 +55,12 @@ import org.apache.james.mailbox.backup.MessageIdExtraField;
 import org.apache.james.mailbox.backup.SizeExtraField;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
-import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
 import com.github.fge.lambdas.Throwing;
 
-import reactor.core.publisher.Mono;
-
 class DeletedMessageZipperTest {
-
-    private class ZipArchiveStreamCaptor implements Answer<ZipArchiveOutputStream> {
-
-        ZipArchiveOutputStream captured;
-
-        @Override
-        public ZipArchiveOutputStream answer(InvocationOnMock invocation) throws Throwable {
-            ZipArchiveOutputStream zipArchiveOutputStream = (ZipArchiveOutputStream) invocation.callRealMethod();
-            captured = spy(zipArchiveOutputStream);
-            return captured;
-        }
-    }
-
-    private class LoadedResourcesStreamCaptor implements Answer<Optional<DeletedMessageWithContent>> {
-
-        List<DeletedMessageWithContent> captured = new ArrayList<>();
-
-        @Override
-        public Optional<DeletedMessageWithContent> answer(InvocationOnMock invocation) throws Throwable {
-            Optional<DeletedMessageWithContent> messageWithContent = (Optional<DeletedMessageWithContent>) invocation.callRealMethod();
-            return messageWithContent.map(this::returnSpied);
-        }
-
-        private DeletedMessageWithContent returnSpied(DeletedMessageWithContent message) {
-            DeletedMessageWithContent spied = spy(message);
-            captured.add(spied);
-            return spied;
-        }
-    }
-
-    private static final DeletedMessageContentLoader CONTENT_LOADER = message -> Mono.just(new ByteArrayInputStream(CONTENT));
+    private static final DeletedMessageContentLoader CONTENT_LOADER = message -> new ByteArrayInputStream(CONTENT);
     private static final String MESSAGE_CONTENT = new String(CONTENT, StandardCharsets.UTF_8);
     private DeletedMessageZipper zipper;
 
@@ -102,8 +71,11 @@ class DeletedMessageZipperTest {
 
     @Test
     void zipShouldPutEntriesToOutputStream() throws Exception {
-        ByteArrayOutputStream messageContents = zip(Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2));
-        try (ZipFile zipFile = zipFile(messageContents)) {
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+
+        zipper.zip(CONTENT_LOADER, Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2), outputStream);
+
+        try (ZipFile zipFile = zipFile(outputStream)) {
             assertThatZip(zipFile)
                 .containsOnlyEntriesMatching(
                     hasName(MESSAGE_ID.serialize()).hasStringContent(MESSAGE_CONTENT),
@@ -113,8 +85,11 @@ class DeletedMessageZipperTest {
 
     @Test
     void zipShouldPutExtraFields() throws Exception {
-        ByteArrayOutputStream messageContents = zip(Stream.of(DELETED_MESSAGE));
-        try (ZipFile zipFile = zipFile(messageContents)) {
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+
+        zipper.zip(CONTENT_LOADER, Stream.of(DELETED_MESSAGE), outputStream);
+
+        try (ZipFile zipFile = zipFile(outputStream)) {
             assertThatZip(zipFile)
                 .containsOnlyEntriesMatching(
                     hasName(MESSAGE_ID.serialize())
@@ -133,109 +108,112 @@ class DeletedMessageZipperTest {
 
     @Test
     void zipShouldCloseAllResourcesStreamWhenFinishZipping() throws Exception {
-        LoadedResourcesStreamCaptor captor = new LoadedResourcesStreamCaptor();
-        doAnswer(captor)
-            .when(zipper).messageWithContent(any(), any());
+        Collection<InputStream> loadedContents = new ConcurrentLinkedQueue<>();
 
-        zip(Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2));
+        zipper.zip(spyLoadedContents(loadedContents), Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2), new ByteArrayOutputStream());
 
-        List<DeletedMessageWithContent> loadedResources = captor.captured;
-        assertThat(loadedResources)
-            .hasSize(2);
-        loadedResources.stream()
-            .forEach(Throwing.consumer(spiedMessage -> verify(spiedMessage, times(1)).close()));
+        assertThat(loadedContents)
+            .hasSize(2)
+            .allSatisfy(Throwing.consumer(content -> verify(content, times(1)).close()));
     }
 
     @Test
     void zipShouldTerminateZipArchiveStreamWhenFinishZipping() throws Exception {
-        ZipArchiveStreamCaptor captor = new ZipArchiveStreamCaptor();
-        doAnswer(captor)
-            .when(zipper).newZipArchiveOutputStream(any());
+        AtomicReference<ZipArchiveOutputStream> zipOutputStreamReference = new AtomicReference<>();
+        when(zipper.newZipArchiveOutputStream(any())).thenAnswer(spyZipOutPutStream(zipOutputStreamReference));
 
-        zip(Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2));
+        zipper.zip(CONTENT_LOADER, Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2), new ByteArrayOutputStream());
 
-        ZipArchiveOutputStream captured = captor.captured;
-        verify(captured, times(1)).finish();
-        verify(captured, times(1)).close();
+        verify(zipOutputStreamReference.get(), times(1)).finish();
+        verify(zipOutputStreamReference.get(), times(1)).close();
     }
 
     @Test
     void zipShouldThrowWhenCreateEntryGetException() throws Exception {
-        doThrow(new IOException("mocked exception"))
-            .when(zipper).createEntry(any(), any());
+        doThrow(new IOException("mocked exception")).when(zipper).createEntry(any(), any());
 
-        assertThatThrownBy(() -> zip(Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2)))
+        assertThatThrownBy(() -> zipper.zip(CONTENT_LOADER, Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2), new ByteArrayOutputStream()))
             .isInstanceOf(IOException.class);
     }
 
     @Test
     void zipShouldThrowWhenPutMessageToEntryGetException() throws Exception {
-        doThrow(new IOException("mocked exception"))
-            .when(zipper).putMessageToEntry(any(), any());
+        doThrow(new IOException("mocked exception")).when(zipper).putMessageToEntry(any(), any(), any());
 
-        assertThatThrownBy(() -> zip(Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2)))
+        assertThatThrownBy(() -> zipper.zip(CONTENT_LOADER, Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2), new ByteArrayOutputStream()))
             .isInstanceOf(IOException.class);
     }
 
     @Test
     void zipShouldStopLoadingResourcesWhenGettingException() throws Exception {
-        doThrow(new IOException("mocked exception"))
-            .when(zipper).createEntry(any(), any());
-
-        LoadedResourcesStreamCaptor captor = new LoadedResourcesStreamCaptor();
-        doAnswer(captor)
-            .when(zipper).messageWithContent(any(), any());
-
-        assertThatThrownBy(() -> zip(Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2)))
-            .isInstanceOf(IOException.class);
+        doThrow(new IOException("mocked exception")).when(zipper).createEntry(any(), any());
+        DeletedMessageContentLoader contentLoader = spy(new DeletedMessageContentLoader() {
+            // lambdas are final and thus can't be spied
+            @Override
+            public InputStream load(DeletedMessage deletedMessage) {
+                return new ByteArrayInputStream(CONTENT);
+            }
+        });
+
+        try {
+            zipper.zip(contentLoader, Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2), new ByteArrayOutputStream());
+        } catch (Exception e) {
+            // ignored
+        }
 
-        List<DeletedMessageWithContent> loadedResources = captor.captured;
-        assertThat(loadedResources)
-            .hasSize(1);
-        loadedResources.stream()
-            .forEach(Throwing.consumer(spiedMessage -> verify(spiedMessage, times(1)).close()));
+        verify(contentLoader, times(1)).load(any());
     }
 
     @Test
     void zipShouldCloseParameterOutputStreamWhenGettingException() throws Exception {
-        doThrow(new IOException("mocked exception"))
-            .when(zipper).putMessageToEntry(any(), any());
-
+        doThrow(new IOException("mocked exception")).when(zipper).putMessageToEntry(any(), any(), any());
         ByteArrayOutputStream outputStream = spy(new ByteArrayOutputStream());
-        assertThatThrownBy(() -> zipper.zip(CONTENT_LOADER, Stream.of(DELETED_MESSAGE), outputStream))
-            .isInstanceOf(IOException.class);
+
+        try {
+            zipper.zip(CONTENT_LOADER, Stream.of(DELETED_MESSAGE), outputStream);
+        } catch (Exception e) {
+            // ignored
+        }
 
         verify(outputStream, times(1)).close();
     }
 
     @Test
     void zipShouldTerminateZipArchiveStreamWhenGettingException() throws Exception {
-        doThrow(new IOException("mocked exception"))
-            .when(zipper).putMessageToEntry(any(), any());
-
-        ZipArchiveStreamCaptor captor = new ZipArchiveStreamCaptor();
-        doAnswer(captor)
-            .when(zipper).newZipArchiveOutputStream(any());
-
-        assertThatThrownBy(() -> zip(Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2)))
-            .isInstanceOf(IOException.class);
+        doThrow(new IOException("mocked exception")).when(zipper).putMessageToEntry(any(), any(), any());
+        AtomicReference<ZipArchiveOutputStream> zipOutputStreamReference = new AtomicReference<>();
+        when(zipper.newZipArchiveOutputStream(any())).thenAnswer(spyZipOutPutStream(zipOutputStreamReference));
+
+        try {
+            zipper.zip(CONTENT_LOADER, Stream.of(DELETED_MESSAGE, DELETED_MESSAGE_2), new ByteArrayOutputStream());
+        } catch (Exception e) {
+            // ignored
+        }
 
-        ZipArchiveOutputStream captured = captor.captured;
-        verify(captured, times(1)).finish();
-        verify(captured, times(1)).close();
+        verify(zipOutputStreamReference.get(), times(1)).finish();
+        verify(zipOutputStreamReference.get(), times(1)).close();
     }
 
-    private ByteArrayOutputStream zip(Stream<DeletedMessage> deletedMessages, DeletedMessageZipper zipper) throws IOException {
-        ByteArrayOutputStream zipOutputStream = new ByteArrayOutputStream();
-        zipper.zip(CONTENT_LOADER, deletedMessages, zipOutputStream);
-        return zipOutputStream;
+    private ZipFile zipFile(ByteArrayOutputStream output) throws IOException {
+        return new ZipFile(new SeekableInMemoryByteChannel(output.toByteArray()));
     }
 
-    private ByteArrayOutputStream zip(Stream<DeletedMessage> deletedMessages) throws IOException {
-        return zip(deletedMessages, zipper);
+    private DeletedMessageZipper.DeletedMessageContentLoader spyLoadedContents(Collection<InputStream> loadedContents) {
+        Answer<InputStream> spyedContent = invocationOnMock -> {
+            InputStream result = spy(new ByteArrayInputStream(CONTENT));
+            loadedContents.add(result);
+            return result;
+        };
+        DeletedMessageContentLoader contentLoader = mock(DeletedMessageContentLoader.class);
+        when(contentLoader.load(any())).thenAnswer(spyedContent);
+        return contentLoader;
     }
 
-    private ZipFile zipFile(ByteArrayOutputStream output) throws IOException {
-        return new ZipFile(new SeekableInMemoryByteChannel(output.toByteArray()));
+    private Answer<ZipArchiveOutputStream> spyZipOutPutStream(AtomicReference<ZipArchiveOutputStream> spiedZipArchiveOutputStream) {
+        return invocation -> {
+            ZipArchiveOutputStream zipArchiveOutputStream = spy((ZipArchiveOutputStream) invocation.callRealMethod());
+            spiedZipArchiveOutputStream.set(zipArchiveOutputStream);
+            return zipArchiveOutputStream;
+        };
     }
 }
\ 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] 08/10: JAMES-2682 Sieve should just do nothing when handling Sieve errors

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 9bb878bebcc2bf0451e834536f6c8dbff368071a
Author: Pablo Pita <pa...@gmail.com>
AuthorDate: Mon Mar 18 20:10:35 2019 +0100

    JAMES-2682 Sieve should just do nothing when handling Sieve errors
---
 .../transport/mailets/jsieve/delivery/SieveExecutor.java      | 11 ++++-------
 .../transport/mailets/delivery/SieveIntegrationTest.java      |  4 +++-
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/delivery/SieveExecutor.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/delivery/SieveExecutor.java
index ebb78ce..3fed2ff 100644
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/delivery/SieveExecutor.java
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/delivery/SieveExecutor.java
@@ -39,6 +39,7 @@ import org.apache.jsieve.parser.generated.ParseException;
 import org.apache.jsieve.parser.generated.TokenMgrError;
 import org.apache.mailet.Attribute;
 import org.apache.mailet.AttributeName;
+import org.apache.mailet.AttributeUtils;
 import org.apache.mailet.AttributeValue;
 import org.apache.mailet.Mail;
 import org.apache.mailet.MailetContext;
@@ -119,14 +120,10 @@ public class SieveExecutor {
     public boolean execute(MailAddress recipient, Mail mail) throws MessagingException {
         Preconditions.checkNotNull(recipient, "Recipient for mail to be spooled cannot be null.");
         Preconditions.checkNotNull(mail.getMessage(), "Mail message to be spooled cannot be null.");
-        Optional<Attribute> oSieveNotification = mail.getAttribute(SIEVE_NOTIFICATION);
-        if (oSieveNotification.isPresent()) {
-            AttributeValue<Boolean> attrValue = (AttributeValue<Boolean>) oSieveNotification.get().getValue();
-            if (attrValue.value()) {
-                throw new MessagingException("Do not process Sieve error notification emails");
-            }
+        boolean isSieveNotification = AttributeUtils.getValueAndCastFromMail(mail, SIEVE_NOTIFICATION, Boolean.class).orElse(false);
+        if (isSieveNotification) {
+           	return false;
         }
-        
         return sieveMessage(recipient, mail);
     }
 
diff --git a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/delivery/SieveIntegrationTest.java b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/delivery/SieveIntegrationTest.java
index a287734..29876c8 100644
--- a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/delivery/SieveIntegrationTest.java
+++ b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/delivery/SieveIntegrationTest.java
@@ -939,13 +939,15 @@ public class SieveIntegrationTest {
         assertThat(fakeMailContext.getSentMails()).containsExactly(expectedSentMail);
     }
     
-    @Test(expected = MessagingException.class)
+    @Test
     public void sieveErrorNotificationEmailsShouldNotBeProcessed() throws Exception {
         prepareTestUsingScript("org/apache/james/transport/mailets/delivery/keep.script");
 
         FakeMail mail = createMail();
         mail.setAttribute(new Attribute(SieveExecutor.SIEVE_NOTIFICATION, AttributeValue.of(true)));
         testee.service(mail);
+        // check that the Sieve mailet performs normally, and nothing gets into ATTRIBUTE_NAME
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).isEmpty();
     }
 
     private void prepareTestUsingScript(final String script) throws Exception {


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