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/05/07 04:24:30 UTC
[james-project] 02/03: JAMES-2716 BigMessage MailboxListener
implementation
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 969de070e8323c0c20240c2f751c6edb813c4e53
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Fri Apr 19 15:35:28 2019 +0700
JAMES-2716 BigMessage MailboxListener implementation
---
examples/custom-listeners/pom.xml | 49 +++++
.../custom/listeners/BigMessageListener.java | 112 ++++++++++++
.../src/main/resources/listeners.xml | 25 +++
.../custom/listeners/BigMessageListenerTest.java | 203 +++++++++++++++++++++
examples/pom.xml | 1 +
5 files changed, 390 insertions(+)
diff --git a/examples/custom-listeners/pom.xml b/examples/custom-listeners/pom.xml
new file mode 100644
index 0000000..07be61d
--- /dev/null
+++ b/examples/custom-listeners/pom.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>examples</artifactId>
+ <groupId>org.apache.james</groupId>
+ <version>3.4.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>custom-listeners</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>${james.groupId}</groupId>
+ <artifactId>apache-james-mailbox-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${james.groupId}</groupId>
+ <artifactId>apache-james-mailbox-api</artifactId>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
+ <dependency>
+ <groupId>${james.groupId}</groupId>
+ <artifactId>apache-james-mailbox-memory</artifactId>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
+ <dependency>
+ <groupId>${james.groupId}</groupId>
+ <artifactId>apache-james-mailbox-memory</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>${james.groupId}</groupId>
+ <artifactId>james-server-util</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-engine</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
diff --git a/examples/custom-listeners/src/main/java/org/apache/james/examples/custom/listeners/BigMessageListener.java b/examples/custom-listeners/src/main/java/org/apache/james/examples/custom/listeners/BigMessageListener.java
new file mode 100644
index 0000000..14f27f1
--- /dev/null
+++ b/examples/custom-listeners/src/main/java/org/apache/james/examples/custom/listeners/BigMessageListener.java
@@ -0,0 +1,112 @@
+/****************************************************************
+ * 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.examples.custom.listeners;
+
+import javax.inject.Inject;
+import javax.mail.Flags;
+
+import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MessageIdManager;
+import org.apache.james.mailbox.MessageManager.FlagsUpdateMode;
+import org.apache.james.mailbox.MessageUid;
+import org.apache.james.mailbox.events.Event;
+import org.apache.james.mailbox.events.Group;
+import org.apache.james.mailbox.events.MailboxListener;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.FetchGroupImpl;
+import org.apache.james.mailbox.model.MessageId;
+import org.apache.james.mailbox.model.MessageResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * A Listener to determine the size of added messages.
+ *
+ * If the size is greater or equals than the BIG_MESSAGE size threshold ({@value ONE_MB}).
+ * Then it will be considered as a big message and added BIG_MESSAGE {@value BIG_MESSAGE} flag
+ *
+ */
+class BigMessageListener implements MailboxListener.GroupMailboxListener {
+
+ public static class BigMessageListenerGroup extends Group {
+ }
+
+ private static final BigMessageListenerGroup GROUP = new BigMessageListenerGroup();
+ private static final Logger LOGGER = LoggerFactory.getLogger(BigMessageListener.class);
+
+ static final long ONE_MB = 1000L * 1000L;
+
+ static String BIG_MESSAGE = "BIG_MESSAGE";
+
+ private final MailboxManager mailboxManager;
+ private final MessageIdManager messageIdManager;
+
+ @Inject
+ BigMessageListener(MailboxManager mailboxManager, MessageIdManager messageIdManager) {
+ this.mailboxManager = mailboxManager;
+ this.messageIdManager = messageIdManager;
+ }
+
+ @Override
+ public void event(Event event) {
+ if (event instanceof MailboxListener.Added) {
+ MailboxListener.Added addedEvent = (MailboxListener.Added) event;
+ addedEvent.getUids().stream()
+ .filter(messageUid -> isBig(addedEvent, messageUid))
+ .forEach(messageUid -> setBigMessageFlag(addedEvent, messageUid));
+ }
+ }
+
+ private boolean isBig(Added addedEvent, MessageUid messageUid) {
+ return addedEvent.getMetaData(messageUid).getSize() >= ONE_MB;
+ }
+
+ private void setBigMessageFlag(Added addedEvent, MessageUid messageUid) {
+ try {
+ MailboxSession session = mailboxManager.createSystemSession(addedEvent.getUser().asString());
+ MessageId messageId = addedEvent.getMetaData(messageUid).getMessageId();
+
+ messageIdManager.getMessages(ImmutableList.of(messageId), FetchGroupImpl.MINIMAL, session)
+ .forEach(messageResult -> setBigMessageFlag(messageResult, session));
+ } catch (MailboxException e) {
+ LOGGER.error("error happens when adding '{}' flag to big messages from user {}",
+ BIG_MESSAGE, addedEvent.getUser().asString(), e);
+ }
+ }
+
+ private void setBigMessageFlag(MessageResult messageResult, MailboxSession session) {
+ try {
+ messageIdManager.setFlags(
+ new Flags(BIG_MESSAGE),
+ FlagsUpdateMode.ADD, messageResult.getMessageId(), ImmutableList.of(messageResult.getMailboxId()), session);
+ } catch (MailboxException e) {
+ LOGGER.error("error happens when adding '{}' flag to message {}",
+ BIG_MESSAGE, messageResult.getMessageId().serialize(), e);
+ }
+ }
+
+ @Override
+ public Group getDefaultGroup() {
+ return GROUP;
+ }
+}
diff --git a/examples/custom-listeners/src/main/resources/listeners.xml b/examples/custom-listeners/src/main/resources/listeners.xml
new file mode 100644
index 0000000..ebac3d6
--- /dev/null
+++ b/examples/custom-listeners/src/main/resources/listeners.xml
@@ -0,0 +1,25 @@
+<?xml version="1.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.
+ -->
+
+<listeners>
+ <listener>
+ <class>org.apache.james.examples.custom.listeners.BigMessageListener</class>
+ </listener>
+</listeners>
\ No newline at end of file
diff --git a/examples/custom-listeners/src/test/java/org/apache/james/examples/custom/listeners/BigMessageListenerTest.java b/examples/custom-listeners/src/test/java/org/apache/james/examples/custom/listeners/BigMessageListenerTest.java
new file mode 100644
index 0000000..5cdca0b
--- /dev/null
+++ b/examples/custom-listeners/src/test/java/org/apache/james/examples/custom/listeners/BigMessageListenerTest.java
@@ -0,0 +1,203 @@
+/****************************************************************
+ * 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.examples.custom.listeners;
+
+import static org.apache.james.examples.custom.listeners.BigMessageListener.BIG_MESSAGE;
+import static org.apache.james.examples.custom.listeners.BigMessageListener.ONE_MB;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.nio.charset.StandardCharsets;
+import java.util.stream.Stream;
+
+import javax.mail.Flags;
+
+import org.apache.james.mailbox.DefaultMailboxes;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MailboxSessionUtil;
+import org.apache.james.mailbox.MessageIdManager;
+import org.apache.james.mailbox.MessageManager;
+import org.apache.james.mailbox.events.Event;
+import org.apache.james.mailbox.inmemory.InMemoryMailboxManager;
+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.MailboxId;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.MessageId;
+import org.apache.james.mailbox.model.MessageMetaData;
+import org.apache.james.mailbox.model.MessageResult;
+import org.apache.james.mailbox.store.event.EventFactory;
+import org.apache.james.mime4j.dom.Message;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+
+class BigMessageListenerTest {
+
+ private static final String USER = "user";
+ private static final Event.EventId RANDOM_EVENT_ID = Event.EventId.random();
+ private static final MailboxPath INBOX_PATH = MailboxPath.forUser(USER, DefaultMailboxes.INBOX);
+
+ private BigMessageListener testee;
+ private MessageManager inboxMessageManager;
+ private MessageIdManager messageIdManager;
+ private MailboxId inboxId;
+ private MailboxSession mailboxSession;
+ private InMemoryMailboxManager mailboxManager;
+
+ @BeforeEach
+ void beforeEach() throws Exception {
+ InMemoryIntegrationResources resources = InMemoryIntegrationResources.defaultResources();
+ mailboxManager = resources.getMailboxManager();
+ messageIdManager = resources.getMessageIdManager();
+ mailboxSession = MailboxSessionUtil.create(USER);
+ inboxId = mailboxManager.createMailbox(INBOX_PATH, mailboxSession).get();
+ inboxMessageManager = mailboxManager.getMailbox(inboxId, mailboxSession);
+
+ testee = new BigMessageListener(mailboxManager, messageIdManager);
+
+ resources.getEventBus().register(testee);
+ }
+
+ @Test
+ void listeningEventShouldNotAddFlagWhenSmallMessages() throws Exception {
+ ComposedMessageId composedId = inboxMessageManager.appendMessage(
+ MessageManager.AppendCommand.builder()
+ .build(smallMessage()),
+ mailboxSession);
+
+ assertThat(getMessageFlags(composedId.getMessageId()))
+ .allSatisfy(flags -> assertThat(flags.contains(BIG_MESSAGE)).isFalse());
+ }
+
+ @Test
+ void listeningEventShouldNotRemoveOtherFlagsWhenSmallMessages() throws Exception {
+ Flags appendMessageFlag = new Flags();
+ appendMessageFlag.add(Flags.Flag.SEEN);
+ appendMessageFlag.add(Flags.Flag.DRAFT);
+
+ ComposedMessageId composedId = inboxMessageManager.appendMessage(
+ MessageManager.AppendCommand.builder()
+ .withFlags(appendMessageFlag)
+ .build(smallMessage()),
+ mailboxSession);
+
+ assertThat(getMessageFlags(composedId.getMessageId()))
+ .allSatisfy(flags -> {
+ assertThat(flags.contains(Flags.Flag.SEEN)).isTrue();
+ assertThat(flags.contains(Flags.Flag.DRAFT)).isTrue();
+ });
+ }
+
+ @Test
+ void listeningEventShouldAddFlagWhenBigMessages() throws Exception {
+ ComposedMessageId composedId = inboxMessageManager.appendMessage(
+ MessageManager.AppendCommand.builder()
+ .build(bigMessage()),
+ mailboxSession);
+
+ assertThat(getMessageFlags(composedId.getMessageId()))
+ .allSatisfy(flags -> assertThat(flags.contains(BIG_MESSAGE)).isTrue());
+ }
+
+ @Test
+ void eventShouldAddFlagWhenMessageSizeIsEqualToBigMessageSize() throws Exception {
+ ComposedMessageId composedIdOfSmallMessage = inboxMessageManager.appendMessage(
+ MessageManager.AppendCommand.builder()
+ .build(smallMessage()),
+ mailboxSession);
+
+ MessageResult addedMessage = messageIdManager
+ .getMessages(ImmutableList.of(composedIdOfSmallMessage.getMessageId()), FetchGroupImpl.MINIMAL, mailboxSession)
+ .get(0);
+ MessageMetaData oneMBMetaData = new MessageMetaData(addedMessage.getUid(), addedMessage.getModSeq(),
+ addedMessage.getFlags(), ONE_MB, addedMessage.getInternalDate(), addedMessage.getMessageId());
+
+ Event eventWithAFakeMessageSize = EventFactory.added()
+ .eventId(RANDOM_EVENT_ID)
+ .mailboxSession(mailboxSession)
+ .mailboxId(inboxId)
+ .mailboxPath(INBOX_PATH)
+ .addMetaData(oneMBMetaData)
+ .build();
+
+ testee.event(eventWithAFakeMessageSize);
+
+ assertThat(getMessageFlags(composedIdOfSmallMessage.getMessageId()))
+ .allSatisfy(flags -> assertThat(flags.contains(BIG_MESSAGE)).isTrue());
+ }
+
+ @Test
+ void listeningEventShouldNotRemoveOtherFlagsWhenBigMessages() throws Exception {
+ Flags appendMessageFlag = new Flags();
+ appendMessageFlag.add(Flags.Flag.SEEN);
+ appendMessageFlag.add(Flags.Flag.DRAFT);
+
+ ComposedMessageId composedId = inboxMessageManager.appendMessage(
+ MessageManager.AppendCommand.builder()
+ .withFlags(appendMessageFlag)
+ .build(bigMessage()),
+ mailboxSession);
+
+ assertThat(getMessageFlags(composedId.getMessageId()))
+ .allSatisfy(flags -> {
+ assertThat(flags.contains(Flags.Flag.SEEN)).isTrue();
+ assertThat(flags.contains(Flags.Flag.DRAFT)).isTrue();
+ assertThat(flags.contains(BIG_MESSAGE)).isTrue();
+ });
+ }
+
+ @Test
+ void listeningEventShouldKeepBigMessageFlagWhenAlreadySet() throws Exception {
+ Flags appendMessageFlag = new Flags();
+ appendMessageFlag.add(BIG_MESSAGE);
+
+ ComposedMessageId composedId = inboxMessageManager.appendMessage(
+ MessageManager.AppendCommand.builder()
+ .withFlags(appendMessageFlag)
+ .build(bigMessage()),
+ mailboxSession);
+
+ assertThat(getMessageFlags(composedId.getMessageId()))
+ .allSatisfy(flags -> assertThat(flags.contains(BIG_MESSAGE)).isTrue());
+ }
+
+ private Stream<Flags> getMessageFlags(MessageId messageId) throws Exception {
+ return messageIdManager.getMessages(ImmutableList.of(messageId), FetchGroupImpl.MINIMAL, mailboxSession)
+ .stream()
+ .map(MessageResult::getFlags);
+ }
+
+ private Message bigMessage() throws Exception {
+ return Message.Builder.of()
+ .setSubject("big message")
+ .setBody(Strings.repeat("big message has size greater than one MB", 1024 * 1024), StandardCharsets.UTF_8)
+ .build();
+ }
+
+ private Message smallMessage() throws Exception {
+ return Message.Builder.of()
+ .setSubject("small message")
+ .setBody("small message has size less than one MB", StandardCharsets.UTF_8)
+ .build();
+ }
+}
diff --git a/examples/pom.xml b/examples/pom.xml
index 084d87d..95b1b77 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -33,6 +33,7 @@
<modules>
<module>custom-mailets</module>
+ <module>custom-listeners</module>
</modules>
</project>
\ 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