JAMES-2399 load listeners and their configuration from listeners.xml file
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/80409198 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/80409198 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/80409198 Branch: refs/heads/master Commit: 8040919877a13b02bf24925b223b4243fe9a79db Parents: cc4fb69 Author: Matthieu Baechler <[email protected]> Authored: Tue May 15 15:52:55 2018 +0200 Committer: Matthieu Baechler <[email protected]> Committed: Tue May 22 10:02:27 2018 +0200 ---------------------------------------------------------------------- mailbox/plugin/quota-mailing/pom.xml | 26 ++- .../QuotaMailingListenerConfiguration.java | 46 +++++ .../QuotaThresholdCrossingListener.java | 40 ++++- .../mailbox/quota/model/QuotaThresholds.java | 16 ++ .../QuotaMailingListenerConfigurationTest.java | 172 +++++++++++++++++++ .../QuotaThresholdListenersTestSystem.java | 4 +- .../quota/model/QuotaThresholdsTest.java | 9 + server/container/guice/cassandra-guice/pom.xml | 4 - .../mailbox/CassandraQuotaMailingModule.java | 2 - .../guice/mailbox-plugin-quota-mailing/pom.xml | 45 ----- .../modules/mailbox/QuotaMailingModule.java | 41 ----- .../modules/mailbox/ListenerConfiguration.java | 23 ++- .../mailbox/MailboxListenersLoaderImpl.java | 7 +- .../mailbox/MailboxListenersLoaderImplTest.java | 8 +- server/container/guice/memory-guice/pom.xml | 8 +- .../org/apache/james/MemoryJamesServerMain.java | 7 +- server/container/guice/pom.xml | 6 - .../src/test/resources/listeners.xml | 5 + .../methods/integration/QuotaMailingTest.java | 37 +++- .../src/test/resources/listeners.xml | 5 + 20 files changed, 367 insertions(+), 144 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/mailbox/plugin/quota-mailing/pom.xml ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing/pom.xml b/mailbox/plugin/quota-mailing/pom.xml index b10bd8e..3cda088 100644 --- a/mailbox/plugin/quota-mailing/pom.xml +++ b/mailbox/plugin/quota-mailing/pom.xml @@ -36,20 +36,6 @@ <dependencies> <dependency> <groupId>${project.groupId}</groupId> - <artifactId>event-sourcing-core</artifactId> - </dependency> - <dependency> - <groupId>${project.groupId}</groupId> - <artifactId>event-sourcing-event-store-api</artifactId> - </dependency> - <dependency> - <groupId>${project.groupId}</groupId> - <artifactId>event-sourcing-event-store-api</artifactId> - <type>test-jar</type> - <scope>test</scope> - </dependency> - <dependency> - <groupId>${project.groupId}</groupId> <artifactId>apache-james-mailbox-api</artifactId> </dependency> <dependency> @@ -75,6 +61,14 @@ </dependency> <dependency> <groupId>${project.groupId}</groupId> + <artifactId>event-sourcing-core</artifactId> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>event-sourcing-event-store-api</artifactId> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> <artifactId>james-server-core</artifactId> <scope>test</scope> </dependency> @@ -93,6 +87,10 @@ </dependency> <dependency> <groupId>${project.groupId}</groupId> + <artifactId>james-server-lifecycle-api</artifactId> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> <artifactId>james-server-util</artifactId> </dependency> <dependency> http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfiguration.java ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfiguration.java b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfiguration.java index b501130..8f680b4 100644 --- a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfiguration.java +++ b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfiguration.java @@ -24,15 +24,59 @@ import java.util.Collection; import java.util.Objects; import java.util.Optional; +import org.apache.commons.configuration.HierarchicalConfiguration; import org.apache.james.filesystem.api.FileSystem; import org.apache.james.mailbox.quota.model.QuotaThreshold; import org.apache.james.mailbox.quota.model.QuotaThresholds; +import org.apache.james.util.TimeConverter; +import com.github.steveash.guavate.Guavate; import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; public class QuotaMailingListenerConfiguration { + interface XmlKeys { + String SUBJECT_TEMPLATE = "subjectTemplate"; + String BODY_TEMPLATE = "bodyTemplate"; + String GRACE_PERIOD = "gracePeriod"; + String THRESHOLDS = "thresholds.threshold"; + String ROOT_KEY = ""; + } + + public static QuotaMailingListenerConfiguration from(HierarchicalConfiguration config) { + return builder() + .addThresholds(readThresholds(config)) + .subjectTemplate(readSubjectTemplate(config)) + .bodyTemplate(readBodyTemplate(config)) + .gracePeriod(readGracePeriod(config)) + .build(); + } + + private static Optional<String> readSubjectTemplate(HierarchicalConfiguration config) { + return Optional.ofNullable(config.getString(XmlKeys.SUBJECT_TEMPLATE, null)); + } + + private static Optional<String> readBodyTemplate(HierarchicalConfiguration config) { + return Optional.ofNullable(config.getString(XmlKeys.BODY_TEMPLATE, null)); + } + + private static Optional<Duration> readGracePeriod(HierarchicalConfiguration config) { + return Optional.ofNullable(config.getString(XmlKeys.GRACE_PERIOD, null)) + .map(string -> TimeConverter.getMilliSeconds(string, TimeConverter.Unit.DAYS)) + .map(Duration::ofMillis); + } + + private static ImmutableList<QuotaThreshold> readThresholds(HierarchicalConfiguration config) { + return config.configurationsAt(XmlKeys.THRESHOLDS) + .stream() + .map(node -> node.getDouble(XmlKeys.ROOT_KEY)) + .map(QuotaThreshold::new) + .collect(Guavate.toImmutableList()); + } + public static class Builder { private ImmutableList.Builder<QuotaThreshold> thresholds; private Optional<Duration> gradePeriod; @@ -67,11 +111,13 @@ public class QuotaMailingListenerConfiguration { } public Builder bodyTemplate(String bodyTemplate) { + Preconditions.checkArgument(!Strings.isNullOrEmpty(bodyTemplate), "Pass a non null/empty bodyTemplate"); this.bodyTemplate = Optional.of(bodyTemplate); return this; } public Builder subjectTemplate(String subjectTemplate) { + Preconditions.checkArgument(!Strings.isNullOrEmpty(subjectTemplate), "Pass a non null/empty subjectTemplate"); this.subjectTemplate = Optional.of(subjectTemplate); return this; } http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/listeners/QuotaThresholdCrossingListener.java ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/listeners/QuotaThresholdCrossingListener.java b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/listeners/QuotaThresholdCrossingListener.java index bf917f7..6aaf1cb 100644 --- a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/listeners/QuotaThresholdCrossingListener.java +++ b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/listeners/QuotaThresholdCrossingListener.java @@ -21,10 +21,14 @@ package org.apache.james.mailbox.quota.mailing.listeners; import javax.inject.Inject; +import org.apache.commons.configuration.HierarchicalConfiguration; import org.apache.james.core.User; +import org.apache.james.eventsourcing.CommandHandler; import org.apache.james.eventsourcing.EventSourcingSystem; +import org.apache.james.eventsourcing.Subscriber; import org.apache.james.eventsourcing.eventstore.EventStore; import org.apache.james.filesystem.api.FileSystem; +import org.apache.james.lifecycle.api.Configurable; import org.apache.james.mailbox.Event; import org.apache.james.mailbox.MailboxListener; import org.apache.james.mailbox.quota.mailing.QuotaMailingListenerConfiguration; @@ -38,19 +42,36 @@ import org.slf4j.LoggerFactory; import com.google.common.collect.ImmutableSet; -public class QuotaThresholdCrossingListener implements MailboxListener { +public class QuotaThresholdCrossingListener implements MailboxListener, Configurable { private static final Logger LOGGER = LoggerFactory.getLogger(QuotaThresholdCrossingListener.class); + private final EventStore eventStore; + private final MailetContext mailetContext; + private final UsersRepository usersRepository; + private final FileSystem fileSystem; - private final EventSourcingSystem eventSourcingSystem; + private EventSourcingSystem eventSourcingSystem; @Inject - public QuotaThresholdCrossingListener(MailetContext mailetContext, UsersRepository usersRepository, - FileSystem fileSystem, EventStore eventStore, QuotaMailingListenerConfiguration configuration) { - this.eventSourcingSystem = new EventSourcingSystem( - ImmutableSet.of(new DetectThresholdCrossingHandler(eventStore, configuration)), - ImmutableSet.of(new QuotaThresholdMailer(mailetContext, usersRepository, fileSystem, configuration)), - eventStore - ); + public QuotaThresholdCrossingListener(MailetContext mailetContext, + UsersRepository usersRepository, + FileSystem fileSystem, + EventStore eventStore) { + this.eventStore = eventStore; + this.mailetContext = mailetContext; + this.usersRepository = usersRepository; + this.fileSystem = fileSystem; + } + + @Override + public void configure(HierarchicalConfiguration config) { + QuotaMailingListenerConfiguration configuration = QuotaMailingListenerConfiguration.from(config); + configure(configuration); + } + + public void configure(QuotaMailingListenerConfiguration configuration) { + ImmutableSet<CommandHandler<?>> handlers = ImmutableSet.of(new DetectThresholdCrossingHandler(eventStore, configuration)); + ImmutableSet<Subscriber> subscribers = ImmutableSet.of(new QuotaThresholdMailer(mailetContext, usersRepository, fileSystem, configuration)); + eventSourcingSystem = new EventSourcingSystem(handlers, subscribers, eventStore); } @Override @@ -85,4 +106,5 @@ public class QuotaThresholdCrossingListener implements MailboxListener { .getUser() .getUserName()); } + } http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/model/QuotaThresholds.java ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/model/QuotaThresholds.java b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/model/QuotaThresholds.java index 042799e..8f92ed3 100644 --- a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/model/QuotaThresholds.java +++ b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/model/QuotaThresholds.java @@ -22,6 +22,7 @@ package org.apache.james.mailbox.quota.model; import java.util.Arrays; import java.util.Comparator; import java.util.List; +import java.util.Objects; import org.apache.james.mailbox.model.Quota; @@ -50,6 +51,21 @@ public class QuotaThresholds { } @Override + public final boolean equals(Object o) { + if (o instanceof QuotaThresholds) { + QuotaThresholds that = (QuotaThresholds) o; + + return Objects.equals(this.quotaThresholds, that.quotaThresholds); + } + return false; + } + + @Override + public final int hashCode() { + return Objects.hash(quotaThresholds); + } + + @Override public String toString() { return MoreObjects.toStringHelper(this) .add("quotaThresholds", quotaThresholds) http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfigurationTest.java ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfigurationTest.java b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfigurationTest.java new file mode 100644 index 0000000..50a4044 --- /dev/null +++ b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfigurationTest.java @@ -0,0 +1,172 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.mailbox.quota.mailing; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.time.Duration; + +import org.apache.commons.configuration.DefaultConfigurationBuilder; +import org.apache.james.mailbox.quota.model.QuotaThreshold; +import org.junit.jupiter.api.Test; + +import nl.jqno.equalsverifier.EqualsVerifier; + +public class QuotaMailingListenerConfigurationTest { + + private static final String SUBJECT_TEMPLATE = "sbj.mustache"; + private static final String BODY_TEMPLATE = "body.mustache"; + + @Test + public void shouldMatchBeanContract() { + EqualsVerifier.forClass(QuotaMailingListenerConfiguration.class) + .allFieldsShouldBeUsed() + .verify(); + } + + @Test + public void fromShouldReadXMLConfiguration() throws Exception { + DefaultConfigurationBuilder xmlConfiguration = new DefaultConfigurationBuilder(); + xmlConfiguration.load(toStream( + "<configuration>\n" + + " <thresholds>\n" + + " <threshold>0.85</threshold>\n" + + " <threshold>0.98</threshold>\n" + + " </thresholds>\n" + + " <gracePeriod>3 days</gracePeriod>\n" + + " <subjectTemplate>" + SUBJECT_TEMPLATE + "</subjectTemplate>\n" + + " <bodyTemplate>" + BODY_TEMPLATE + "</bodyTemplate>\n" + + "</configuration>")); + + QuotaMailingListenerConfiguration result = QuotaMailingListenerConfiguration.from(xmlConfiguration); + + assertThat(result) + .isEqualTo(QuotaMailingListenerConfiguration.builder() + .addThresholds(new QuotaThreshold(0.85), + new QuotaThreshold(0.98)) + .gracePeriod(Duration.ofDays(3)) + .subjectTemplate(SUBJECT_TEMPLATE) + .bodyTemplate(BODY_TEMPLATE) + .build()); + } + + @Test + public void fromShouldAcceptEmptyThreshold() throws Exception { + DefaultConfigurationBuilder xmlConfiguration = new DefaultConfigurationBuilder(); + xmlConfiguration.load(toStream( + "<configuration>\n" + + " <thresholds></thresholds>\n" + + " <gracePeriod>3 days</gracePeriod>\n" + + " <subjectTemplate>" + SUBJECT_TEMPLATE + "</subjectTemplate>\n" + + " <bodyTemplate>" + BODY_TEMPLATE + "</bodyTemplate>\n" + + "</configuration>")); + + QuotaMailingListenerConfiguration result = QuotaMailingListenerConfiguration.from(xmlConfiguration); + + assertThat(result) + .isEqualTo(QuotaMailingListenerConfiguration.builder() + .gracePeriod(Duration.ofDays(3)) + .subjectTemplate(SUBJECT_TEMPLATE) + .bodyTemplate(BODY_TEMPLATE) + .build()); + } + + @Test + public void fromShouldReturnDefaultWhenEmptyConfiguration() throws Exception { + DefaultConfigurationBuilder xmlConfiguration = new DefaultConfigurationBuilder(); + xmlConfiguration.load(toStream( + "<configuration></configuration>")); + + QuotaMailingListenerConfiguration result = QuotaMailingListenerConfiguration.from(xmlConfiguration); + + assertThat(result) + .isEqualTo(QuotaMailingListenerConfiguration.builder() + .build()); + } + + @Test + public void fromShouldThrowOnNonParsableGracePeriod() throws Exception { + DefaultConfigurationBuilder xmlConfiguration = new DefaultConfigurationBuilder(); + xmlConfiguration.load(toStream( + "<configuration><gracePeriod>nonParsable</gracePeriod></configuration>")); + + assertThatThrownBy(() -> QuotaMailingListenerConfiguration.from(xmlConfiguration)) + .isInstanceOf(NumberFormatException.class); + } + + @Test + public void fromShouldThrowOnNegativeGracePeriod() throws Exception { + DefaultConfigurationBuilder xmlConfiguration = new DefaultConfigurationBuilder(); + xmlConfiguration.load(toStream( + "<configuration><gracePeriod>-12 ms</gracePeriod></configuration>")); + + assertThatThrownBy(() -> QuotaMailingListenerConfiguration.from(xmlConfiguration)) + .isInstanceOf(NumberFormatException.class); + } + + @Test + public void fromShouldLoadGracePeriodInMs() throws Exception { + DefaultConfigurationBuilder xmlConfiguration = new DefaultConfigurationBuilder(); + xmlConfiguration.load(toStream( + "<configuration><gracePeriod>12 ms</gracePeriod></configuration>")); + + assertThat(QuotaMailingListenerConfiguration.from(xmlConfiguration).getGracePeriod()) + .isEqualTo(Duration.ofMillis(12)); + } + + @Test + public void defaultUnitShouldBeMilliseconds() throws Exception { + DefaultConfigurationBuilder xmlConfiguration = new DefaultConfigurationBuilder(); + xmlConfiguration.load(toStream( + "<configuration><gracePeriod>12</gracePeriod></configuration>")); + + assertThat(QuotaMailingListenerConfiguration.from(xmlConfiguration).getGracePeriod()) + .isEqualTo(Duration.ofDays(12)); + } + + @Test + public void fromShouldThrowOnEmptySubjectTemplate() throws Exception { + DefaultConfigurationBuilder xmlConfiguration = new DefaultConfigurationBuilder(); + xmlConfiguration.load(toStream( + "<configuration><subjectTemplate></subjectTemplate></configuration>")); + + assertThatThrownBy(() -> QuotaMailingListenerConfiguration.from(xmlConfiguration)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void fromShouldThrowOnEmptyBodyTemplate() throws Exception { + DefaultConfigurationBuilder xmlConfiguration = new DefaultConfigurationBuilder(); + xmlConfiguration.load(toStream( + "<configuration><bodyTemplate></bodyTemplate></configuration>")); + + assertThatThrownBy(() -> QuotaMailingListenerConfiguration.from(xmlConfiguration)) + .isInstanceOf(IllegalArgumentException.class); + } + + private InputStream toStream(String string) { + return new ByteArrayInputStream(string.getBytes(StandardCharsets.UTF_8)); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/listeners/QuotaThresholdListenersTestSystem.java ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/listeners/QuotaThresholdListenersTestSystem.java b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/listeners/QuotaThresholdListenersTestSystem.java index 32f19e3..f6be2c0 100644 --- a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/listeners/QuotaThresholdListenersTestSystem.java +++ b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/listeners/QuotaThresholdListenersTestSystem.java @@ -41,7 +41,9 @@ public class QuotaThresholdListenersTestSystem { FileSystem fileSystem = new FileSystemImpl(new JamesServerResourceLoader(".")); QuotaThresholdCrossingListener thresholdCrossingListener = - new QuotaThresholdCrossingListener(mailetContext, MemoryUsersRepository.withVirtualHosting(), fileSystem, eventStore, configuration); + new QuotaThresholdCrossingListener(mailetContext, MemoryUsersRepository.withVirtualHosting(), fileSystem, eventStore); + + thresholdCrossingListener.configure(configuration); MockMailboxSession mailboxSession = new MockMailboxSession("system"); delegatingListener.addGlobalListener(thresholdCrossingListener, mailboxSession); http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdsTest.java ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdsTest.java b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdsTest.java index 09245eb..b959c1d 100644 --- a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdsTest.java +++ b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdsTest.java @@ -32,9 +32,18 @@ import org.junit.jupiter.api.Test; import com.google.common.collect.ImmutableList; +import nl.jqno.equalsverifier.EqualsVerifier; + public class QuotaThresholdsTest { @Test + public void shouldMatchBeanContract() { + EqualsVerifier.forClass(QuotaThresholds.class) + .allFieldsShouldBeUsed() + .verify(); + } + + @Test public void highestExceededThresholdShouldReturnZeroWhenBelowAllThresholds() { assertThat( new QuotaThresholds(ImmutableList.of(_50, _80, _95, _99)) http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/container/guice/cassandra-guice/pom.xml ---------------------------------------------------------------------- diff --git a/server/container/guice/cassandra-guice/pom.xml b/server/container/guice/cassandra-guice/pom.xml index 11725ec..54f4958 100644 --- a/server/container/guice/cassandra-guice/pom.xml +++ b/server/container/guice/cassandra-guice/pom.xml @@ -146,10 +146,6 @@ </dependency> <dependency> <groupId>${project.groupId}</groupId> - <artifactId>james-server-guice-mailbox-plugin-quota-mailing</artifactId> - </dependency> - <dependency> - <groupId>${project.groupId}</groupId> <artifactId>james-server-guice-mailbox-plugin-spamassassin</artifactId> </dependency> <dependency> http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraQuotaMailingModule.java ---------------------------------------------------------------------- diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraQuotaMailingModule.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraQuotaMailingModule.java index c8994d4..f81d572 100644 --- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraQuotaMailingModule.java +++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraQuotaMailingModule.java @@ -28,8 +28,6 @@ import com.google.inject.multibindings.Multibinder; public class CassandraQuotaMailingModule extends AbstractModule { @Override protected void configure() { - install(new QuotaMailingModule()); - Multibinder.newSetBinder(binder(), EventDTOModule.class) .addBinding() .to(QuotaThresholdChangedEventDTOModule.class); http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/container/guice/mailbox-plugin-quota-mailing/pom.xml ---------------------------------------------------------------------- diff --git a/server/container/guice/mailbox-plugin-quota-mailing/pom.xml b/server/container/guice/mailbox-plugin-quota-mailing/pom.xml deleted file mode 100644 index 1a96872..0000000 --- a/server/container/guice/mailbox-plugin-quota-mailing/pom.xml +++ /dev/null @@ -1,45 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - 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. ---> -<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"> - <modelVersion>4.0.0</modelVersion> - <parent> - <groupId>org.apache.james</groupId> - <artifactId>james-server-guice</artifactId> - <version>3.1.0-SNAPSHOT</version> - <relativePath>../pom.xml</relativePath> - </parent> - - <artifactId>james-server-guice-mailbox-plugin-quota-mailing</artifactId> - - <name>Apache James :: Server :: Guice :: Mailbox :: Plugin :: Quota Mailing</name> - <description>Mailbox modules for Guice implementation of Quota mailing</description> - - <dependencies> - <dependency> - <groupId>${project.groupId}</groupId> - <artifactId>apache-james-mailbox-quota-mailing</artifactId> - </dependency> - <dependency> - <groupId>com.google.inject</groupId> - <artifactId>guice</artifactId> - </dependency> - </dependencies> - -</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/container/guice/mailbox-plugin-quota-mailing/src/main/java/org/apache/james/modules/mailbox/QuotaMailingModule.java ---------------------------------------------------------------------- diff --git a/server/container/guice/mailbox-plugin-quota-mailing/src/main/java/org/apache/james/modules/mailbox/QuotaMailingModule.java b/server/container/guice/mailbox-plugin-quota-mailing/src/main/java/org/apache/james/modules/mailbox/QuotaMailingModule.java deleted file mode 100644 index 7d13cc6..0000000 --- a/server/container/guice/mailbox-plugin-quota-mailing/src/main/java/org/apache/james/modules/mailbox/QuotaMailingModule.java +++ /dev/null @@ -1,41 +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.modules.mailbox; - -import java.time.Duration; - -import org.apache.james.mailbox.quota.mailing.QuotaMailingListenerConfiguration; -import org.apache.james.mailbox.quota.model.QuotaThreshold; - -import com.google.inject.AbstractModule; - -public class QuotaMailingModule extends AbstractModule { - @Override - protected void configure() { - bind(QuotaMailingListenerConfiguration.class) - .toInstance( - QuotaMailingListenerConfiguration.builder() - .addThresholds( - new QuotaThreshold(0.80), - new QuotaThreshold(0.99)) - .gracePeriod(Duration.ofDays(1)) - .build()); - } -} http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/ListenerConfiguration.java ---------------------------------------------------------------------- diff --git a/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/ListenerConfiguration.java b/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/ListenerConfiguration.java index 7258190..f2d5ea3 100644 --- a/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/ListenerConfiguration.java +++ b/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/ListenerConfiguration.java @@ -18,9 +18,10 @@ ****************************************************************/ package org.apache.james.modules.mailbox; +import java.util.Optional; + import org.apache.commons.configuration.HierarchicalConfiguration; -import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import com.google.common.base.Strings; @@ -29,16 +30,32 @@ public class ListenerConfiguration { public static ListenerConfiguration from(HierarchicalConfiguration configuration) { String listenerClass = configuration.getString("class"); Preconditions.checkState(!Strings.isNullOrEmpty(listenerClass), "class name is mandatory"); - return new ListenerConfiguration(listenerClass); + return new ListenerConfiguration(listenerClass, extractSubconfiguration(configuration)); + } + + public static ListenerConfiguration forClass(String clazz) { + return new ListenerConfiguration(clazz, Optional.empty()); + } + + private static Optional<HierarchicalConfiguration> extractSubconfiguration(HierarchicalConfiguration configuration) { + return configuration.configurationsAt("configuration") + .stream() + .findFirst(); } private final String clazz; + private final Optional<HierarchicalConfiguration> configuration; - @VisibleForTesting ListenerConfiguration(String clazz) { + private ListenerConfiguration(String clazz, Optional<HierarchicalConfiguration> configuration) { this.clazz = clazz; + this.configuration = configuration; } public String getClazz() { return clazz; } + + public Optional<HierarchicalConfiguration> getConfiguration() { + return configuration; + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/MailboxListenersLoaderImpl.java ---------------------------------------------------------------------- diff --git a/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/MailboxListenersLoaderImpl.java b/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/MailboxListenersLoaderImpl.java index d8476be..68a8643 100644 --- a/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/MailboxListenersLoaderImpl.java +++ b/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/MailboxListenersLoaderImpl.java @@ -20,6 +20,7 @@ package org.apache.james.modules.mailbox; import java.util.Set; +import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.HierarchicalConfiguration; import org.apache.james.lifecycle.api.Configurable; import org.apache.james.mailbox.MailboxListener; @@ -56,6 +57,7 @@ public class MailboxListenersLoaderImpl implements Configurable, MailboxListener ListenersConfiguration listenersConfiguration = ListenersConfiguration.from(configuration); guiceDefinedListeners.forEach(this::register); + listenersConfiguration.getListenersConfiguration().stream() .map(this::createListener) .forEach(this::register); @@ -78,8 +80,11 @@ public class MailboxListenersLoaderImpl implements Configurable, MailboxListener LOGGER.info("Loading user registered mailbox listener {}", listenerClass); Class<MailboxListener> clazz = classLoader.locateClass(listenerClass); MailboxListener listener = mailboxListenerFactory.createInstance(clazz); + if (listener instanceof Configurable && configuration.getConfiguration().isPresent()) { + ((Configurable)listener).configure(configuration.getConfiguration().get()); + } return listener; - } catch (ClassNotFoundException e) { + } catch (ClassNotFoundException | ConfigurationException e) { LOGGER.error("Error while loading user registered global listener {}", listenerClass, e); throw new RuntimeException(e); } http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/container/guice/mailbox/src/test/java/org/apache/james/modules/mailbox/MailboxListenersLoaderImplTest.java ---------------------------------------------------------------------- diff --git a/server/container/guice/mailbox/src/test/java/org/apache/james/modules/mailbox/MailboxListenersLoaderImplTest.java b/server/container/guice/mailbox/src/test/java/org/apache/james/modules/mailbox/MailboxListenersLoaderImplTest.java index aeff77d..c592907 100644 --- a/server/container/guice/mailbox/src/test/java/org/apache/james/modules/mailbox/MailboxListenersLoaderImplTest.java +++ b/server/container/guice/mailbox/src/test/java/org/apache/james/modules/mailbox/MailboxListenersLoaderImplTest.java @@ -58,7 +58,7 @@ public class MailboxListenersLoaderImplTest { @Test public void createListenerShouldThrowWhenClassCantBeLoaded() { - ListenerConfiguration configuration = new ListenerConfiguration("MyUnknownClass"); + ListenerConfiguration configuration = ListenerConfiguration.forClass("MyUnknownClass"); assertThatThrownBy(() -> testee.createListener(configuration)) .isInstanceOf(RuntimeException.class); @@ -66,7 +66,7 @@ public class MailboxListenersLoaderImplTest { @Test public void createListenerShouldThrowWhenClassCantBeCastToMailboxListener() { - ListenerConfiguration configuration = new ListenerConfiguration("java.lang.String"); + ListenerConfiguration configuration = ListenerConfiguration.forClass("java.lang.String"); assertThatThrownBy(() -> testee.createListener(configuration)) .isInstanceOf(RuntimeException.class); @@ -74,7 +74,7 @@ public class MailboxListenersLoaderImplTest { @Test public void createListenerShouldThrowWhenNotFullClassName() { - ListenerConfiguration configuration = new ListenerConfiguration("NoopMailboxListener"); + ListenerConfiguration configuration = ListenerConfiguration.forClass("NoopMailboxListener"); assertThatThrownBy(() -> testee.createListener(configuration)) .isInstanceOf(RuntimeException.class); @@ -82,7 +82,7 @@ public class MailboxListenersLoaderImplTest { @Test public void createListenerShouldReturnMailboxListenerWhenConfigurationIsGood() { - ListenerConfiguration configuration = new ListenerConfiguration("org.apache.james.modules.mailbox.NoopMailboxListener"); + ListenerConfiguration configuration = ListenerConfiguration.forClass("org.apache.james.modules.mailbox.NoopMailboxListener"); MailboxListener listener = testee.createListener(configuration); http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/container/guice/memory-guice/pom.xml ---------------------------------------------------------------------- diff --git a/server/container/guice/memory-guice/pom.xml b/server/container/guice/memory-guice/pom.xml index a62830e..be1e5a3 100644 --- a/server/container/guice/memory-guice/pom.xml +++ b/server/container/guice/memory-guice/pom.xml @@ -41,6 +41,10 @@ </dependency> <dependency> <groupId>${project.groupId}</groupId> + <artifactId>apache-james-mailbox-quota-mailing</artifactId> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> <artifactId>apache-james-mailbox-scanning-search</artifactId> <type>test-jar</type> </dependency> @@ -92,10 +96,6 @@ </dependency> <dependency> <groupId>${project.groupId}</groupId> - <artifactId>james-server-guice-mailbox-plugin-quota-mailing</artifactId> - </dependency> - <dependency> - <groupId>${project.groupId}</groupId> <artifactId>james-server-guice-mailbox-plugin-spamassassin</artifactId> </dependency> <dependency> http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java ---------------------------------------------------------------------- diff --git a/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java b/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java index 30df53c..99783fd 100644 --- a/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java +++ b/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java @@ -25,7 +25,6 @@ import org.apache.james.modules.data.MemoryDataJmapModule; import org.apache.james.modules.data.MemoryDataModule; import org.apache.james.modules.eventstore.MemoryEventStoreModule; import org.apache.james.modules.mailbox.MemoryMailboxModule; -import org.apache.james.modules.mailbox.QuotaMailingModule; import org.apache.james.modules.protocols.IMAPServerModule; import org.apache.james.modules.protocols.JMAPServerModule; import org.apache.james.modules.protocols.LMTPServerModule; @@ -68,9 +67,6 @@ public class MemoryJamesServerMain { new SMTPServerModule(), new SpamAssassinListenerModule()); - public static final Module PLUGINS = Modules.combine( - new QuotaMailingModule()); - public static final Module JMAP = Modules.combine( new MemoryDataJmapModule(), new JMAPServerModule()); @@ -99,8 +95,7 @@ public class MemoryJamesServerMain { IN_MEMORY_SERVER_MODULE, PROTOCOLS, JMAP, - WEBADMIN, - PLUGINS); + WEBADMIN); public static void main(String[] args) throws Exception { Configuration configuration = Configuration.builder().useWorkingDirectoryEnvProperty().build(); http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/container/guice/pom.xml ---------------------------------------------------------------------- diff --git a/server/container/guice/pom.xml b/server/container/guice/pom.xml index 2bdaf1f..ab62bb7 100644 --- a/server/container/guice/pom.xml +++ b/server/container/guice/pom.xml @@ -45,7 +45,6 @@ <module>jpa-guice</module> <module>jpa-smtp</module> <module>mailbox</module> - <module>mailbox-plugin-quota-mailing</module> <module>mailbox-plugin-spamassassin</module> <module>mailet</module> <module>memory-guice</module> @@ -111,11 +110,6 @@ </dependency> <dependency> <groupId>${project.groupId}</groupId> - <artifactId>james-server-guice-mailbox-plugin-quota-mailing</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>${project.groupId}</groupId> <artifactId>james-server-guice-mailbox-plugin-spamassassin</artifactId> <version>${project.version}</version> </dependency> http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/resources/listeners.xml ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/resources/listeners.xml b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/resources/listeners.xml index 35cb6b5..8c82680 100644 --- a/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/resources/listeners.xml +++ b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/resources/listeners.xml @@ -27,5 +27,10 @@ </listener> <listener> <class>org.apache.james.mailbox.quota.mailing.listeners.QuotaThresholdCrossingListener</class> + <configuration> + <thresholds> + <threshold>0.1</threshold> + </thresholds> + </configuration> </listener> </listeners> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/QuotaMailingTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/QuotaMailingTest.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/QuotaMailingTest.java index 93be0a1..ec5d65a 100644 --- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/QuotaMailingTest.java +++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/QuotaMailingTest.java @@ -29,6 +29,7 @@ import static org.apache.james.jmap.TestingConstants.ARGUMENTS; import static org.apache.james.jmap.TestingConstants.DOMAIN; import static org.apache.james.jmap.TestingConstants.calmlyAwait; import static org.apache.james.jmap.TestingConstants.jmapRequestSpecBuilder; +import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.hasItem; import java.io.IOException; @@ -94,8 +95,7 @@ public abstract class QuotaMailingTest { new SerializableQuotaValue<>(QuotaSize.size(100 * 1000))); bartSendMessageToHomer(); - // Homer receives a 83.995 Bytes mail, triggering the 0.80 threshold mailing - + // Homer receives a mail big enough to trigger a configured threshold calmlyAwait.atMost(30, TimeUnit.SECONDS) .until(() -> listMessageIdsForAccount(homerAccessToken).size() == 2); @@ -116,10 +116,39 @@ public abstract class QuotaMailingTest { hasItem("Warning: Your email usage just exceeded a configured threshold")); } + @Test + public void configurationShouldBeWellLoaded() throws Exception { + jmapServer.getProbe(QuotaProbesImpl.class) + .setMaxStorage(MailboxConstants.USER_NAMESPACE + "&" + HOMER, + new SerializableQuotaValue<>(QuotaSize.size(100 * 1000))); + + bartSendMessageToHomer(); + // Home receives a mail big enough to trigger a configured threshold + + calmlyAwait.atMost(30, TimeUnit.SECONDS) + .until(() -> listMessageIdsForAccount(homerAccessToken).size() == 2); + + List<String> ids = listMessageIdsForAccount(homerAccessToken); + String idString = ids.stream() + .map(id -> "\"" + id + "\"") + .collect(Collectors.joining(",")); + + given() + .header("Authorization", homerAccessToken.serialize()) + .body("[[\"getMessages\", {\"ids\": [" + idString + "]}, \"#0\"]]") + .when() + .post("/jmap") + .then() + .statusCode(200) + .log().ifValidationFails() + .body(ARGUMENTS + ".list.textBody", + hasItem(containsString("You currently occupy more than 10 % of the total size allocated to you"))); + } + private void bartSendMessageToHomer() { String messageCreationId = "creationId"; String outboxId = getOutboxId(bartAccessToken); - String eightyKBBody = Strings.repeat("123456789\n", 80 * 100); + String bigEnoughBody = Strings.repeat("123456789\n", 12 * 100); String requestBody = "[" + " [" + " \"setMessages\"," + @@ -129,7 +158,7 @@ public abstract class QuotaMailingTest { " \"from\": { \"name\": \"Bob\", \"email\": \"" + BART + "\"}," + " \"to\": [{ \"name\": \"User\", \"email\": \"" + HOMER + "\"}]," + " \"subject\": \"Message without an attachment\"," + - " \"textBody\": \"" + eightyKBBody + "\"," + + " \"textBody\": \"" + bigEnoughBody + "\"," + " \"htmlBody\": \"Test <b>body</b>, HTML version\"," + " \"mailboxIds\": [\"" + outboxId + "\"] " + " }}" + http://git-wip-us.apache.org/repos/asf/james-project/blob/80409198/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/listeners.xml ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/listeners.xml b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/listeners.xml index f658226..47a3381 100644 --- a/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/listeners.xml +++ b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/listeners.xml @@ -24,5 +24,10 @@ </listener> <listener> <class>org.apache.james.mailbox.quota.mailing.listeners.QuotaThresholdCrossingListener</class> + <configuration> + <thresholds> + <threshold>0.1</threshold> + </thresholds> + </configuration> </listener> </listeners> \ No newline at end of file --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
