JAMES-2420 DLP rule store API, contract & event sourcing implementation
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/3f368fc7 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/3f368fc7 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/3f368fc7 Branch: refs/heads/master Commit: 3f368fc7c870e15f254f2fc97359e1d9c678d775 Parents: 18ab2d4 Author: benwa <btell...@linagora.com> Authored: Fri Jun 8 17:15:48 2018 +0700 Committer: benwa <btell...@linagora.com> Committed: Thu Jun 14 15:22:58 2018 +0700 ---------------------------------------------------------------------- .../james/eventsourcing/CommandDispatcher.java | 2 +- .../apache/james/eventsourcing/EventBus.java | 5 +- server/data/data-api/pom.xml | 6 +- .../james/dlp/api/DLPConfigurationItem.java | 185 +++++++++++++++++++ .../james/dlp/api/DLPConfigurationStore.java | 41 ++++ .../james/dlp/api/DLPConfigurationItemTest.java | 162 ++++++++++++++++ .../dlp/api/DLPConfigurationStoreContract.java | 101 ++++++++++ .../org/apache/james/dlp/api/DLPFixture.java | 34 ++++ server/data/data-library/pom.xml | 10 + .../EventSourcingDLPConfigurationStore.java | 81 ++++++++ .../aggregates/DLPAggregateId.java | 60 ++++++ .../aggregates/DLPDomainConfiguration.java | 151 +++++++++++++++ .../eventsourcing/commands/ClearCommand.java | 64 +++++++ .../commands/ClearCommandHandler.java | 52 ++++++ .../eventsourcing/commands/StoreCommand.java | 75 ++++++++ .../commands/StoreCommandHandler.java | 52 ++++++ .../events/ConfigurationItemsAdded.java | 89 +++++++++ .../events/ConfigurationItemsRemoved.java | 91 +++++++++ .../aggregates/DLPAggregateIdTest.java | 51 +++++ .../commands/ClearCommandTest.java | 43 +++++ .../commands/StoreCommandTest.java | 53 ++++++ .../events/ConfigurationItemsAddedTest.java | 67 +++++++ .../events/ConfigurationItemsRemovedTest.java | 67 +++++++ server/data/data-memory/pom.xml | 11 ++ .../EventSourcingDLPConfigurationStoreTest.java | 28 +++ ...tSourcingDLPConfigurationStoreExtension.java | 40 ++++ 26 files changed, 1615 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/event-sourcing/event-sourcing-core/src/main/java/org/apache/james/eventsourcing/CommandDispatcher.java ---------------------------------------------------------------------- diff --git a/event-sourcing/event-sourcing-core/src/main/java/org/apache/james/eventsourcing/CommandDispatcher.java b/event-sourcing/event-sourcing-core/src/main/java/org/apache/james/eventsourcing/CommandDispatcher.java index 15d128c..14498ae 100644 --- a/event-sourcing/event-sourcing-core/src/main/java/org/apache/james/eventsourcing/CommandDispatcher.java +++ b/event-sourcing/event-sourcing-core/src/main/java/org/apache/james/eventsourcing/CommandDispatcher.java @@ -86,7 +86,7 @@ public class CommandDispatcher { .orElseThrow(() -> new TooManyRetries(c, MAX_RETRY)); } - public Optional<Integer> trySeveralTimes(Supplier<Boolean> singleTry) { + private Optional<Integer> trySeveralTimes(Supplier<Boolean> singleTry) { return IntStream.range(0, MAX_RETRY) .boxed() .filter(any -> singleTry.get()) http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/event-sourcing/event-sourcing-core/src/main/java/org/apache/james/eventsourcing/EventBus.java ---------------------------------------------------------------------- diff --git a/event-sourcing/event-sourcing-core/src/main/java/org/apache/james/eventsourcing/EventBus.java b/event-sourcing/event-sourcing-core/src/main/java/org/apache/james/eventsourcing/EventBus.java index 289433e..22b817f 100644 --- a/event-sourcing/event-sourcing-core/src/main/java/org/apache/james/eventsourcing/EventBus.java +++ b/event-sourcing/event-sourcing-core/src/main/java/org/apache/james/eventsourcing/EventBus.java @@ -34,7 +34,8 @@ import com.google.common.collect.ImmutableSet; public class EventBus { - public static final Logger LOGGER = LoggerFactory.getLogger(EventBus.class); + private static final Logger LOGGER = LoggerFactory.getLogger(EventBus.class); + private final EventStore eventStore; private final Set<Subscriber> subscribers; @@ -51,7 +52,7 @@ public class EventBus { .forEach(this::handle); } - public void handle(Pair<Event, Subscriber> pair) { + private void handle(Pair<Event, Subscriber> pair) { Subscriber subscriber = pair.getRight(); Event event = pair.getLeft(); try { http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-api/pom.xml ---------------------------------------------------------------------- diff --git a/server/data/data-api/pom.xml b/server/data/data-api/pom.xml index 7a58cfc..26de148 100644 --- a/server/data/data-api/pom.xml +++ b/server/data/data-api/pom.xml @@ -34,13 +34,13 @@ <dependencies> <dependency> + <!-- only used by JamesUser (for MailAddress) --> <groupId>${project.groupId}</groupId> - <artifactId>james-core</artifactId> + <artifactId>apache-mailet-api</artifactId> </dependency> <dependency> - <!-- only used by JamesUser (for MailAddress) --> <groupId>${project.groupId}</groupId> - <artifactId>apache-mailet-api</artifactId> + <artifactId>james-core</artifactId> </dependency> <dependency> <groupId>${project.groupId}</groupId> http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationItem.java ---------------------------------------------------------------------- diff --git a/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationItem.java b/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationItem.java new file mode 100644 index 0000000..bda1c24 --- /dev/null +++ b/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationItem.java @@ -0,0 +1,185 @@ +/**************************************************************** + * 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.dlp.api; + +import java.util.Objects; +import java.util.Optional; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; + +public class DLPConfigurationItem { + + public static class Builder { + private static final boolean NOT_TARGETED = false; + + private Optional<Boolean> targetsSender; + private Optional<Boolean> targetsRecipients; + private Optional<Boolean> targetsContent; + private Optional<String> explanation; + private Optional<String> expression; + + public Builder() { + targetsSender = Optional.empty(); + targetsRecipients = Optional.empty(); + targetsContent = Optional.empty(); + explanation = Optional.empty(); + expression = Optional.empty(); + } + + public Builder targetsSender() { + this.targetsSender = Optional.of(true); + return this; + } + + public Builder targetsRecipients() { + this.targetsRecipients = Optional.of(true); + return this; + } + + public Builder targetsContent() { + this.targetsContent = Optional.of(true); + return this; + } + + public Builder expression(String expression) { + this.expression = Optional.of(expression); + return this; + } + + public Builder explanation(String explanation) { + this.explanation = Optional.of(explanation); + return this; + } + + public DLPConfigurationItem build() { + Preconditions.checkState(expression.isPresent(), "`expression` is mandatory"); + return new DLPConfigurationItem( + explanation, + expression.get(), + new Targets( + targetsSender.orElse(NOT_TARGETED), + targetsRecipients.orElse(NOT_TARGETED), + targetsContent.orElse(NOT_TARGETED))); + } + } + + public static class Targets { + private final boolean senderTargeted; + private final boolean recipientTargeted; + private final boolean contentTargeted; + + public Targets(boolean senderTargeted, boolean recipientTargeted, boolean contentTargeted) { + this.senderTargeted = senderTargeted; + this.recipientTargeted = recipientTargeted; + this.contentTargeted = contentTargeted; + } + + public boolean isSenderTargeted() { + return senderTargeted; + } + + public boolean isRecipientTargeted() { + return recipientTargeted; + } + + public boolean isContentTargeted() { + return contentTargeted; + } + + @Override + public final boolean equals(Object o) { + if (o instanceof Targets) { + Targets targets = (Targets) o; + + return Objects.equals(this.senderTargeted, targets.senderTargeted) + && Objects.equals(this.recipientTargeted, targets.recipientTargeted) + && Objects.equals(this.contentTargeted, targets.contentTargeted); + } + return false; + } + + @Override + public final int hashCode() { + return Objects.hash(senderTargeted, recipientTargeted, contentTargeted); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("senderTargeted", senderTargeted) + .add("recipientTargeted", recipientTargeted) + .add("contentTargeted", contentTargeted) + .toString(); + } + } + + public static Builder builder() { + return new Builder(); + } + + private final Optional<String> explanation; + private final String regexp; + private final Targets targets; + + private DLPConfigurationItem(Optional<String> explanation, String regexp, Targets targets) { + this.explanation = explanation; + this.regexp = regexp; + this.targets = targets; + } + + public Optional<String> getExplanation() { + return explanation; + } + + public String getRegexp() { + return regexp; + } + + public Targets getTargets() { + return targets; + } + + @Override + public final boolean equals(Object o) { + if (o instanceof DLPConfigurationItem) { + DLPConfigurationItem dlpConfigurationItem = (DLPConfigurationItem) o; + + return Objects.equals(this.explanation, dlpConfigurationItem.explanation) + && Objects.equals(this.regexp, dlpConfigurationItem.regexp) + && Objects.equals(this.targets, dlpConfigurationItem.targets); + } + return false; + } + + @Override + public final int hashCode() { + return Objects.hash(explanation, regexp, targets); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("explanation", explanation) + .add("regexp", regexp) + .add("targets", targets) + .toString(); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationStore.java ---------------------------------------------------------------------- diff --git a/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationStore.java b/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationStore.java new file mode 100644 index 0000000..457341e --- /dev/null +++ b/server/data/data-api/src/main/java/org/apache/james/dlp/api/DLPConfigurationStore.java @@ -0,0 +1,41 @@ +/**************************************************************** + * 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.dlp.api; + +import java.util.List; +import java.util.stream.Stream; + +import org.apache.james.core.Domain; + +import com.google.common.collect.ImmutableList; + +public interface DLPConfigurationStore { + + Stream<DLPConfigurationItem> list(Domain domain); + + void store(Domain domain, List<DLPConfigurationItem> rule); + + default void store(Domain domain, DLPConfigurationItem rule) { + store(domain, ImmutableList.of(rule)); + } + + void clear(Domain domain); + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationItemTest.java ---------------------------------------------------------------------- diff --git a/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationItemTest.java b/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationItemTest.java new file mode 100644 index 0000000..4a38bf1 --- /dev/null +++ b/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationItemTest.java @@ -0,0 +1,162 @@ +/**************************************************************** + * 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.dlp.api; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.assertj.core.api.SoftAssertions; +import org.junit.jupiter.api.Test; + +import nl.jqno.equalsverifier.EqualsVerifier; + +public class DLPConfigurationItemTest { + + private static final String EXPLANATION = "explanation"; + private static final String REGEX = "regex"; + + @Test + void shouldMatchBeanContract() { + EqualsVerifier.forClass(DLPConfigurationItem.class) + .allFieldsShouldBeUsed() + .verify(); + } + + @Test + void innerClassTargetsShouldMatchBeanContract() { + EqualsVerifier.forClass(DLPConfigurationItem.Targets.class) + .allFieldsShouldBeUsed() + .verify(); + } + + @Test + void expressionShouldBeMandatory() { + assertThatThrownBy(() -> + DLPConfigurationItem.builder() + .targetsRecipients() + .targetsSender() + .targetsContent() + .explanation(EXPLANATION) + .build()) + .isInstanceOf(IllegalStateException.class); + } + + @Test + void expressionShouldBeTheOnlyMandatoryField() { + assertThatCode(() -> + DLPConfigurationItem.builder() + .expression(REGEX) + .build()) + .doesNotThrowAnyException(); + } + + @Test + void builderShouldPreserveExpression() { + DLPConfigurationItem dlpConfigurationItem = DLPConfigurationItem.builder() + .expression(REGEX) + .build(); + + assertThat(dlpConfigurationItem.getRegexp()).isEqualTo(REGEX); + } + + @Test + void builderShouldPreserveExplanation() { + DLPConfigurationItem dlpConfigurationItem = DLPConfigurationItem.builder() + .explanation(EXPLANATION) + .expression(REGEX) + .build(); + + assertThat(dlpConfigurationItem.getExplanation()).contains(EXPLANATION); + } + + @Test + void dlpRuleShouldHaveNoTargetsWhenNoneSpecified() { + DLPConfigurationItem dlpConfigurationItem = DLPConfigurationItem.builder() + .expression(REGEX) + .build(); + + SoftAssertions.assertSoftly(softly -> { + softly.assertThat(dlpConfigurationItem.getTargets().isContentTargeted()).isFalse(); + softly.assertThat(dlpConfigurationItem.getTargets().isRecipientTargeted()).isFalse(); + softly.assertThat(dlpConfigurationItem.getTargets().isSenderTargeted()).isFalse(); + }); + } + + @Test + void targetsRecipientsShouldBeReportedInTargets() { + DLPConfigurationItem dlpConfigurationItem = DLPConfigurationItem.builder() + .targetsRecipients() + .expression(REGEX) + .build(); + + SoftAssertions.assertSoftly(softly -> { + softly.assertThat(dlpConfigurationItem.getTargets().isContentTargeted()).isFalse(); + softly.assertThat(dlpConfigurationItem.getTargets().isRecipientTargeted()).isTrue(); + softly.assertThat(dlpConfigurationItem.getTargets().isSenderTargeted()).isFalse(); + }); + } + + @Test + void targetsSenderShouldBeReportedInTargets() { + DLPConfigurationItem dlpConfigurationItem = DLPConfigurationItem.builder() + .targetsSender() + .expression(REGEX) + .build(); + + SoftAssertions.assertSoftly(softly -> { + softly.assertThat(dlpConfigurationItem.getTargets().isContentTargeted()).isFalse(); + softly.assertThat(dlpConfigurationItem.getTargets().isRecipientTargeted()).isFalse(); + softly.assertThat(dlpConfigurationItem.getTargets().isSenderTargeted()).isTrue(); + }); + } + + @Test + void targetsContentShouldBeReportedInTargets() { + DLPConfigurationItem dlpConfigurationItem = DLPConfigurationItem.builder() + .targetsContent() + .expression(REGEX) + .build(); + + SoftAssertions.assertSoftly(softly -> { + softly.assertThat(dlpConfigurationItem.getTargets().isContentTargeted()).isTrue(); + softly.assertThat(dlpConfigurationItem.getTargets().isRecipientTargeted()).isFalse(); + softly.assertThat(dlpConfigurationItem.getTargets().isSenderTargeted()).isFalse(); + }); + } + + @Test + void allTargetsShouldBeReportedInTargets() { + DLPConfigurationItem dlpConfigurationItem = DLPConfigurationItem.builder() + .targetsContent() + .targetsSender() + .targetsRecipients() + .expression(REGEX) + .build(); + + SoftAssertions.assertSoftly(softly -> { + softly.assertThat(dlpConfigurationItem.getTargets().isContentTargeted()).isTrue(); + softly.assertThat(dlpConfigurationItem.getTargets().isRecipientTargeted()).isTrue(); + softly.assertThat(dlpConfigurationItem.getTargets().isSenderTargeted()).isTrue(); + }); + } + + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationStoreContract.java ---------------------------------------------------------------------- diff --git a/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationStoreContract.java b/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationStoreContract.java new file mode 100644 index 0000000..fa506b7 --- /dev/null +++ b/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPConfigurationStoreContract.java @@ -0,0 +1,101 @@ +/**************************************************************** + * 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.dlp.api; + +import static org.apache.james.dlp.api.DLPFixture.RULE; +import static org.apache.james.dlp.api.DLPFixture.RULE_2; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; + +import org.apache.james.core.Domain; +import org.junit.jupiter.api.Test; + +import com.google.common.collect.ImmutableList; + +public interface DLPConfigurationStoreContract { + + Domain OTHER_DOMAIN = Domain.of("any.com"); + + @Test + default void listShouldReturnEmptyWhenNone(DLPConfigurationStore dlpConfigurationStore) { + assertThat(dlpConfigurationStore.list(Domain.LOCALHOST)) + .isEmpty(); + } + + @Test + default void listShouldReturnExistingEntries(DLPConfigurationStore dlpConfigurationStore) { + dlpConfigurationStore.store(Domain.LOCALHOST, RULE); + dlpConfigurationStore.store(Domain.LOCALHOST, RULE_2); + + assertThat(dlpConfigurationStore.list(Domain.LOCALHOST)).containsOnly(RULE_2); + } + + @Test + default void listShouldNotReturnEntriesOfOtherDomains(DLPConfigurationStore dlpConfigurationStore) { + dlpConfigurationStore.store(Domain.LOCALHOST, RULE); + dlpConfigurationStore.store(OTHER_DOMAIN, RULE_2); + + assertThat(dlpConfigurationStore.list(Domain.LOCALHOST)).containsOnly(RULE); + } + + @Test + default void clearShouldRemoveAllEnriesOfADomain(DLPConfigurationStore dlpConfigurationStore) { + dlpConfigurationStore.store(Domain.LOCALHOST, RULE); + dlpConfigurationStore.store(Domain.LOCALHOST, RULE_2); + + dlpConfigurationStore.clear(Domain.LOCALHOST); + + assertThat(dlpConfigurationStore.list(Domain.LOCALHOST)).isEmpty(); + } + + @Test + default void clearShouldNotFailWhenDomainDoesNotExist(DLPConfigurationStore dlpConfigurationStore) { + assertThatCode(() -> dlpConfigurationStore.clear(Domain.LOCALHOST)) + .doesNotThrowAnyException(); + } + + @Test + default void clearShouldOnlyRemoveEntriesOfADomain(DLPConfigurationStore dlpConfigurationStore) { + dlpConfigurationStore.store(Domain.LOCALHOST, RULE); + dlpConfigurationStore.store(OTHER_DOMAIN, RULE_2); + + dlpConfigurationStore.clear(Domain.LOCALHOST); + + assertThat(dlpConfigurationStore.list(OTHER_DOMAIN)).containsOnly(RULE_2); + } + @Test + default void clearShouldOnlyRemovePreviouslyExistingEntries(DLPConfigurationStore dlpConfigurationStore) { + dlpConfigurationStore.store(Domain.LOCALHOST, ImmutableList.of(RULE, RULE_2)); + + dlpConfigurationStore.clear(Domain.LOCALHOST); + + dlpConfigurationStore.store(Domain.LOCALHOST, ImmutableList.of(RULE)); + + assertThat(dlpConfigurationStore.list(Domain.LOCALHOST)).containsOnly(RULE); + } + + @Test + default void storeShouldOverwritePreviouslyStoredEntries(DLPConfigurationStore dlpConfigurationStore) { + dlpConfigurationStore.store(Domain.LOCALHOST, ImmutableList.of(RULE, RULE_2)); + dlpConfigurationStore.store(Domain.LOCALHOST, ImmutableList.of(RULE)); + + assertThat(dlpConfigurationStore.list(Domain.LOCALHOST)).containsOnly(RULE); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPFixture.java ---------------------------------------------------------------------- diff --git a/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPFixture.java b/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPFixture.java new file mode 100644 index 0000000..9eea6fc --- /dev/null +++ b/server/data/data-api/src/test/java/org/apache/james/dlp/api/DLPFixture.java @@ -0,0 +1,34 @@ +/**************************************************************** + * 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.dlp.api; + +public interface DLPFixture { + DLPConfigurationItem RULE = DLPConfigurationItem.builder() + .explanation("explanation") + .expression("regex") + .targetsSender() + .build(); + DLPConfigurationItem RULE_2 = DLPConfigurationItem.builder() + .explanation("explanation2") + .expression("regex2") + .targetsSender() + .targetsRecipients() + .build(); +} http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/pom.xml ---------------------------------------------------------------------- diff --git a/server/data/data-library/pom.xml b/server/data/data-library/pom.xml index fe9bb3e..1f3d16d 100644 --- a/server/data/data-library/pom.xml +++ b/server/data/data-library/pom.xml @@ -39,6 +39,10 @@ </dependency> <dependency> <groupId>${project.groupId}</groupId> + <artifactId>event-sourcing-core</artifactId> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> <artifactId>james-server-core</artifactId> <scope>test</scope> </dependency> @@ -48,6 +52,12 @@ </dependency> <dependency> <groupId>${project.groupId}</groupId> + <artifactId>james-server-data-api</artifactId> + <type>test-jar</type> + <scope>test</scope> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> <artifactId>james-server-dnsservice-api</artifactId> </dependency> <dependency> http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/EventSourcingDLPConfigurationStore.java ---------------------------------------------------------------------- diff --git a/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/EventSourcingDLPConfigurationStore.java b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/EventSourcingDLPConfigurationStore.java new file mode 100644 index 0000000..f367135 --- /dev/null +++ b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/EventSourcingDLPConfigurationStore.java @@ -0,0 +1,81 @@ +/**************************************************************** + * 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.dlp.eventsourcing; + +import java.util.List; +import java.util.stream.Stream; + +import javax.inject.Inject; + +import org.apache.james.core.Domain; +import org.apache.james.dlp.api.DLPConfigurationItem; +import org.apache.james.dlp.api.DLPConfigurationStore; +import org.apache.james.dlp.eventsourcing.aggregates.DLPAggregateId; +import org.apache.james.dlp.eventsourcing.aggregates.DLPDomainConfiguration; +import org.apache.james.dlp.eventsourcing.commands.ClearCommand; +import org.apache.james.dlp.eventsourcing.commands.ClearCommandHandler; +import org.apache.james.dlp.eventsourcing.commands.StoreCommand; +import org.apache.james.dlp.eventsourcing.commands.StoreCommandHandler; +import org.apache.james.eventsourcing.EventSourcingSystem; +import org.apache.james.eventsourcing.Subscriber; +import org.apache.james.eventsourcing.eventstore.EventStore; + +import com.google.common.collect.ImmutableSet; + +public class EventSourcingDLPConfigurationStore implements DLPConfigurationStore { + + private static final ImmutableSet<Subscriber> NO_SUBSCRIBER = ImmutableSet.of(); + + private final EventSourcingSystem eventSourcingSystem; + private final EventStore eventStore; + + @Inject + public EventSourcingDLPConfigurationStore(EventStore eventStore) { + this.eventSourcingSystem = new EventSourcingSystem( + ImmutableSet.of( + new ClearCommandHandler(eventStore), + new StoreCommandHandler(eventStore)), + NO_SUBSCRIBER, + eventStore); + this.eventStore = eventStore; + } + + @Override + public Stream<DLPConfigurationItem> list(Domain domain) { + + DLPAggregateId aggregateId = new DLPAggregateId(domain); + + return DLPDomainConfiguration.load( + aggregateId, + eventStore.getEventsOfAggregate(aggregateId)) + .retrieveRules(); + } + + @Override + public void store(Domain domain, List<DLPConfigurationItem> rules) { + eventSourcingSystem.dispatch(new StoreCommand(domain, rules)); + } + + @Override + public void clear(Domain domain) { + eventSourcingSystem.dispatch(new ClearCommand(domain)); + } + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/aggregates/DLPAggregateId.java ---------------------------------------------------------------------- diff --git a/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/aggregates/DLPAggregateId.java b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/aggregates/DLPAggregateId.java new file mode 100644 index 0000000..9e4a61b --- /dev/null +++ b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/aggregates/DLPAggregateId.java @@ -0,0 +1,60 @@ +/**************************************************************** + * 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.dlp.eventsourcing.aggregates; + +import java.util.Objects; + +import org.apache.james.core.Domain; +import org.apache.james.eventsourcing.AggregateId; + +import com.google.common.base.Preconditions; + +public class DLPAggregateId implements AggregateId { + private static final String SEPARATOR = "/"; + private static final String PREFIX = "DLPRule"; + + private final Domain domain; + + public DLPAggregateId(Domain domain) { + Preconditions.checkNotNull(domain); + + this.domain = domain; + } + + @Override + public String asAggregateKey() { + return PREFIX + SEPARATOR + domain.asString(); + } + + @Override + public final boolean equals(Object o) { + if (o instanceof DLPAggregateId) { + DLPAggregateId that = (DLPAggregateId) o; + + return Objects.equals(this.domain, that.domain); + } + return false; + } + + @Override + public final int hashCode() { + return Objects.hash(domain); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/aggregates/DLPDomainConfiguration.java ---------------------------------------------------------------------- diff --git a/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/aggregates/DLPDomainConfiguration.java b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/aggregates/DLPDomainConfiguration.java new file mode 100644 index 0000000..ece6353 --- /dev/null +++ b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/aggregates/DLPDomainConfiguration.java @@ -0,0 +1,151 @@ +/**************************************************************** + * 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.dlp.eventsourcing.aggregates; + +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Stream; + +import org.apache.james.dlp.api.DLPConfigurationItem; +import org.apache.james.dlp.eventsourcing.events.ConfigurationItemsAdded; +import org.apache.james.dlp.eventsourcing.events.ConfigurationItemsRemoved; +import org.apache.james.eventsourcing.Event; +import org.apache.james.eventsourcing.EventId; +import org.apache.james.eventsourcing.eventstore.History; +import org.apache.james.util.OptionalUtils; + +import com.github.steveash.guavate.Guavate; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; + +public class DLPDomainConfiguration { + + public static DLPDomainConfiguration load(DLPAggregateId aggregateId, History history) { + return new DLPDomainConfiguration(aggregateId, history); + } + + private static class State { + + static State initial() { + return new State(ImmutableSet.of()); + } + + final ImmutableSet<DLPConfigurationItem> rules; + + private State(ImmutableSet<DLPConfigurationItem> rules) { + this.rules = rules; + } + + State add(DLPConfigurationItem rule) { + return add(ImmutableList.of(rule)); + } + + State add(List<DLPConfigurationItem> toAdd) { + ImmutableSet<DLPConfigurationItem> union = Stream.concat(this.rules.stream(), toAdd.stream()).collect(Guavate.toImmutableSet()); + return new State(union); + } + + State remove(DLPConfigurationItem toRemove) { + return remove(ImmutableList.of(toRemove)); + } + + State remove(List<DLPConfigurationItem> toRemove) { + ImmutableSet<DLPConfigurationItem> filtered = rules.stream().filter(rule -> !toRemove.contains(rule)).collect(Guavate.toImmutableSet()); + return new State(filtered); + } + } + + private final DLPAggregateId aggregateId; + private final History history; + private State state; + + private DLPDomainConfiguration(DLPAggregateId aggregateId, History history) { + this.aggregateId = aggregateId; + this.state = State.initial(); + history.getEvents().forEach(this::apply); + this.history = history; + } + + public Stream<DLPConfigurationItem> retrieveRules() { + return state.rules.stream(); + } + + public List<Event> clear() { + ImmutableList<DLPConfigurationItem> rules = retrieveRules().collect(Guavate.toImmutableList()); + if (!rules.isEmpty()) { + ImmutableList<Event> events = ImmutableList.of(new ConfigurationItemsRemoved(aggregateId, history.getNextEventId(), rules)); + events.forEach(this::apply); + return events; + } else { + return ImmutableList.of(); + } + } + + public List<Event> store(List<DLPConfigurationItem> updatedRules) { + ImmutableSet<DLPConfigurationItem> existingRules = retrieveRules().collect(Guavate.toImmutableSet()); + ImmutableSet<DLPConfigurationItem> updatedRulesSet = ImmutableSet.copyOf(updatedRules); + + Optional<Event> removedRulesEvent = generateRemovedRulesEvent(existingRules, updatedRulesSet); + Optional<Event> addedRulesEvent = generateAddedRulesEvent(existingRules, updatedRulesSet, computeNextEventId(removedRulesEvent)); + + ImmutableList<Event> events = Stream + .of(removedRulesEvent, addedRulesEvent) + .flatMap(OptionalUtils::toStream) + .collect(Guavate.toImmutableList()); + + events.forEach(this::apply); + return events; + } + + private EventId computeNextEventId(Optional<Event> removedRulesEvent) { + return removedRulesEvent + .map(Event::eventId) + .map(EventId::next) + .orElse(history.getNextEventId()); + } + + private Optional<Event> generateRemovedRulesEvent(ImmutableSet<DLPConfigurationItem> existingRules, ImmutableSet<DLPConfigurationItem> updateRulesSet) { + Set<DLPConfigurationItem> removedRules = Sets.difference(existingRules, updateRulesSet); + if (!removedRules.isEmpty()) { + return Optional.of(new ConfigurationItemsRemoved(aggregateId, history.getNextEventId(), removedRules)); + } + return Optional.empty(); + } + + private Optional<Event> generateAddedRulesEvent(Set<DLPConfigurationItem> existingRules, Set<DLPConfigurationItem> updateRulesSet, EventId nextEventId) { + Set<DLPConfigurationItem> addedRules = Sets.difference(updateRulesSet, existingRules); + if (!addedRules.isEmpty()) { + return Optional.of(new ConfigurationItemsAdded(aggregateId, nextEventId, addedRules)); + } + return Optional.empty(); + } + + private void apply(Event event) { + if (event instanceof ConfigurationItemsAdded) { + state = state.add(((ConfigurationItemsAdded) event).getRules()); + } + if (event instanceof ConfigurationItemsRemoved) { + state = state.remove(((ConfigurationItemsRemoved) event).getRules()); + } + } + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/ClearCommand.java ---------------------------------------------------------------------- diff --git a/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/ClearCommand.java b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/ClearCommand.java new file mode 100644 index 0000000..1cb4513 --- /dev/null +++ b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/ClearCommand.java @@ -0,0 +1,64 @@ +/**************************************************************** + * 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.dlp.eventsourcing.commands; + +import java.util.Objects; + +import org.apache.james.core.Domain; +import org.apache.james.eventsourcing.Command; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; + +public class ClearCommand implements Command { + private final Domain domain; + + public ClearCommand(Domain domain) { + Preconditions.checkNotNull(domain); + + this.domain = domain; + } + + public Domain getDomain() { + return domain; + } + + @Override + public final boolean equals(Object o) { + if (o instanceof ClearCommand) { + ClearCommand that = (ClearCommand) o; + + return Objects.equals(this.domain, that.domain); + } + return false; + } + + @Override + public final int hashCode() { + return Objects.hash(domain); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("domain", domain) + .toString(); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/ClearCommandHandler.java ---------------------------------------------------------------------- diff --git a/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/ClearCommandHandler.java b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/ClearCommandHandler.java new file mode 100644 index 0000000..a0b0c18 --- /dev/null +++ b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/ClearCommandHandler.java @@ -0,0 +1,52 @@ +/**************************************************************** + * 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.dlp.eventsourcing.commands; + +import java.util.List; + +import org.apache.james.dlp.eventsourcing.aggregates.DLPAggregateId; +import org.apache.james.dlp.eventsourcing.aggregates.DLPDomainConfiguration; +import org.apache.james.eventsourcing.CommandHandler; +import org.apache.james.eventsourcing.Event; +import org.apache.james.eventsourcing.eventstore.EventStore; + +public class ClearCommandHandler implements CommandHandler<ClearCommand> { + + private final EventStore eventStore; + + public ClearCommandHandler(EventStore eventStore) { + this.eventStore = eventStore; + } + + @Override + public Class<ClearCommand> handledClass() { + return ClearCommand.class; + } + + @Override + public List<? extends Event> handle(ClearCommand clearCommand) { + DLPAggregateId aggregateId = new DLPAggregateId(clearCommand.getDomain()); + + return DLPDomainConfiguration.load( + aggregateId, + eventStore.getEventsOfAggregate(aggregateId)) + .clear(); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/StoreCommand.java ---------------------------------------------------------------------- diff --git a/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/StoreCommand.java b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/StoreCommand.java new file mode 100644 index 0000000..d48bfa4 --- /dev/null +++ b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/StoreCommand.java @@ -0,0 +1,75 @@ +/**************************************************************** + * 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.dlp.eventsourcing.commands; + +import java.util.List; +import java.util.Objects; + +import org.apache.james.core.Domain; +import org.apache.james.dlp.api.DLPConfigurationItem; +import org.apache.james.eventsourcing.Command; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; + +public class StoreCommand implements Command { + private final Domain domain; + private final List<DLPConfigurationItem> rules; + + public StoreCommand(Domain domain, List<DLPConfigurationItem> rules) { + Preconditions.checkNotNull(domain); + Preconditions.checkNotNull(rules); + + this.domain = domain; + this.rules = rules; + } + + public Domain getDomain() { + return domain; + } + + public List<DLPConfigurationItem> getRules() { + return rules; + } + + @Override + public final boolean equals(Object o) { + if (o instanceof StoreCommand) { + StoreCommand that = (StoreCommand) o; + + return Objects.equals(this.domain, that.domain) + && Objects.equals(this.rules, that.rules); + } + return false; + } + + @Override + public final int hashCode() { + return Objects.hash(domain, rules); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("domain", domain) + .add("rules", rules) + .toString(); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/StoreCommandHandler.java ---------------------------------------------------------------------- diff --git a/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/StoreCommandHandler.java b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/StoreCommandHandler.java new file mode 100644 index 0000000..dc81548 --- /dev/null +++ b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/commands/StoreCommandHandler.java @@ -0,0 +1,52 @@ +/**************************************************************** + * 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.dlp.eventsourcing.commands; + +import java.util.List; + +import org.apache.james.dlp.eventsourcing.aggregates.DLPAggregateId; +import org.apache.james.dlp.eventsourcing.aggregates.DLPDomainConfiguration; +import org.apache.james.eventsourcing.CommandHandler; +import org.apache.james.eventsourcing.Event; +import org.apache.james.eventsourcing.eventstore.EventStore; + +public class StoreCommandHandler implements CommandHandler<StoreCommand> { + + private final EventStore eventStore; + + public StoreCommandHandler(EventStore eventStore) { + this.eventStore = eventStore; + } + + @Override + public Class<StoreCommand> handledClass() { + return StoreCommand.class; + } + + @Override + public List<? extends Event> handle(StoreCommand storeCommand) { + DLPAggregateId aggregateId = new DLPAggregateId(storeCommand.getDomain()); + + return DLPDomainConfiguration.load( + aggregateId, + eventStore.getEventsOfAggregate(aggregateId)) + .store(storeCommand.getRules()); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsAdded.java ---------------------------------------------------------------------- diff --git a/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsAdded.java b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsAdded.java new file mode 100644 index 0000000..7a150df --- /dev/null +++ b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsAdded.java @@ -0,0 +1,89 @@ +/**************************************************************** + * 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.dlp.eventsourcing.events; + +import java.util.Collection; +import java.util.List; +import java.util.Objects; + +import org.apache.james.dlp.api.DLPConfigurationItem; +import org.apache.james.dlp.eventsourcing.aggregates.DLPAggregateId; +import org.apache.james.eventsourcing.Event; +import org.apache.james.eventsourcing.EventId; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +public class ConfigurationItemsAdded implements Event { + private final DLPAggregateId aggregateId; + private final EventId eventId; + private final List<DLPConfigurationItem> rules; + + public ConfigurationItemsAdded(DLPAggregateId aggregateId, EventId eventId, Collection<DLPConfigurationItem> rules) { + Preconditions.checkNotNull(aggregateId); + Preconditions.checkNotNull(eventId); + Preconditions.checkNotNull(rules); + Preconditions.checkArgument(!rules.isEmpty()); + + this.aggregateId = aggregateId; + this.eventId = eventId; + this.rules = ImmutableList.copyOf(rules); + } + + @Override + public EventId eventId() { + return eventId; + } + + public DLPAggregateId getAggregateId() { + return aggregateId; + } + + public List<DLPConfigurationItem> getRules() { + return rules; + } + + @Override + public final boolean equals(Object o) { + if (o instanceof ConfigurationItemsAdded) { + ConfigurationItemsAdded that = (ConfigurationItemsAdded) o; + + return Objects.equals(this.aggregateId, that.aggregateId) + && Objects.equals(this.eventId, that.eventId) + && Objects.equals(this.rules, that.rules); + } + return false; + } + + @Override + public final int hashCode() { + return Objects.hash(aggregateId, eventId, rules); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("aggregateId", aggregateId) + .add("eventId", eventId) + .add("rules", rules) + .toString(); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsRemoved.java ---------------------------------------------------------------------- diff --git a/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsRemoved.java b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsRemoved.java new file mode 100644 index 0000000..572617a --- /dev/null +++ b/server/data/data-library/src/main/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsRemoved.java @@ -0,0 +1,91 @@ +/**************************************************************** + * 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.dlp.eventsourcing.events; + +import java.util.Collection; +import java.util.List; +import java.util.Objects; + +import org.apache.james.dlp.api.DLPConfigurationItem; +import org.apache.james.dlp.eventsourcing.aggregates.DLPAggregateId; +import org.apache.james.eventsourcing.AggregateId; +import org.apache.james.eventsourcing.Event; +import org.apache.james.eventsourcing.EventId; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +public class ConfigurationItemsRemoved implements Event { + private final DLPAggregateId aggregateId; + private final EventId eventId; + private final List<DLPConfigurationItem> rules; + + public ConfigurationItemsRemoved(DLPAggregateId aggregateId, EventId eventId, Collection<DLPConfigurationItem> rules) { + Preconditions.checkNotNull(aggregateId); + Preconditions.checkNotNull(eventId); + Preconditions.checkNotNull(rules); + Preconditions.checkArgument(!rules.isEmpty()); + + this.aggregateId = aggregateId; + this.eventId = eventId; + this.rules = ImmutableList.copyOf(rules); + } + + @Override + public EventId eventId() { + return eventId; + } + + @Override + public AggregateId getAggregateId() { + return aggregateId; + } + + public List<DLPConfigurationItem> getRules() { + return rules; + } + + @Override + public final boolean equals(Object o) { + if (o instanceof ConfigurationItemsRemoved) { + ConfigurationItemsRemoved that = (ConfigurationItemsRemoved) o; + + return Objects.equals(this.aggregateId, that.aggregateId) + && Objects.equals(this.eventId, that.eventId) + && Objects.equals(this.rules, that.rules); + } + return false; + } + + @Override + public final int hashCode() { + return Objects.hash(aggregateId, eventId, rules); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("aggregateId", aggregateId) + .add("eventId", eventId) + .add("rules", rules) + .toString(); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/aggregates/DLPAggregateIdTest.java ---------------------------------------------------------------------- diff --git a/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/aggregates/DLPAggregateIdTest.java b/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/aggregates/DLPAggregateIdTest.java new file mode 100644 index 0000000..3604974 --- /dev/null +++ b/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/aggregates/DLPAggregateIdTest.java @@ -0,0 +1,51 @@ +/**************************************************************** + * 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.dlp.eventsourcing.aggregates; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.apache.james.core.Domain; +import org.junit.Test; + +import nl.jqno.equalsverifier.EqualsVerifier; + +public class DLPAggregateIdTest { + + @Test + public void shouldMatchBeanContract() { + EqualsVerifier.forClass(DLPAggregateId.class) + .allFieldsShouldBeUsed() + .verify(); + } + + @Test + public void constructorShouldThrowWhenNullDomain() { + assertThatThrownBy(() -> new DLPAggregateId(null)) + .isInstanceOf(NullPointerException.class); + } + + @Test + public void asAggregateKeyShouldReturnAStringContainingThePrefixAndTheDomain() { + assertThat(new DLPAggregateId(Domain.LOCALHOST).asAggregateKey()) + .isEqualTo("DLPRule/localhost"); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/commands/ClearCommandTest.java ---------------------------------------------------------------------- diff --git a/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/commands/ClearCommandTest.java b/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/commands/ClearCommandTest.java new file mode 100644 index 0000000..d859728 --- /dev/null +++ b/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/commands/ClearCommandTest.java @@ -0,0 +1,43 @@ +/**************************************************************** + * 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.dlp.eventsourcing.commands; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.junit.Test; + +import nl.jqno.equalsverifier.EqualsVerifier; + +public class ClearCommandTest { + + @Test + public void shouldMatchBeanContract() { + EqualsVerifier.forClass(ClearCommand.class) + .allFieldsShouldBeUsed() + .verify(); + } + + @Test + public void constructorShouldThrowWhenNullDomain() { + assertThatThrownBy(() -> new ClearCommand(null)) + .isInstanceOf(NullPointerException.class); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/commands/StoreCommandTest.java ---------------------------------------------------------------------- diff --git a/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/commands/StoreCommandTest.java b/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/commands/StoreCommandTest.java new file mode 100644 index 0000000..5b6b473 --- /dev/null +++ b/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/commands/StoreCommandTest.java @@ -0,0 +1,53 @@ +/**************************************************************** + * 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.dlp.eventsourcing.commands; + +import static org.apache.james.dlp.api.DLPFixture.RULE; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.apache.james.core.Domain; +import org.junit.Test; + +import com.google.common.collect.ImmutableList; + +import nl.jqno.equalsverifier.EqualsVerifier; + +public class StoreCommandTest { + + @Test + public void shouldMatchBeanContract() { + EqualsVerifier.forClass(StoreCommand.class) + .allFieldsShouldBeUsed() + .verify(); + } + + @Test + public void constructorShouldThrowWhenNullDomain() { + assertThatThrownBy(() -> new StoreCommand(null, ImmutableList.of(RULE))) + .isInstanceOf(NullPointerException.class); + } + + @Test + public void constructorShouldThrowWhenNullRules() { + assertThatThrownBy(() -> new StoreCommand(Domain.LOCALHOST, null)) + .isInstanceOf(NullPointerException.class); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsAddedTest.java ---------------------------------------------------------------------- diff --git a/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsAddedTest.java b/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsAddedTest.java new file mode 100644 index 0000000..3aa81b5 --- /dev/null +++ b/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsAddedTest.java @@ -0,0 +1,67 @@ +/**************************************************************** + * 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.dlp.eventsourcing.events; + +import static org.apache.james.dlp.api.DLPFixture.RULE; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.apache.james.core.Domain; +import org.apache.james.dlp.eventsourcing.aggregates.DLPAggregateId; +import org.apache.james.eventsourcing.EventId; +import org.junit.Test; + +import com.google.common.collect.ImmutableList; + +import nl.jqno.equalsverifier.EqualsVerifier; + +public class ConfigurationItemsAddedTest { + + @Test + public void shouldMatchBeanContract() { + EqualsVerifier.forClass(ConfigurationItemsAdded.class) + .allFieldsShouldBeUsed() + .verify(); + } + + @Test + public void constructorShouldThrowWhenNullAggregateId() { + assertThatThrownBy(() -> new ConfigurationItemsAdded(null, EventId.first(), ImmutableList.of(RULE))) + .isInstanceOf(NullPointerException.class); + } + + @Test + public void constructorShouldThrowWhenNullEventId() { + assertThatThrownBy(() -> new ConfigurationItemsAdded(new DLPAggregateId(Domain.LOCALHOST), null, ImmutableList.of(RULE))) + .isInstanceOf(NullPointerException.class); + } + + @Test + public void constructorShouldThrowWhenNullRules() { + assertThatThrownBy(() -> new ConfigurationItemsAdded(new DLPAggregateId(Domain.LOCALHOST), EventId.first(), null)) + .isInstanceOf(NullPointerException.class); + } + + @Test + public void constructorShouldThrowWhenEmptyRulesList() { + assertThatThrownBy(() -> new ConfigurationItemsAdded(new DLPAggregateId(Domain.LOCALHOST), EventId.first(), ImmutableList.of())) + .isInstanceOf(IllegalArgumentException.class); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsRemovedTest.java ---------------------------------------------------------------------- diff --git a/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsRemovedTest.java b/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsRemovedTest.java new file mode 100644 index 0000000..2a2027b --- /dev/null +++ b/server/data/data-library/src/test/java/org/apache/james/dlp/eventsourcing/events/ConfigurationItemsRemovedTest.java @@ -0,0 +1,67 @@ +/**************************************************************** + * 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.dlp.eventsourcing.events; + +import static org.apache.james.dlp.api.DLPFixture.RULE; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.apache.james.core.Domain; +import org.apache.james.dlp.eventsourcing.aggregates.DLPAggregateId; +import org.apache.james.eventsourcing.EventId; +import org.junit.Test; + +import com.google.common.collect.ImmutableList; + +import nl.jqno.equalsverifier.EqualsVerifier; + +public class ConfigurationItemsRemovedTest { + + @Test + public void shouldMatchBeanContract() { + EqualsVerifier.forClass(ConfigurationItemsRemoved.class) + .allFieldsShouldBeUsed() + .verify(); + } + + @Test + public void constructorShouldThrowWhenNullAggregateId() { + assertThatThrownBy(() -> new ConfigurationItemsRemoved(null, EventId.first(), ImmutableList.of(RULE))) + .isInstanceOf(NullPointerException.class); + } + + @Test + public void constructorShouldThrowWhenNullEventId() { + assertThatThrownBy(() -> new ConfigurationItemsRemoved(new DLPAggregateId(Domain.LOCALHOST), null, ImmutableList.of())) + .isInstanceOf(NullPointerException.class); + } + + @Test + public void constructorShouldThrowWhenEmptyRulesList() { + assertThatThrownBy(() -> new ConfigurationItemsRemoved(new DLPAggregateId(Domain.LOCALHOST), EventId.first(), ImmutableList.of())) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void constructorShouldThrowWhenNullRulesList() { + assertThatThrownBy(() -> new ConfigurationItemsRemoved(new DLPAggregateId(Domain.LOCALHOST), EventId.first(), null)) + .isInstanceOf(NullPointerException.class); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-memory/pom.xml ---------------------------------------------------------------------- diff --git a/server/data/data-memory/pom.xml b/server/data/data-memory/pom.xml index 6b4661b..38c543b 100644 --- a/server/data/data-memory/pom.xml +++ b/server/data/data-memory/pom.xml @@ -35,7 +35,18 @@ <dependencies> <dependency> <groupId>${project.groupId}</groupId> + <artifactId>event-sourcing-event-store-memory</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>james-server-data-api</artifactId> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> <artifactId>james-server-data-api</artifactId> + <type>test-jar</type> + <scope>test</scope> </dependency> <dependency> <groupId>${project.groupId}</groupId> http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-memory/src/test/java/org/apache/james/dlp/memory/EventSourcingDLPConfigurationStoreTest.java ---------------------------------------------------------------------- diff --git a/server/data/data-memory/src/test/java/org/apache/james/dlp/memory/EventSourcingDLPConfigurationStoreTest.java b/server/data/data-memory/src/test/java/org/apache/james/dlp/memory/EventSourcingDLPConfigurationStoreTest.java new file mode 100644 index 0000000..a226fce --- /dev/null +++ b/server/data/data-memory/src/test/java/org/apache/james/dlp/memory/EventSourcingDLPConfigurationStoreTest.java @@ -0,0 +1,28 @@ +/**************************************************************** + * 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.dlp.memory; + +import org.apache.james.dlp.api.DLPConfigurationStoreContract; +import org.junit.jupiter.api.extension.ExtendWith; + +@ExtendWith(InMemoryEventSourcingDLPConfigurationStoreExtension.class) +public class EventSourcingDLPConfigurationStoreTest implements DLPConfigurationStoreContract { + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/3f368fc7/server/data/data-memory/src/test/java/org/apache/james/dlp/memory/InMemoryEventSourcingDLPConfigurationStoreExtension.java ---------------------------------------------------------------------- diff --git a/server/data/data-memory/src/test/java/org/apache/james/dlp/memory/InMemoryEventSourcingDLPConfigurationStoreExtension.java b/server/data/data-memory/src/test/java/org/apache/james/dlp/memory/InMemoryEventSourcingDLPConfigurationStoreExtension.java new file mode 100644 index 0000000..fe9392c --- /dev/null +++ b/server/data/data-memory/src/test/java/org/apache/james/dlp/memory/InMemoryEventSourcingDLPConfigurationStoreExtension.java @@ -0,0 +1,40 @@ +/**************************************************************** + * 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.dlp.memory; + +import org.apache.james.dlp.api.DLPConfigurationStore; +import org.apache.james.dlp.eventsourcing.EventSourcingDLPConfigurationStore; +import org.apache.james.eventsourcing.eventstore.memory.InMemoryEventStore; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.api.extension.ParameterResolutionException; +import org.junit.jupiter.api.extension.ParameterResolver; + +public class InMemoryEventSourcingDLPConfigurationStoreExtension implements ParameterResolver { + @Override + public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { + return (parameterContext.getParameter().getType() == DLPConfigurationStore.class); + } + + @Override + public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { + return new EventSourcingDLPConfigurationStore(new InMemoryEventStore()); + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org