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 d2c5ca54f57baca2848266f6db37777d8e1208b5 Author: tran tien duc <[email protected]> AuthorDate: Wed Feb 20 18:15:52 2019 +0700 MAILBOX-379 Plug PreDeletionHook to MailboxStoreManager - Implement hook tests and enable them for Memory & Cassandra tests - Disable hook tests for Maildir, JPA mailbox managers, because feature seems like be not supported, when running hook tests I saw DefaultMessageId doesn't support equals method which is used in hook tests. - Disable temporally Memory hook tests, I see a messy setup for Memory mailbox system, it hard to inject hooks to tested instance. Will address it in next commits --- .../apache/james/mailbox/MailboxManagerTest.java | 172 +++++++++++++++++++++ .../mailbox/cassandra/CassandraMailboxManager.java | 11 +- .../mailbox/cassandra/CassandraMessageManager.java | 8 +- .../cassandra/CassandraMailboxManagerProvider.java | 8 +- .../CassandraMailboxManagerStressTest.java | 3 +- .../cassandra/CassandraMailboxManagerTest.java | 3 +- .../cassandra/CassandraTestSystemFixture.java | 2 +- .../CassandraMailboxManagerAttachmentTest.java | 5 +- .../ElasticSearchIntegrationTest.java | 3 +- .../james/mailbox/jpa/JPAMailboxManager.java | 3 +- .../james/mailbox/jpa/JPAMessageManager.java | 3 +- .../james/mailbox/jpa/JPAMailboxManagerTest.java | 7 + .../search/LuceneMessageSearchIndexTest.java | 3 +- .../DomainUserMaildirMailboxManagerTest.java | 10 ++ .../maildir/FullUserMaildirMailboxManagerTest.java | 9 ++ .../maildir/MaildirMailboxManagerProvider.java | 3 +- .../mailbox/inmemory/InMemoryMailboxManager.java | 8 +- .../mailbox/inmemory/InMemoryMessageManager.java | 3 +- .../mailbox/inmemory/MemoryMailboxManagerTest.java | 8 + .../mail/InMemoryMailboxManagerAttachmentTest.java | 5 +- .../manager/InMemoryIntegrationResources.java | 3 +- .../InMemoryMessageIdManagerSideEffectTest.java | 3 +- .../james/mailbox/store/StoreMailboxManager.java | 12 +- .../james/mailbox/store/StoreMessageManager.java | 34 +++- .../mailbox/store/StoreMailboxManagerTest.java | 3 +- .../tools/indexer/CassandraReIndexerImplTest.java | 4 +- .../cassandra/host/CassandraHostSystem.java | 3 +- .../host/ElasticSearchHostSystem.java | 4 +- .../lucenesearch/host/LuceneSearchHostSystem.java | 4 +- .../maildir/host/MaildirHostSystem.java | 3 +- 30 files changed, 317 insertions(+), 33 deletions(-) diff --git a/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxManagerTest.java b/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxManagerTest.java index db11402..ae6e3c9 100644 --- a/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxManagerTest.java +++ b/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxManagerTest.java @@ -23,11 +23,18 @@ import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.SoftAssertions.assertSoftly; import static org.junit.jupiter.api.Assumptions.assumeTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.List; import java.util.Optional; +import java.util.Set; +import java.util.concurrent.CountDownLatch; import javax.mail.Flags; @@ -42,8 +49,10 @@ import org.apache.james.mailbox.events.MessageMoveEvent; import org.apache.james.mailbox.exception.AnnotationException; import org.apache.james.mailbox.exception.MailboxException; import org.apache.james.mailbox.exception.TooLongMailboxNameException; +import org.apache.james.mailbox.extension.PreDeletionHook; import org.apache.james.mailbox.mock.DataProvisioner; 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.MailboxAnnotation; import org.apache.james.mailbox.model.MailboxAnnotationKey; @@ -53,6 +62,7 @@ import org.apache.james.mailbox.model.MailboxMetaData; 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.MessageResult; import org.apache.james.mailbox.model.MultimailboxesSearchQuery; import org.apache.james.mailbox.model.Quota; import org.apache.james.mailbox.model.QuotaRoot; @@ -61,15 +71,19 @@ import org.apache.james.mailbox.model.search.MailboxQuery; import org.apache.james.mailbox.util.EventCollector; import org.apache.james.mime4j.dom.Message; import org.apache.james.util.concurrency.ConcurrentTestRunner; +import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; +import reactor.core.publisher.Mono; + /** * Test the {@link MailboxManager} methods that * are not covered by the protocol-tester suite. @@ -88,12 +102,20 @@ public abstract class MailboxManagerTest<T extends MailboxManager> { private MailboxSession session; private Message.Builder message; + private PreDeletionHook preDeletionHook1; + private PreDeletionHook preDeletionHook2; + protected abstract T provideMailboxManager(); protected abstract EventBus retrieveEventBus(T mailboxManager); + protected Set<PreDeletionHook> preDeletionHooks() { + return ImmutableSet.of(preDeletionHook1, preDeletionHook2); + } + @BeforeEach void setUp() throws Exception { + setupMockForPreDeletionHooks(); this.mailboxManager = provideMailboxManager(); this.message = Message.Builder.of() @@ -101,6 +123,16 @@ public abstract class MailboxManagerTest<T extends MailboxManager> { .setBody("testmail", StandardCharsets.UTF_8); } + private void setupMockForPreDeletionHooks() { + preDeletionHook1 = mock(PreDeletionHook.class); + when(preDeletionHook1.notifyDelete(any(PreDeletionHook.DeleteOperation.class))) + .thenReturn(Mono.empty()); + + preDeletionHook2 = mock(PreDeletionHook.class); + when(preDeletionHook2.notifyDelete(any(PreDeletionHook.DeleteOperation.class))) + .thenReturn(Mono.empty()); + } + @AfterEach void tearDown() throws Exception { mailboxManager.logout(session, false); @@ -1300,4 +1332,144 @@ public abstract class MailboxManagerTest<T extends MailboxManager> { assertThat(session.isOpen()).isFalse(); } } + + @Nested + class HookTests { + + @Nested + class PreDeletion { + + private final QuotaRoot quotaRoot = QuotaRoot.quotaRoot("#private&USER_1", Optional.empty()); + private MailboxPath inbox; + private MailboxId inboxId; + private MailboxId anotherMailboxId; + private MessageManager inboxManager; + private MessageManager anotherMailboxManager; + + @BeforeEach + void setUp() throws Exception { + session = mailboxManager.createSystemSession(USER_1); + inbox = MailboxPath.inbox(session); + + MailboxPath anotherMailboxPath = MailboxPath.forUser(USER_1, "anotherMailbox"); + anotherMailboxId = mailboxManager.createMailbox(anotherMailboxPath, session).get(); + + inboxId = mailboxManager.createMailbox(inbox, session).get(); + inboxManager = mailboxManager.getMailbox(inbox, session); + anotherMailboxManager = mailboxManager.getMailbox(anotherMailboxPath, session); + } + + @Test + void expungeShouldCallAllPreDeletionHooks() throws Exception { + ComposedMessageId composeId = inboxManager.appendMessage(AppendCommand.builder() + .build(message), session); + inboxManager.expunge(MessageRange.one(composeId.getUid()), session); + + ArgumentCaptor<PreDeletionHook.DeleteOperation> preDeleteCaptor1 = ArgumentCaptor.forClass(PreDeletionHook.DeleteOperation.class); + ArgumentCaptor<PreDeletionHook.DeleteOperation> preDeleteCaptor2 = ArgumentCaptor.forClass(PreDeletionHook.DeleteOperation.class); + verify(preDeletionHook1, times(1)).notifyDelete(preDeleteCaptor1.capture()); + verify(preDeletionHook2, times(1)).notifyDelete(preDeleteCaptor2.capture()); + + assertThat(preDeleteCaptor1.getValue().getDeletionMetadataList()) + .hasSize(1) + .hasSameElementsAs(preDeleteCaptor2.getValue().getDeletionMetadataList()) + .allSatisfy(deleteMetadata -> SoftAssertions.assertSoftly(softy -> { + softy.assertThat(deleteMetadata.getMailboxId()).isEqualTo(inboxId); + softy.assertThat(deleteMetadata.getMessageMetaData().getMessageId()).isEqualTo(composeId.getMessageId()); + })); + } + + @Test + void expungeShouldCallAllPreDeletionHooksOnEachMessageDeletionCall() throws Exception { + ComposedMessageId composeId1 = inboxManager.appendMessage(AppendCommand.builder().build(message), session); + ComposedMessageId composeId2 = inboxManager.appendMessage(AppendCommand.builder().build(message), session); + + inboxManager.expunge(MessageRange.one(composeId1.getUid()), session); + inboxManager.expunge(MessageRange.one(composeId2.getUid()), session); + + ArgumentCaptor<PreDeletionHook.DeleteOperation> preDeleteCaptor1 = ArgumentCaptor.forClass(PreDeletionHook.DeleteOperation.class); + ArgumentCaptor<PreDeletionHook.DeleteOperation> preDeleteCaptor2 = ArgumentCaptor.forClass(PreDeletionHook.DeleteOperation.class); + verify(preDeletionHook1, times(2)).notifyDelete(preDeleteCaptor1.capture()); + verify(preDeletionHook2, times(2)).notifyDelete(preDeleteCaptor2.capture()); + + assertThat(preDeleteCaptor1.getAllValues()) + .hasSize(2) + .hasSameElementsAs(preDeleteCaptor2.getAllValues()) + .flatExtracting(PreDeletionHook.DeleteOperation::getDeletionMetadataList) + .allSatisfy(deleteMetadata -> assertThat(deleteMetadata.getMailboxId()).isEqualTo(inboxId)) + .extracting(deleteMetadata -> deleteMetadata.getMessageMetaData().getMessageId()) + .containsOnly(composeId1.getMessageId(), composeId2.getMessageId()); + } + + @Test + void expungeShouldCallAllPreDeletionHooksOnEachMessageDeletionOnDifferentMailboxes() throws Exception { + ComposedMessageId composeId1 = inboxManager.appendMessage(AppendCommand.builder().build(message), session); + ComposedMessageId composeId2 = anotherMailboxManager.appendMessage(AppendCommand.builder().build(message), session); + + inboxManager.expunge(MessageRange.one(composeId1.getUid()), session); + anotherMailboxManager.expunge(MessageRange.one(composeId2.getUid()), session); + + ArgumentCaptor<PreDeletionHook.DeleteOperation> preDeleteCaptor1 = ArgumentCaptor.forClass(PreDeletionHook.DeleteOperation.class); + ArgumentCaptor<PreDeletionHook.DeleteOperation> preDeleteCaptor2 = ArgumentCaptor.forClass(PreDeletionHook.DeleteOperation.class); + verify(preDeletionHook1, times(2)).notifyDelete(preDeleteCaptor1.capture()); + verify(preDeletionHook2, times(2)).notifyDelete(preDeleteCaptor2.capture()); + + assertThat(preDeleteCaptor1.getAllValues()) + .hasSameElementsAs(preDeleteCaptor2.getAllValues()) + .flatExtracting(PreDeletionHook.DeleteOperation::getDeletionMetadataList) + .extracting(deleteMetadata -> deleteMetadata.getMessageMetaData().getMessageId()) + .containsOnly(composeId1.getMessageId(), composeId2.getMessageId()); + + assertThat(preDeleteCaptor1.getAllValues()) + .hasSameElementsAs(preDeleteCaptor2.getAllValues()) + .flatExtracting(PreDeletionHook.DeleteOperation::getDeletionMetadataList) + .extracting(MetadataWithMailboxId::getMailboxId) + .containsOnly(inboxId, anotherMailboxId); + } + + @Test + void expungeShouldNotBeExecutedWhenOneOfPreDeleteHooksFails() throws Exception { + when(preDeletionHook1.notifyDelete(any(PreDeletionHook.DeleteOperation.class))) + .thenThrow(new RuntimeException("throw at hook 1")); + + ComposedMessageId composeId1 = inboxManager.appendMessage(AppendCommand.builder().build(message), session); + assertThatThrownBy(() -> inboxManager.expunge(MessageRange.one(composeId1.getUid()), session)) + .isInstanceOf(RuntimeException.class); + + assertThat(ImmutableList.copyOf(inboxManager.getMessages(MessageRange.one(composeId1.getUid()), FetchGroupImpl.MINIMAL, session)) + .stream() + .map(MessageResult::getMessageId)) + .hasSize(1) + .containsOnly(composeId1.getMessageId()); + } + + @Test + void expungeShouldBeExecutedAfterAllHooksFinish() throws Exception { + CountDownLatch latchForHook1 = new CountDownLatch(1); + when(preDeletionHook1.notifyDelete(any(PreDeletionHook.DeleteOperation.class))) + .thenAnswer(invocation -> { + latchForHook1.countDown(); + return Mono.empty(); + }); + + CountDownLatch latchForHook2 = new CountDownLatch(1); + when(preDeletionHook2.notifyDelete(any(PreDeletionHook.DeleteOperation.class))) + .thenAnswer(invocation -> { + latchForHook2.countDown(); + return Mono.empty(); + }); + + ComposedMessageId composeId1 = inboxManager.appendMessage(AppendCommand.builder().build(message), session); + inboxManager.setFlags(new Flags(Flags.Flag.DELETED), MessageManager.FlagsUpdateMode.ADD, + MessageRange.one(composeId1.getUid()), session); + inboxManager.expunge(MessageRange.all(), session); + + latchForHook1.await(); + latchForHook2.await(); + + assertThat(inboxManager.getMessages(MessageRange.one(composeId1.getUid()), FetchGroupImpl.MINIMAL, session)) + .isEmpty(); + } + } + } } diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxManager.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxManager.java index 44a00ad..e1b4442 100644 --- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxManager.java +++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxManager.java @@ -20,6 +20,7 @@ package org.apache.james.mailbox.cassandra; import java.util.EnumSet; +import java.util.Set; import javax.inject.Inject; @@ -27,6 +28,7 @@ import org.apache.james.mailbox.MailboxManager; import org.apache.james.mailbox.MailboxPathLocker; import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.events.EventBus; +import org.apache.james.mailbox.extension.PreDeletionHook; import org.apache.james.mailbox.model.MailboxACL; import org.apache.james.mailbox.model.MailboxPath; import org.apache.james.mailbox.model.MessageId; @@ -64,7 +66,8 @@ public class CassandraMailboxManager extends StoreMailboxManager { MessageId.Factory messageIdFactory, EventBus eventBus, StoreMailboxAnnotationManager annotationManager, StoreRightManager storeRightManager, QuotaComponents quotaComponents, MessageSearchIndex index, - MailboxManagerConfiguration configuration) { + MailboxManagerConfiguration configuration, + Set<PreDeletionHook> preDeletionHooks) { super(mapperFactory, sessionProvider, locker, @@ -75,7 +78,8 @@ public class CassandraMailboxManager extends StoreMailboxManager { storeRightManager, quotaComponents, index, - configuration); + configuration, + preDeletionHooks); this.locker = locker; this.mapperFactory = mapperFactory; } @@ -109,7 +113,8 @@ public class CassandraMailboxManager extends StoreMailboxManager { getMessageParser(), getMessageIdFactory(), configuration.getBatchSizes(), - getStoreRightManager()); + getStoreRightManager(), + getPreDeletionHooks()); } } diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMessageManager.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMessageManager.java index 918dd1d..29114a4 100644 --- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMessageManager.java +++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMessageManager.java @@ -20,6 +20,7 @@ package org.apache.james.mailbox.cassandra; import java.util.List; +import java.util.Set; import javax.mail.Flags; @@ -27,6 +28,7 @@ import org.apache.james.mailbox.MailboxPathLocker; import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.events.EventBus; import org.apache.james.mailbox.exception.MailboxException; +import org.apache.james.mailbox.extension.PreDeletionHook; import org.apache.james.mailbox.model.MessageAttachment; import org.apache.james.mailbox.model.MessageId; import org.apache.james.mailbox.quota.QuotaManager; @@ -53,9 +55,11 @@ public class CassandraMessageManager extends StoreMessageManager { EventBus eventBus, MailboxPathLocker locker, Mailbox mailbox, QuotaManager quotaManager, QuotaRootResolver quotaRootResolver, MessageParser messageParser, MessageId.Factory messageIdFactory, BatchSizes batchSizes, - StoreRightManager storeRightManager) { + StoreRightManager storeRightManager, + Set<PreDeletionHook> preDeletionHooks) { super(CassandraMailboxManager.MESSAGE_CAPABILITIES, mapperFactory, index, eventBus, locker, mailbox, - quotaManager, quotaRootResolver, messageParser, messageIdFactory, batchSizes, storeRightManager); + quotaManager, quotaRootResolver, messageParser, messageIdFactory, batchSizes, storeRightManager, + preDeletionHooks); this.mapperFactory = mapperFactory; } diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerProvider.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerProvider.java index 5849e2f..cdfe721 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerProvider.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerProvider.java @@ -19,6 +19,8 @@ package org.apache.james.mailbox.cassandra; +import java.util.Set; + import org.apache.james.backends.cassandra.init.CassandraTypesProvider; import org.apache.james.mailbox.acl.GroupMembershipResolver; import org.apache.james.mailbox.acl.MailboxACLResolver; @@ -32,6 +34,7 @@ import org.apache.james.mailbox.cassandra.quota.CassandraPerUserMaxQuotaDao; import org.apache.james.mailbox.cassandra.quota.CassandraPerUserMaxQuotaManager; import org.apache.james.mailbox.events.InVMEventBus; import org.apache.james.mailbox.events.delivery.InVmEventDelivery; +import org.apache.james.mailbox.extension.PreDeletionHook; import org.apache.james.mailbox.quota.QuotaRootResolver; import org.apache.james.mailbox.store.Authenticator; import org.apache.james.mailbox.store.Authorizator; @@ -57,7 +60,8 @@ public class CassandraMailboxManagerProvider { private static final int LIMIT_ANNOTATIONS = 3; private static final int LIMIT_ANNOTATION_SIZE = 30; - public static CassandraMailboxManager provideMailboxManager(Session session, CassandraTypesProvider cassandraTypesProvider) { + public static CassandraMailboxManager provideMailboxManager(Session session, CassandraTypesProvider cassandraTypesProvider, + Set<PreDeletionHook> preDeletionHooks) { CassandraMessageId.Factory messageIdFactory = new CassandraMessageId.Factory(); CassandraMailboxSessionMapperFactory mapperFactory = TestCassandraMailboxSessionMapperFactory.forTests( @@ -90,7 +94,7 @@ public class CassandraMailboxManagerProvider { CassandraMailboxManager manager = new CassandraMailboxManager(mapperFactory, sessionProvider, new NoMailboxPathLocker(), messageParser, messageIdFactory, eventBus, annotationManager, storeRightManager, - quotaComponents, index, MailboxManagerConfiguration.DEFAULT); + quotaComponents, index, MailboxManagerConfiguration.DEFAULT, preDeletionHooks); eventBus.register(quotaUpdater); eventBus.register(new MailboxAnnotationListener(mapperFactory, sessionProvider)); diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerStressTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerStressTest.java index 94d3092..4569fbd 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerStressTest.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerStressTest.java @@ -24,6 +24,7 @@ import org.apache.james.backends.cassandra.DockerCassandraRule; import org.apache.james.mailbox.MailboxManagerStressTest; import org.apache.james.mailbox.cassandra.mail.MailboxAggregateModule; import org.apache.james.mailbox.events.EventBus; +import org.apache.james.mailbox.extension.PreDeletionHook; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; @@ -48,7 +49,7 @@ public class CassandraMailboxManagerStressTest extends MailboxManagerStressTest< @Override protected CassandraMailboxManager provideManager() { - return CassandraMailboxManagerProvider.provideMailboxManager(cassandra.getConf(), cassandra.getTypesProvider()); + return CassandraMailboxManagerProvider.provideMailboxManager(cassandra.getConf(), cassandra.getTypesProvider(), PreDeletionHook.NO_PRE_DELETION_HOOK); } @Override diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java index 0408aa6..cb24d0e 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java @@ -32,7 +32,8 @@ public class CassandraMailboxManagerTest extends MailboxManagerTest<CassandraMai protected CassandraMailboxManager provideMailboxManager() { return CassandraMailboxManagerProvider.provideMailboxManager( cassandra.getCassandraCluster().getConf(), - cassandra.getCassandraCluster().getTypesProvider()); + cassandra.getCassandraCluster().getTypesProvider(), + preDeletionHooks()); } @Override diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java index 4c32722..aafe425 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java @@ -78,7 +78,7 @@ class CassandraTestSystemFixture { MessageSearchIndex index = new SimpleMessageSearchIndex(mapperFactory, mapperFactory, new DefaultTextExtractor()); CassandraMailboxManager cassandraMailboxManager = new CassandraMailboxManager(mapperFactory, sessionProvider, new NoMailboxPathLocker(), new MessageParser(), new CassandraMessageId.Factory(), - eventBus, annotationManager, storeRightManager, quotaComponents, index, MailboxManagerConfiguration.DEFAULT); + eventBus, annotationManager, storeRightManager, quotaComponents, index, MailboxManagerConfiguration.DEFAULT, PreDeletionHook.NO_PRE_DELETION_HOOK); eventBus.register(new MailboxAnnotationListener(mapperFactory, sessionProvider)); diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxManagerAttachmentTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxManagerAttachmentTest.java index d0ff808..23c9bb0 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxManagerAttachmentTest.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxManagerAttachmentTest.java @@ -33,6 +33,7 @@ import org.apache.james.mailbox.cassandra.TestCassandraMailboxSessionMapperFacto import org.apache.james.mailbox.cassandra.ids.CassandraMessageId; import org.apache.james.mailbox.events.InVMEventBus; import org.apache.james.mailbox.events.delivery.InVmEventDelivery; +import org.apache.james.mailbox.extension.PreDeletionHook; import org.apache.james.mailbox.store.AbstractMailboxManagerAttachmentTest; import org.apache.james.mailbox.store.Authenticator; import org.apache.james.mailbox.store.Authorizator; @@ -104,13 +105,13 @@ public class CassandraMailboxManagerAttachmentTest extends AbstractMailboxManage mailboxManager = new CassandraMailboxManager(mailboxSessionMapperFactory, sessionProvider, new NoMailboxPathLocker(), new MessageParser(), messageIdFactory, eventBus, annotationManager, storeRightManager, quotaComponents, - index, MailboxManagerConfiguration.DEFAULT); + index, MailboxManagerConfiguration.DEFAULT, PreDeletionHook.NO_PRE_DELETION_HOOK); MessageParser failingMessageParser = mock(MessageParser.class); when(failingMessageParser.retrieveAttachments(any())) .thenThrow(new RuntimeException("Message parser set to fail")); parseFailingMailboxManager = new CassandraMailboxManager(mailboxSessionMapperFactory, sessionProvider, new NoMailboxPathLocker(), failingMessageParser, messageIdFactory, - eventBus, annotationManager, storeRightManager, quotaComponents, index, MailboxManagerConfiguration.DEFAULT); + eventBus, annotationManager, storeRightManager, quotaComponents, index, MailboxManagerConfiguration.DEFAULT, PreDeletionHook.NO_PRE_DELETION_HOOK); } @Override diff --git a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIntegrationTest.java b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIntegrationTest.java index e49c063..0d1037a 100644 --- a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIntegrationTest.java +++ b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIntegrationTest.java @@ -152,7 +152,8 @@ public class ElasticSearchIntegrationTest extends AbstractMessageSearchIndexTest annotationManager, storeRightManager, quotaComponents, - elasticSearchListeningMessageSearchIndex); + elasticSearchListeningMessageSearchIndex, + PreDeletionHook.NO_PRE_DELETION_HOOK); messageIdManager = new StoreMessageIdManager( storeMailboxManager, diff --git a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMailboxManager.java b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMailboxManager.java index 86ae50f..b0240d5 100644 --- a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMailboxManager.java +++ b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMailboxManager.java @@ -24,6 +24,7 @@ import org.apache.james.mailbox.MailboxPathLocker; import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.events.EventBus; import org.apache.james.mailbox.exception.MailboxException; +import org.apache.james.mailbox.extension.PreDeletionHook; import org.apache.james.mailbox.jpa.mail.JPAMailboxMapper; import org.apache.james.mailbox.jpa.mail.model.JPAMailbox; import org.apache.james.mailbox.model.MailboxPath; @@ -62,7 +63,7 @@ public abstract class JPAMailboxManager extends StoreMailboxManager { super(mailboxSessionMapperFactory, sessionProvider, locker, messageParser, messageIdFactory, annotationManager, eventBus, storeRightManager, quotaComponents, - index, MailboxManagerConfiguration.DEFAULT); + index, MailboxManagerConfiguration.DEFAULT, PreDeletionHook.NO_PRE_DELETION_HOOK); } @Override diff --git a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMessageManager.java b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMessageManager.java index 3af130f..2ee3e8a 100644 --- a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMessageManager.java +++ b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMessageManager.java @@ -28,6 +28,7 @@ import org.apache.james.mailbox.MailboxPathLocker; import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.events.EventBus; import org.apache.james.mailbox.exception.MailboxException; +import org.apache.james.mailbox.extension.PreDeletionHook; import org.apache.james.mailbox.jpa.mail.model.JPAMailbox; import org.apache.james.mailbox.jpa.mail.model.openjpa.JPAMailboxMessage; import org.apache.james.mailbox.model.MessageAttachment; @@ -62,7 +63,7 @@ public class JPAMessageManager extends StoreMessageManager { StoreRightManager storeRightManager) { super(JPAMailboxManager.DEFAULT_NO_MESSAGE_CAPABILITIES, mapperFactory, index, eventBus, locker, mailbox, - quotaManager, quotaRootResolver, messageParser, messageIdFactory, batchSizes, storeRightManager); + quotaManager, quotaRootResolver, messageParser, messageIdFactory, batchSizes, storeRightManager, PreDeletionHook.NO_PRE_DELETION_HOOK); } @Override diff --git a/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/JPAMailboxManagerTest.java b/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/JPAMailboxManagerTest.java index b9e5073..0b5524b 100644 --- a/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/JPAMailboxManagerTest.java +++ b/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/JPAMailboxManagerTest.java @@ -26,10 +26,17 @@ import org.apache.james.mailbox.events.EventBus; import org.apache.james.mailbox.jpa.openjpa.OpenJPAMailboxManager; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; public class JPAMailboxManagerTest extends MailboxManagerTest<OpenJPAMailboxManager> { + @Disabled("JPAMailboxManager is using DefaultMessageId which doesn't support full feature of a messageId, which is an essential" + + "element of the Vault") + @Nested + class HookTests { + } + private static final JpaTestCluster JPA_TEST_CLUSTER = JpaTestCluster.create(JPAMailboxFixture.MAILBOX_PERSISTANCE_CLASSES); private Optional<OpenJPAMailboxManager> openJPAMailboxManager = Optional.empty(); diff --git a/mailbox/lucene/src/test/java/org/apache/james/mailbox/lucene/search/LuceneMessageSearchIndexTest.java b/mailbox/lucene/src/test/java/org/apache/james/mailbox/lucene/search/LuceneMessageSearchIndexTest.java index d82be9c..955257f 100644 --- a/mailbox/lucene/src/test/java/org/apache/james/mailbox/lucene/search/LuceneMessageSearchIndexTest.java +++ b/mailbox/lucene/src/test/java/org/apache/james/mailbox/lucene/search/LuceneMessageSearchIndexTest.java @@ -78,7 +78,8 @@ public class LuceneMessageSearchIndexTest extends AbstractMessageSearchIndexTest annotationManager, storeRightManager, quotaComponents, - luceneMessageSearchIndex); + luceneMessageSearchIndex, + PreDeletionHook.NO_PRE_DELETION_HOOK); messageIdManager = new StoreMessageIdManager( storeMailboxManager, diff --git a/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/DomainUserMaildirMailboxManagerTest.java b/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/DomainUserMaildirMailboxManagerTest.java index d5be3b6..8885135 100644 --- a/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/DomainUserMaildirMailboxManagerTest.java +++ b/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/DomainUserMaildirMailboxManagerTest.java @@ -22,10 +22,18 @@ import org.apache.james.junit.TemporaryFolderExtension; import org.apache.james.mailbox.MailboxManagerTest; import org.apache.james.mailbox.events.EventBus; import org.apache.james.mailbox.store.StoreMailboxManager; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.extension.RegisterExtension; public class DomainUserMaildirMailboxManagerTest extends MailboxManagerTest<StoreMailboxManager> { + @Disabled("Maildir is using DefaultMessageId which doesn't support full feature of a messageId, which is an essential" + + "element of the Vault") + @Nested + class HookTests { + } + @RegisterExtension TemporaryFolderExtension temporaryFolder = new TemporaryFolderExtension(); @@ -42,4 +50,6 @@ public class DomainUserMaildirMailboxManagerTest extends MailboxManagerTest<Stor protected EventBus retrieveEventBus(StoreMailboxManager mailboxManager) { return mailboxManager.getEventBus(); } + + } diff --git a/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/FullUserMaildirMailboxManagerTest.java b/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/FullUserMaildirMailboxManagerTest.java index 08faae2..3e7280e 100644 --- a/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/FullUserMaildirMailboxManagerTest.java +++ b/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/FullUserMaildirMailboxManagerTest.java @@ -22,9 +22,18 @@ import org.apache.james.junit.TemporaryFolderExtension; import org.apache.james.mailbox.MailboxManagerTest; import org.apache.james.mailbox.events.EventBus; import org.apache.james.mailbox.store.StoreMailboxManager; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.extension.RegisterExtension; public class FullUserMaildirMailboxManagerTest extends MailboxManagerTest<StoreMailboxManager> { + + @Disabled("Maildir is using DefaultMessageId which doesn't support full feature of a messageId, which is an essential" + + "element of the Vault") + @Nested + class HookTests { + } + @RegisterExtension TemporaryFolderExtension temporaryFolder = new TemporaryFolderExtension(); diff --git a/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/MaildirMailboxManagerProvider.java b/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/MaildirMailboxManagerProvider.java index 5eb0490..4604f53 100644 --- a/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/MaildirMailboxManagerProvider.java +++ b/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/MaildirMailboxManagerProvider.java @@ -29,6 +29,7 @@ import org.apache.james.mailbox.acl.UnionMailboxACLResolver; import org.apache.james.mailbox.events.InVMEventBus; import org.apache.james.mailbox.events.delivery.InVmEventDelivery; import org.apache.james.mailbox.exception.MailboxException; +import org.apache.james.mailbox.extension.PreDeletionHook; import org.apache.james.mailbox.store.Authenticator; import org.apache.james.mailbox.store.Authorizator; import org.apache.james.mailbox.store.JVMMailboxPathLocker; @@ -72,7 +73,7 @@ public class MaildirMailboxManagerProvider { StoreMailboxManager manager = new StoreMailboxManager(mf, sessionProvider, new JVMMailboxPathLocker(), messageParser, new DefaultMessageId.Factory(), annotationManager, eventBus, storeRightManager, - quotaComponents, index, MailboxManagerConfiguration.DEFAULT); + quotaComponents, index, MailboxManagerConfiguration.DEFAULT, PreDeletionHook.NO_PRE_DELETION_HOOK); return manager; } diff --git a/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/InMemoryMailboxManager.java b/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/InMemoryMailboxManager.java index f6f6387..bd25f42 100644 --- a/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/InMemoryMailboxManager.java +++ b/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/InMemoryMailboxManager.java @@ -20,12 +20,14 @@ package org.apache.james.mailbox.inmemory; import java.util.EnumSet; +import java.util.Set; import javax.inject.Inject; import org.apache.james.mailbox.MailboxPathLocker; import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.events.EventBus; +import org.apache.james.mailbox.extension.PreDeletionHook; import org.apache.james.mailbox.model.MessageId; import org.apache.james.mailbox.store.MailboxManagerConfiguration; import org.apache.james.mailbox.store.MailboxSessionMapperFactory; @@ -56,9 +58,11 @@ public class InMemoryMailboxManager extends StoreMailboxManager { StoreMailboxAnnotationManager annotationManager, StoreRightManager storeRightManager, QuotaComponents quotaComponents, - MessageSearchIndex searchIndex) { + MessageSearchIndex searchIndex, + Set<PreDeletionHook> preDeletionHooks) { super(mailboxSessionMapperFactory, sessionProvider, locker, messageParser, messageIdFactory, - annotationManager, eventBus, storeRightManager, quotaComponents, searchIndex, MailboxManagerConfiguration.DEFAULT); + annotationManager, eventBus, storeRightManager, quotaComponents, searchIndex, MailboxManagerConfiguration.DEFAULT, + preDeletionHooks); } @Override diff --git a/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/InMemoryMessageManager.java b/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/InMemoryMessageManager.java index c331b6a..645d0fb 100644 --- a/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/InMemoryMessageManager.java +++ b/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/InMemoryMessageManager.java @@ -8,6 +8,7 @@ import org.apache.james.mailbox.MailboxPathLocker; import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.events.EventBus; import org.apache.james.mailbox.exception.MailboxException; +import org.apache.james.mailbox.extension.PreDeletionHook; import org.apache.james.mailbox.model.MessageAttachment; import org.apache.james.mailbox.model.MessageId; import org.apache.james.mailbox.quota.QuotaManager; @@ -40,7 +41,7 @@ public class InMemoryMessageManager extends StoreMessageManager { StoreRightManager storeRightManager) { super(InMemoryMailboxManager.MESSAGE_CAPABILITIES, mapperFactory, index, eventBus, locker, mailbox, quotaManager, quotaRootResolver, - messageParser, messageIdFactory, batchSizes, storeRightManager); + messageParser, messageIdFactory, batchSizes, storeRightManager, PreDeletionHook.NO_PRE_DELETION_HOOK); this.mapperFactory = (InMemoryMailboxSessionMapperFactory) mapperFactory; } diff --git a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/MemoryMailboxManagerTest.java b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/MemoryMailboxManagerTest.java index 7ad8bcf..889f35d 100644 --- a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/MemoryMailboxManagerTest.java +++ b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/MemoryMailboxManagerTest.java @@ -21,8 +21,16 @@ package org.apache.james.mailbox.inmemory; import org.apache.james.mailbox.MailboxManagerTest; import org.apache.james.mailbox.events.EventBus; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Nested; public class MemoryMailboxManagerTest extends MailboxManagerTest<InMemoryMailboxManager> { + + @Disabled("will enable at later commits") + @Nested + class HookTests { + } + @Override protected InMemoryMailboxManager provideMailboxManager() { return MemoryMailboxManagerProvider.provideMailboxManager(); diff --git a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/mail/InMemoryMailboxManagerAttachmentTest.java b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/mail/InMemoryMailboxManagerAttachmentTest.java index 2cc6bae..ebf76fa 100644 --- a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/mail/InMemoryMailboxManagerAttachmentTest.java +++ b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/mail/InMemoryMailboxManagerAttachmentTest.java @@ -30,6 +30,7 @@ import org.apache.james.mailbox.acl.GroupMembershipResolver; import org.apache.james.mailbox.acl.UnionMailboxACLResolver; import org.apache.james.mailbox.events.InVMEventBus; import org.apache.james.mailbox.events.delivery.InVmEventDelivery; +import org.apache.james.mailbox.extension.PreDeletionHook; import org.apache.james.mailbox.inmemory.InMemoryMailboxManager; import org.apache.james.mailbox.inmemory.InMemoryMailboxSessionMapperFactory; import org.apache.james.mailbox.inmemory.InMemoryMessageId; @@ -76,12 +77,12 @@ public class InMemoryMailboxManagerAttachmentTest extends AbstractMailboxManager StoreMailboxAnnotationManager annotationManager = new StoreMailboxAnnotationManager(mailboxSessionMapperFactory, storeRightManager); mailboxManager = new InMemoryMailboxManager(mailboxSessionMapperFactory, sessionProvider, new NoMailboxPathLocker(), - new MessageParser(), messageIdFactory, eventBus, annotationManager, storeRightManager, quotaComponents, index); + new MessageParser(), messageIdFactory, eventBus, annotationManager, storeRightManager, quotaComponents, index, PreDeletionHook.NO_PRE_DELETION_HOOK); MessageParser failingMessageParser = mock(MessageParser.class); when(failingMessageParser.retrieveAttachments(any(InputStream.class))) .thenThrow(new RuntimeException("Message parser set to fail")); parseFailingMailboxManager = new InMemoryMailboxManager(mailboxSessionMapperFactory, sessionProvider, new NoMailboxPathLocker(), - failingMessageParser, messageIdFactory, eventBus, annotationManager, storeRightManager, quotaComponents, index); + failingMessageParser, messageIdFactory, eventBus, annotationManager, storeRightManager, quotaComponents, index, PreDeletionHook.NO_PRE_DELETION_HOOK); super.setUp(); } diff --git a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/manager/InMemoryIntegrationResources.java b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/manager/InMemoryIntegrationResources.java index 9e5e5a5..8ae5009 100644 --- a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/manager/InMemoryIntegrationResources.java +++ b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/manager/InMemoryIntegrationResources.java @@ -173,7 +173,8 @@ public class InMemoryIntegrationResources implements IntegrationResources<StoreM annotationManager, storeRightManager, quotaComponents, - index); + index, + PreDeletionHook.NO_PRE_DELETION_HOOK); eventBus.register(listeningCurrentQuotaUpdater); eventBus.register(new MailboxAnnotationListener(mailboxSessionMapperFactory, sessionProvider)); diff --git a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/manager/InMemoryMessageIdManagerSideEffectTest.java b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/manager/InMemoryMessageIdManagerSideEffectTest.java index c99bb6b..0f84e06 100644 --- a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/manager/InMemoryMessageIdManagerSideEffectTest.java +++ b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/manager/InMemoryMessageIdManagerSideEffectTest.java @@ -83,7 +83,8 @@ public class InMemoryMessageIdManagerSideEffectTest extends AbstractMessageIdMan new StoreMailboxAnnotationManager(mapperFactory, rightManager), rightManager, quotaComponents, - index); + index, + preDeletionHooks); StoreMessageIdManager messageIdManager = new StoreMessageIdManager( mailboxManager, mapperFactory, diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java index 7e46527..22af4a8 100644 --- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java +++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java @@ -44,6 +44,7 @@ import org.apache.james.mailbox.exception.MailboxException; import org.apache.james.mailbox.exception.MailboxExistsException; import org.apache.james.mailbox.exception.MailboxNotFoundException; import org.apache.james.mailbox.exception.TooLongMailboxNameException; +import org.apache.james.mailbox.extension.PreDeletionHook; import org.apache.james.mailbox.model.MailboxACL; import org.apache.james.mailbox.model.MailboxACL.Rfc4314Rights; import org.apache.james.mailbox.model.MailboxACL.Right; @@ -110,6 +111,7 @@ public class StoreMailboxManager implements MailboxManager { private final QuotaRootResolver quotaRootResolver; private final QuotaComponents quotaComponents; private final MessageSearchIndex index; + private final Set<PreDeletionHook> preDeletionHooks; protected final MailboxManagerConfiguration configuration; @Inject @@ -117,7 +119,8 @@ public class StoreMailboxManager implements MailboxManager { MailboxPathLocker locker, MessageParser messageParser, MessageId.Factory messageIdFactory, MailboxAnnotationManager annotationManager, EventBus eventBus, StoreRightManager storeRightManager, - QuotaComponents quotaComponents, MessageSearchIndex searchIndex, MailboxManagerConfiguration configuration) { + QuotaComponents quotaComponents, MessageSearchIndex searchIndex, MailboxManagerConfiguration configuration, + Set<PreDeletionHook> preDeletionHooks) { Preconditions.checkNotNull(eventBus); Preconditions.checkNotNull(mailboxSessionMapperFactory); @@ -134,6 +137,7 @@ public class StoreMailboxManager implements MailboxManager { this.quotaComponents = quotaComponents; this.index = searchIndex; this.configuration = configuration; + this.preDeletionHooks = preDeletionHooks; } public QuotaComponents getQuotaComponents() { @@ -202,6 +206,10 @@ public class StoreMailboxManager implements MailboxManager { return messageParser; } + public Set<PreDeletionHook> getPreDeletionHooks() { + return preDeletionHooks; + } + /** * Generate an return the next uid validity * @@ -251,7 +259,7 @@ public class StoreMailboxManager implements MailboxManager { return new StoreMessageManager(DEFAULT_NO_MESSAGE_CAPABILITIES, getMapperFactory(), getMessageSearchIndex(), getEventBus(), getLocker(), mailbox, quotaManager, getQuotaComponents().getQuotaRootResolver(), getMessageParser(), getMessageIdFactory(), configuration.getBatchSizes(), - getStoreRightManager()); + getStoreRightManager(), preDeletionHooks); } /** diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java index 7b9c641..1de663a 100644 --- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java +++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java @@ -19,6 +19,8 @@ package org.apache.james.mailbox.store; +import static org.apache.james.mailbox.extension.PreDeletionHook.DeleteOperation; + import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -29,6 +31,7 @@ import java.util.EnumSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; @@ -44,6 +47,7 @@ import org.apache.james.mailbox.MailboxPathLocker; import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.MessageManager; import org.apache.james.mailbox.MessageUid; +import org.apache.james.mailbox.MetadataWithMailboxId; import org.apache.james.mailbox.acl.UnionMailboxACLResolver; import org.apache.james.mailbox.events.EventBus; import org.apache.james.mailbox.events.MailboxIdRegistrationKey; @@ -51,6 +55,7 @@ import org.apache.james.mailbox.events.MailboxListener; import org.apache.james.mailbox.exception.MailboxException; import org.apache.james.mailbox.exception.ReadOnlyException; import org.apache.james.mailbox.exception.UnsupportedRightException; +import org.apache.james.mailbox.extension.PreDeletionHook; import org.apache.james.mailbox.model.ComposedMessageId; import org.apache.james.mailbox.model.MailboxACL; import org.apache.james.mailbox.model.MailboxCounters; @@ -89,15 +94,19 @@ import org.apache.james.mime4j.stream.MimeTokenStream; import org.apache.james.mime4j.stream.RecursionMode; import org.apache.james.util.BodyOffsetInputStream; import org.apache.james.util.IteratorWrapper; +import org.apache.james.util.StreamUtils; import org.apache.james.util.streams.Iterators; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.github.fge.lambdas.Throwing; import com.github.steveash.guavate.Guavate; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSortedMap; import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.core.scheduler.Schedulers; /** * Base class for {@link MessageManager} @@ -112,6 +121,7 @@ import reactor.core.publisher.Flux; */ public class StoreMessageManager implements MessageManager { + private static final int NO_LIMIT = -1; private static final MailboxCounters ZERO_MAILBOX_COUNTERS = MailboxCounters.builder() .count(0) .unseen(0) @@ -148,12 +158,13 @@ public class StoreMessageManager implements MessageManager { private final MessageParser messageParser; private final Factory messageIdFactory; private final BatchSizes batchSizes; + private final Set<PreDeletionHook> preDeletionHooks; public StoreMessageManager(EnumSet<MailboxManager.MessageCapabilities> messageCapabilities, MailboxSessionMapperFactory mapperFactory, MessageSearchIndex index, EventBus eventBus, MailboxPathLocker locker, Mailbox mailbox, QuotaManager quotaManager, QuotaRootResolver quotaRootResolver, MessageParser messageParser, MessageId.Factory messageIdFactory, BatchSizes batchSizes, - StoreRightManager storeRightManager) { + StoreRightManager storeRightManager, Set<PreDeletionHook> preDeletionHooks) { this.messageCapabilities = messageCapabilities; this.eventBus = eventBus; this.mailbox = mailbox; @@ -166,6 +177,7 @@ public class StoreMessageManager implements MessageManager { this.messageIdFactory = messageIdFactory; this.batchSizes = batchSizes; this.storeRightManager = storeRightManager; + this.preDeletionHooks = preDeletionHooks; } protected Factory getMessageIdFactory() { @@ -284,6 +296,8 @@ public class StoreMessageManager implements MessageManager { private Map<MessageUid, MessageMetaData> deleteMessages(List<MessageUid> messageUids, MailboxSession session) throws MailboxException { MessageMapper messageMapper = mapperFactory.getMessageMapper(session); + runPredeletionHooks(messageUids, session); + return messageMapper.execute( () -> messageMapper.deleteMessages(getMailboxEntity(), messageUids)); } @@ -715,6 +729,24 @@ public class StoreMessageManager implements MessageManager { } + private void runPredeletionHooks(List<MessageUid> uids, MailboxSession session) throws MailboxException { + MessageMapper messageMapper = mapperFactory.getMessageMapper(session); + + DeleteOperation deleteOperation = Flux.fromIterable(MessageRange.toRanges(uids)) + .publishOn(Schedulers.elastic()) + .flatMap(range -> Mono.fromCallable(() -> messageMapper.findInMailbox(mailbox, range, FetchType.Metadata, NO_LIMIT)) + .flatMapMany(iterator -> Flux.fromStream(Iterators.toStream(iterator)))) + .map(mailboxMessage -> MetadataWithMailboxId.from(mailboxMessage.metaData(), mailboxMessage.getMailboxId())) + .collect(Guavate.toImmutableList()) + .map(DeleteOperation::from) + .block(); + + Flux.fromIterable(preDeletionHooks) + .publishOn(Schedulers.elastic()) + .flatMap(hook -> hook.notifyDelete(deleteOperation)) + .blockLast(); + } + @Override public Iterator<MessageUid> search(SearchQuery query, MailboxSession mailboxSession) throws MailboxException { if (query.equals(new SearchQuery(SearchQuery.all()))) { diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMailboxManagerTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMailboxManagerTest.java index b5b5ca1..b32ffa9 100644 --- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMailboxManagerTest.java +++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMailboxManagerTest.java @@ -36,6 +36,7 @@ import org.apache.james.mailbox.exception.MailboxException; import org.apache.james.mailbox.exception.MailboxNotFoundException; import org.apache.james.mailbox.exception.NotAdminException; import org.apache.james.mailbox.exception.UserDoesNotExistException; +import org.apache.james.mailbox.extension.PreDeletionHook; import org.apache.james.mailbox.model.MailboxACL; import org.apache.james.mailbox.model.MailboxId; import org.apache.james.mailbox.model.MailboxPath; @@ -93,7 +94,7 @@ public class StoreMailboxManagerTest { storeMailboxManager = new StoreMailboxManager(mockedMapperFactory, sessionProvider, new JVMMailboxPathLocker(), new MessageParser(), messageIdFactory, - annotationManager, eventBus, storeRightManager, quotaComponents, index, MailboxManagerConfiguration.DEFAULT); + annotationManager, eventBus, storeRightManager, quotaComponents, index, MailboxManagerConfiguration.DEFAULT, PreDeletionHook.NO_PRE_DELETION_HOOK); } @Test(expected = MailboxNotFoundException.class) diff --git a/mailbox/tools/indexer/src/test/java/org/apache/mailbox/tools/indexer/CassandraReIndexerImplTest.java b/mailbox/tools/indexer/src/test/java/org/apache/mailbox/tools/indexer/CassandraReIndexerImplTest.java index 7161b38..ca278ee 100644 --- a/mailbox/tools/indexer/src/test/java/org/apache/mailbox/tools/indexer/CassandraReIndexerImplTest.java +++ b/mailbox/tools/indexer/src/test/java/org/apache/mailbox/tools/indexer/CassandraReIndexerImplTest.java @@ -35,6 +35,7 @@ import org.apache.james.mailbox.MessageManager; import org.apache.james.mailbox.cassandra.CassandraMailboxManager; import org.apache.james.mailbox.cassandra.CassandraMailboxManagerProvider; import org.apache.james.mailbox.cassandra.mail.MailboxAggregateModule; +import org.apache.james.mailbox.extension.PreDeletionHook; import org.apache.james.mailbox.indexer.ReIndexer; import org.apache.james.mailbox.model.MailboxPath; import org.apache.james.mailbox.store.MailboxSessionMapperFactory; @@ -61,7 +62,8 @@ public class CassandraReIndexerImplTest { @BeforeEach void setUp(CassandraCluster cassandra) { - mailboxManager = CassandraMailboxManagerProvider.provideMailboxManager(cassandra.getConf(), cassandra.getTypesProvider()); + mailboxManager = CassandraMailboxManagerProvider.provideMailboxManager(cassandra.getConf(), cassandra.getTypesProvider(), + PreDeletionHook.NO_PRE_DELETION_HOOK); MailboxSessionMapperFactory mailboxSessionMapperFactory = mailboxManager.getMapperFactory(); messageSearchIndex = mock(ListeningMessageSearchIndex.class); reIndexer = new ReIndexerImpl(new ReIndexerPerformer(mailboxManager, messageSearchIndex, mailboxSessionMapperFactory), diff --git a/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java b/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java index 2b4d901..62a64a8 100644 --- a/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java +++ b/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java @@ -40,6 +40,7 @@ import org.apache.james.mailbox.cassandra.quota.CassandraPerUserMaxQuotaDao; import org.apache.james.mailbox.cassandra.quota.CassandraPerUserMaxQuotaManager; import org.apache.james.mailbox.events.InVMEventBus; import org.apache.james.mailbox.events.delivery.InVmEventDelivery; +import org.apache.james.mailbox.extension.PreDeletionHook; import org.apache.james.mailbox.quota.QuotaRootResolver; import org.apache.james.mailbox.store.JVMMailboxPathLocker; import org.apache.james.mailbox.store.MailboxManagerConfiguration; @@ -112,7 +113,7 @@ public class CassandraHostSystem extends JamesImapHostSystem { mailboxManager = new CassandraMailboxManager(mapperFactory, sessionProvider, new JVMMailboxPathLocker(), new MessageParser(), messageIdFactory, - eventBus, annotationManager, storeRightManager, quotaComponents, index, MailboxManagerConfiguration.DEFAULT); + eventBus, annotationManager, storeRightManager, quotaComponents, index, MailboxManagerConfiguration.DEFAULT, PreDeletionHook.NO_PRE_DELETION_HOOK); eventBus.register(quotaUpdater); diff --git a/mpt/impl/imap-mailbox/elasticsearch/src/test/java/org/apache/james/mpt/imapmailbox/elasticsearch/host/ElasticSearchHostSystem.java b/mpt/impl/imap-mailbox/elasticsearch/src/test/java/org/apache/james/mpt/imapmailbox/elasticsearch/host/ElasticSearchHostSystem.java index d599899..e0c85b5 100644 --- a/mpt/impl/imap-mailbox/elasticsearch/src/test/java/org/apache/james/mpt/imapmailbox/elasticsearch/host/ElasticSearchHostSystem.java +++ b/mpt/impl/imap-mailbox/elasticsearch/src/test/java/org/apache/james/mpt/imapmailbox/elasticsearch/host/ElasticSearchHostSystem.java @@ -51,6 +51,7 @@ import org.apache.james.mailbox.elasticsearch.search.ElasticSearchSearcher; import org.apache.james.mailbox.events.InVMEventBus; import org.apache.james.mailbox.events.delivery.InVmEventDelivery; import org.apache.james.mailbox.exception.MailboxException; +import org.apache.james.mailbox.extension.PreDeletionHook; import org.apache.james.mailbox.inmemory.InMemoryId; import org.apache.james.mailbox.inmemory.InMemoryMailboxManager; import org.apache.james.mailbox.inmemory.InMemoryMailboxSessionMapperFactory; @@ -140,7 +141,8 @@ public class ElasticSearchHostSystem extends JamesImapHostSystem { annotationManager, storeRightManager, quotaComponents, - searchIndex); + searchIndex, + PreDeletionHook.NO_PRE_DELETION_HOOK); eventBus.register(searchIndex); diff --git a/mpt/impl/imap-mailbox/lucenesearch/src/test/java/org/apache/james/mpt/imapmailbox/lucenesearch/host/LuceneSearchHostSystem.java b/mpt/impl/imap-mailbox/lucenesearch/src/test/java/org/apache/james/mpt/imapmailbox/lucenesearch/host/LuceneSearchHostSystem.java index 52756d6..a2a7c3d 100644 --- a/mpt/impl/imap-mailbox/lucenesearch/src/test/java/org/apache/james/mpt/imapmailbox/lucenesearch/host/LuceneSearchHostSystem.java +++ b/mpt/impl/imap-mailbox/lucenesearch/src/test/java/org/apache/james/mpt/imapmailbox/lucenesearch/host/LuceneSearchHostSystem.java @@ -37,6 +37,7 @@ import org.apache.james.mailbox.acl.SimpleGroupMembershipResolver; import org.apache.james.mailbox.acl.UnionMailboxACLResolver; import org.apache.james.mailbox.events.InVMEventBus; import org.apache.james.mailbox.events.delivery.InVmEventDelivery; +import org.apache.james.mailbox.extension.PreDeletionHook; import org.apache.james.mailbox.inmemory.InMemoryId; import org.apache.james.mailbox.inmemory.InMemoryMailboxManager; import org.apache.james.mailbox.inmemory.InMemoryMailboxSessionMapperFactory; @@ -118,7 +119,8 @@ public class LuceneSearchHostSystem extends JamesImapHostSystem { new StoreMailboxAnnotationManager(mapperFactory, rightManager), rightManager, QuotaComponents.disabled(sessionProvider, mapperFactory), - searchIndex); + searchIndex, + PreDeletionHook.NO_PRE_DELETION_HOOK); searchIndex.setEnableSuffixMatch(true); diff --git a/mpt/impl/imap-mailbox/maildir/src/test/java/org/apache/james/mpt/imapmailbox/maildir/host/MaildirHostSystem.java b/mpt/impl/imap-mailbox/maildir/src/test/java/org/apache/james/mpt/imapmailbox/maildir/host/MaildirHostSystem.java index ae23921..4612fea 100644 --- a/mpt/impl/imap-mailbox/maildir/src/test/java/org/apache/james/mpt/imapmailbox/maildir/host/MaildirHostSystem.java +++ b/mpt/impl/imap-mailbox/maildir/src/test/java/org/apache/james/mpt/imapmailbox/maildir/host/MaildirHostSystem.java @@ -35,6 +35,7 @@ import org.apache.james.mailbox.acl.SimpleGroupMembershipResolver; import org.apache.james.mailbox.acl.UnionMailboxACLResolver; import org.apache.james.mailbox.events.InVMEventBus; import org.apache.james.mailbox.events.delivery.InVmEventDelivery; +import org.apache.james.mailbox.extension.PreDeletionHook; import org.apache.james.mailbox.maildir.MaildirMailboxSessionMapperFactory; import org.apache.james.mailbox.maildir.MaildirStore; import org.apache.james.mailbox.store.JVMMailboxPathLocker; @@ -85,7 +86,7 @@ public class MaildirHostSystem extends JamesImapHostSystem { mailboxManager = new StoreMailboxManager(mailboxSessionMapperFactory, sessionProvider, locker, messageParser, new DefaultMessageId.Factory(), annotationManager, eventBus, storeRightManager, quotaComponents, - index, MailboxManagerConfiguration.DEFAULT); + index, MailboxManagerConfiguration.DEFAULT, PreDeletionHook.NO_PRE_DELETION_HOOK); ImapProcessor defaultImapProcessorFactory = DefaultImapProcessorFactory.createDefaultProcessor( --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
