JAMES-2425 Do not leak protocol over webadmin
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/ee71575a Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/ee71575a Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/ee71575a Branch: refs/heads/master Commit: ee71575a69bd6f6817df90267719b7936a7ad0f5 Parents: c9f8c9c Author: Gautier DI FOLCO <[email protected]> Authored: Fri Jun 15 15:19:36 2018 +0200 Committer: Raphael Ouazana <[email protected]> Committed: Wed Jun 27 15:50:05 2018 +0200 ---------------------------------------------------------------------- .../utils/InMemoryMailRepositoryStore.java | 10 + .../utils/InMemoryMailRepositoryStoreTest.java | 65 +++++ .../MailRepositoryStoreBeanFactory.java | 11 + .../mailrepository/api/MailRepositoryStore.java | 21 +- .../mock/MockMailRepositoryStore.java | 10 + .../transport/mailets/DlpIntegrationTest.java | 8 +- .../transport/mailets/ToRepositoryTest.java | 4 +- .../mailrepository/mailrepository-api/pom.xml | 5 + .../mailrepository/api/MailRepositoryPath.java | 81 ++++++ .../mailrepository/api/MailRepositoryUrl.java | 38 ++- .../api/MailRepositoryUrlTest.java | 40 ++- .../WebAdminServerIntegrationTest.java | 16 +- .../dto/ExtendedMailRepositoryResponse.java | 21 +- .../webadmin/dto/MailRepositoryResponse.java | 19 +- .../dto/SingleMailRepositoryResponse.java | 43 ++++ .../webadmin/routes/MailRepositoriesRoutes.java | 111 ++++---- .../service/ClearMailRepositoryTask.java | 39 +-- .../service/MailRepositoryStoreService.java | 82 +++--- .../service/ReprocessingAllMailsTask.java | 22 +- .../service/ReprocessingOneMailTask.java | 22 +- .../webadmin/service/ReprocessingService.java | 21 +- .../routes/MailRepositoriesRoutesTest.java | 255 ++++++++++--------- .../service/MailRepositoryStoreServiceTest.java | 60 ++--- src/site/markdown/server/manage-webadmin.md | 80 +++--- 24 files changed, 714 insertions(+), 370 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/ee71575a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java ---------------------------------------------------------------------- diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java index 06c2cf3..b93ea77 100644 --- a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java +++ b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java @@ -34,6 +34,7 @@ import org.apache.commons.configuration.DefaultConfigurationBuilder; import org.apache.commons.configuration.HierarchicalConfiguration; import org.apache.james.lifecycle.api.Configurable; import org.apache.james.mailrepository.api.MailRepository; +import org.apache.james.mailrepository.api.MailRepositoryPath; import org.apache.james.mailrepository.api.MailRepositoryStore; import org.apache.james.mailrepository.api.MailRepositoryUrl; import org.apache.james.mailrepository.api.MailRepositoryUrlStore; @@ -101,6 +102,15 @@ public class InMemoryMailRepositoryStore implements MailRepositoryStore, Configu } @Override + public Stream<MailRepository> getByPath(MailRepositoryPath path) { + return destinationToRepositoryAssociations + .keySet() + .stream() + .filter((MailRepositoryUrl key) -> key.getPath().equals(path)) + .map(destinationToRepositoryAssociations::get); + } + + @Override public MailRepository select(MailRepositoryUrl mailRepositoryUrl) { return Optional.ofNullable(destinationToRepositoryAssociations.get(mailRepositoryUrl)) .orElseGet(Throwing.supplier( http://git-wip-us.apache.org/repos/asf/james-project/blob/ee71575a/server/container/guice/guice-common/src/test/java/org/apache/james/utils/InMemoryMailRepositoryStoreTest.java ---------------------------------------------------------------------- diff --git a/server/container/guice/guice-common/src/test/java/org/apache/james/utils/InMemoryMailRepositoryStoreTest.java b/server/container/guice/guice-common/src/test/java/org/apache/james/utils/InMemoryMailRepositoryStoreTest.java index f373bbe..5ad89e4 100644 --- a/server/container/guice/guice-common/src/test/java/org/apache/james/utils/InMemoryMailRepositoryStoreTest.java +++ b/server/container/guice/guice-common/src/test/java/org/apache/james/utils/InMemoryMailRepositoryStoreTest.java @@ -28,6 +28,7 @@ import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.HierarchicalConfiguration; import org.apache.james.core.builder.MimeMessageBuilder; import org.apache.james.mailrepository.api.MailRepository; +import org.apache.james.mailrepository.api.MailRepositoryPath; import org.apache.james.mailrepository.api.MailRepositoryStore; import org.apache.james.mailrepository.api.MailRepositoryUrl; import org.apache.james.mailrepository.file.FileMailRepository; @@ -46,6 +47,8 @@ import com.google.common.collect.Sets; public class InMemoryMailRepositoryStoreTest { private static final MailRepositoryUrl FILE_REPO = MailRepositoryUrl.from("file://repo"); + private static final MailRepositoryUrl MEMORY_REPO = MailRepositoryUrl.from("memory://repo"); + private static final MailRepositoryPath PATH_REPO = MailRepositoryPath.from("repo"); private MemoryMailRepositoryUrlStore urlStore; @@ -150,6 +153,36 @@ public class InMemoryMailRepositoryStoreTest { } @Test + public void getPathsShouldBeEmptyIfNoSelectWerePerformed() { + assertThat(repositoryStore.getPaths()).isEmpty(); + } + + @Test + public void getPathsShouldReturnUsedUrls() { + MailRepositoryPath path1 = MailRepositoryPath.from("repo1"); + MailRepositoryPath path2 = MailRepositoryPath.from("repo1"); + MailRepositoryPath path3 = MailRepositoryPath.from("repo1"); + repositoryStore.select(MailRepositoryUrl.fromPathAndProtocol(path1, "file")); + repositoryStore.select(MailRepositoryUrl.fromPathAndProtocol(path2, "file")); + repositoryStore.select(MailRepositoryUrl.fromPathAndProtocol(path3, "file")); + assertThat(repositoryStore.getPaths()).containsOnly(path1, path2, path3); + } + + @Test + public void getPathsResultsShouldNotBeDuplicatedWithTheSameProtocol() { + repositoryStore.select(FILE_REPO); + repositoryStore.select(FILE_REPO); + assertThat(repositoryStore.getPaths()).containsExactly(PATH_REPO); + } + + @Test + public void getPathsResultsShouldNotBeDuplicatedWithDifferentProtocols() { + repositoryStore.select(FILE_REPO); + repositoryStore.select(MEMORY_REPO); + assertThat(repositoryStore.getPaths()).containsExactly(PATH_REPO); + } + + @Test public void getShouldReturnEmptyWhenUrlNotInUse() { assertThat(repositoryStore.get(FILE_REPO)) .isEmpty(); @@ -172,6 +205,38 @@ public class InMemoryMailRepositoryStoreTest { } @Test + public void getByPathShouldReturnEmptyWhenUrlNotInUse() { + assertThat(repositoryStore.getByPath(PATH_REPO)) + .isEmpty(); + } + + @Test + public void getByPathShouldReturnPreviouslyCreatedMatchingMailRepository() { + MailRepository mailRepository = repositoryStore.select(FILE_REPO); + + assertThat(repositoryStore.getByPath(PATH_REPO)) + .contains(mailRepository); + } + + @Test + public void getByPathShouldReturnPreviouslyCreatedMatchingMailRepositories() { + MailRepository mailRepositoryFile = repositoryStore.select(FILE_REPO); + MailRepository mailRepositoryArbitrary = repositoryStore.select(MEMORY_REPO); + + assertThat(repositoryStore.getByPath(PATH_REPO)) + .contains(mailRepositoryFile) + .contains(mailRepositoryArbitrary); + } + + @Test + public void getByPathShouldReturnEmptyWhenNoMailRepositoriesAreMatching() { + repositoryStore.select(FILE_REPO); + + assertThat(repositoryStore.getByPath(MailRepositoryPath.from("unknown"))) + .isEmpty(); + } + + @Test public void selectShouldNotReturnDifferentResultsWhenUsedInAConcurrentEnvironment() throws Exception { MailRepositoryUrl url = MailRepositoryUrl.from("memory://repo"); int threadCount = 10; http://git-wip-us.apache.org/repos/asf/james-project/blob/ee71575a/server/container/spring/src/main/java/org/apache/james/container/spring/bean/factory/mailrepositorystore/MailRepositoryStoreBeanFactory.java ---------------------------------------------------------------------- diff --git a/server/container/spring/src/main/java/org/apache/james/container/spring/bean/factory/mailrepositorystore/MailRepositoryStoreBeanFactory.java b/server/container/spring/src/main/java/org/apache/james/container/spring/bean/factory/mailrepositorystore/MailRepositoryStoreBeanFactory.java index a05b3ca..93deae5 100644 --- a/server/container/spring/src/main/java/org/apache/james/container/spring/bean/factory/mailrepositorystore/MailRepositoryStoreBeanFactory.java +++ b/server/container/spring/src/main/java/org/apache/james/container/spring/bean/factory/mailrepositorystore/MailRepositoryStoreBeanFactory.java @@ -34,6 +34,7 @@ import org.apache.commons.configuration.HierarchicalConfiguration; import org.apache.james.container.spring.bean.factory.AbstractBeanFactory; import org.apache.james.lifecycle.api.Configurable; import org.apache.james.mailrepository.api.MailRepository; +import org.apache.james.mailrepository.api.MailRepositoryPath; import org.apache.james.mailrepository.api.MailRepositoryStore; import org.apache.james.mailrepository.api.MailRepositoryUrl; import org.apache.james.mailrepository.api.Protocol; @@ -94,6 +95,16 @@ public class MailRepositoryStoreBeanFactory extends AbstractBeanFactory implemen return Optional.ofNullable(repositories.get(url)); } + @Override + public Stream<MailRepository> getByPath(MailRepositoryPath path) { + return repositories + .keySet() + .stream() + .filter((MailRepositoryUrl key) -> key.getPath().equals(path)) + .map(repositories::get); + } + + /** * <p> * Registers a new mail repository type in the mail store's registry based http://git-wip-us.apache.org/repos/asf/james-project/blob/ee71575a/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryStore.java ---------------------------------------------------------------------- diff --git a/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryStore.java b/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryStore.java index 1ae2b5d..babc19c 100644 --- a/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryStore.java +++ b/server/data/data-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryStore.java @@ -19,7 +19,6 @@ package org.apache.james.mailrepository.api; -import java.util.List; import java.util.Optional; import java.util.stream.Stream; @@ -49,13 +48,27 @@ public interface MailRepositoryStore { Optional<MailRepository> get(MailRepositoryUrl url) throws MailRepositoryStoreException; /** - * Return a {@link List} which contains all urls of the selected + * Returns all the {@link MailRepository} for the given path. + */ + Stream<MailRepository> getByPath(MailRepositoryPath path) throws MailRepositoryStoreException; + + /** + * Return a {@link Stream} which contains all urls of the selected * {@link MailRepository}'s - * - * @return urls */ Stream<MailRepositoryUrl> getUrls(); + /** + * Return a {@link Stream} which contains all paths of the selected + * {@link MailRepository}'s + */ + default Stream<MailRepositoryPath> getPaths() { + return getUrls() + .map(MailRepositoryUrl::getPath) + .sorted() + .distinct(); + } + class MailRepositoryStoreException extends Exception { public MailRepositoryStoreException(String msg, Throwable t) { super(msg, t); http://git-wip-us.apache.org/repos/asf/james-project/blob/ee71575a/server/data/data-library/src/test/java/org/apache/james/mailrepository/mock/MockMailRepositoryStore.java ---------------------------------------------------------------------- diff --git a/server/data/data-library/src/test/java/org/apache/james/mailrepository/mock/MockMailRepositoryStore.java b/server/data/data-library/src/test/java/org/apache/james/mailrepository/mock/MockMailRepositoryStore.java index dc3e1d9..6cd742e 100644 --- a/server/data/data-library/src/test/java/org/apache/james/mailrepository/mock/MockMailRepositoryStore.java +++ b/server/data/data-library/src/test/java/org/apache/james/mailrepository/mock/MockMailRepositoryStore.java @@ -25,6 +25,7 @@ import java.util.Optional; import java.util.stream.Stream; import org.apache.james.mailrepository.api.MailRepository; +import org.apache.james.mailrepository.api.MailRepositoryPath; import org.apache.james.mailrepository.api.MailRepositoryStore; import org.apache.james.mailrepository.api.MailRepositoryUrl; @@ -47,6 +48,15 @@ public class MockMailRepositoryStore implements MailRepositoryStore { } @Override + public Stream<MailRepository> getByPath(MailRepositoryPath path) { + return storedObjectMap + .keySet() + .stream() + .filter((MailRepositoryUrl key) -> key.getPath().equals(path)) + .map(storedObjectMap::get); + } + + @Override public Stream<MailRepositoryUrl> getUrls() { return storedObjectMap.keySet().stream(); } http://git-wip-us.apache.org/repos/asf/james-project/blob/ee71575a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/DlpIntegrationTest.java ---------------------------------------------------------------------- diff --git a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/DlpIntegrationTest.java b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/DlpIntegrationTest.java index 0762995..aae098e 100644 --- a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/DlpIntegrationTest.java +++ b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/DlpIntegrationTest.java @@ -174,7 +174,7 @@ public class DlpIntegrationTest { MailRepositoryUrl repositoryUrl = MailRepositoryUrl.from(REPOSITORY_PREFIX + DEFAULT_DOMAIN); given() .spec(specification) - .get("/mailRepositories/" + repositoryUrl.urlEncoded() + "/mails") + .get("/mailRepositories/" + repositoryUrl.getPath().urlEncoded() + "/mails") .then() .statusCode(HttpStatus.NOT_FOUND_404); } @@ -223,7 +223,8 @@ public class DlpIntegrationTest { MailRepositoryUrl repositoryUrl = MailRepositoryUrl.from(REPOSITORY_PREFIX + DEFAULT_DOMAIN); given() .spec(specification) - .put("/mailRepositories/" + repositoryUrl.urlEncoded()); + .param("protocol", repositoryUrl.getProtocol().getValue()) + .put("/mailRepositories/" + repositoryUrl.getPath().urlEncoded()); given() .spec(specification) @@ -253,8 +254,7 @@ public class DlpIntegrationTest { try { return given() .spec(specification) - .get("/mailRepositories/" + repositoryUrl.urlEncoded() + "/mails") - .prettyPeek() + .get("/mailRepositories/" + repositoryUrl.getPath().urlEncoded() + "/mails") .jsonPath() .getList(".") .size() == 1; http://git-wip-us.apache.org/repos/asf/james-project/blob/ee71575a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/ToRepositoryTest.java ---------------------------------------------------------------------- diff --git a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/ToRepositoryTest.java b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/ToRepositoryTest.java index 0fecd96..3bcff8c 100644 --- a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/ToRepositoryTest.java +++ b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/ToRepositoryTest.java @@ -117,7 +117,7 @@ public class ToRepositoryTest { .queryParam("processor", ProcessorConfiguration.STATE_TRANSPORT) .queryParam("action", "reprocess") .patch(MailRepositoriesRoutes.MAIL_REPOSITORIES - + "/" + CUSTOM_REPOSITORY.urlEncoded() + + "/" + CUSTOM_REPOSITORY.getPath().urlEncoded() + "/mails") .jsonPath() .getString("taskId"); @@ -148,7 +148,7 @@ public class ToRepositoryTest { .queryParam("processor", ProcessorConfiguration.STATE_TRANSPORT) .queryParam("action", "reprocess") .patch(MailRepositoriesRoutes.MAIL_REPOSITORIES - + "/" + CUSTOM_REPOSITORY.urlEncoded() + + "/" + CUSTOM_REPOSITORY.getPath().urlEncoded() + "/mails/" + key.asString()) .jsonPath() .get("taskId"); http://git-wip-us.apache.org/repos/asf/james-project/blob/ee71575a/server/mailrepository/mailrepository-api/pom.xml ---------------------------------------------------------------------- diff --git a/server/mailrepository/mailrepository-api/pom.xml b/server/mailrepository/mailrepository-api/pom.xml index cd972a7..e11f0c3 100644 --- a/server/mailrepository/mailrepository-api/pom.xml +++ b/server/mailrepository/mailrepository-api/pom.xml @@ -68,6 +68,11 @@ <artifactId>junit-jupiter-engine</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.junit.platform</groupId> + <artifactId>junit-platform-launcher</artifactId> + <scope>test</scope> + </dependency> </dependencies> <build> http://git-wip-us.apache.org/repos/asf/james-project/blob/ee71575a/server/mailrepository/mailrepository-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryPath.java ---------------------------------------------------------------------- diff --git a/server/mailrepository/mailrepository-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryPath.java b/server/mailrepository/mailrepository-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryPath.java new file mode 100644 index 0000000..31d549d --- /dev/null +++ b/server/mailrepository/mailrepository-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryPath.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.mailrepository.api; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Objects; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; + +public class MailRepositoryPath implements Comparable<MailRepositoryPath> { + public static final MailRepositoryPath fromEncoded(String encodedPath) throws UnsupportedEncodingException { + return new MailRepositoryPath(URLDecoder.decode(encodedPath, StandardCharsets.UTF_8.displayName())); + } + + public static final MailRepositoryPath from(String path) { + return new MailRepositoryPath(path); + } + + private final String value; + + private MailRepositoryPath(String value) { + Preconditions.checkNotNull(value); + this.value = value; + } + + public String asString() { + return value; + } + + public String urlEncoded() throws UnsupportedEncodingException { + return URLEncoder.encode(value, StandardCharsets.UTF_8.displayName()); + } + + @Override + public final boolean equals(Object o) { + if (o instanceof MailRepositoryPath) { + MailRepositoryPath that = (MailRepositoryPath) o; + + return Objects.equals(this.value, that.value); + } + return false; + } + + @Override + public final int hashCode() { + return Objects.hash(value); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("value", value) + .toString(); + } + + @Override + public int compareTo(MailRepositoryPath that) { + return this.value.compareTo(that.value); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/ee71575a/server/mailrepository/mailrepository-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryUrl.java ---------------------------------------------------------------------- diff --git a/server/mailrepository/mailrepository-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryUrl.java b/server/mailrepository/mailrepository-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryUrl.java index c6e69ec..f88ca2a 100644 --- a/server/mailrepository/mailrepository-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryUrl.java +++ b/server/mailrepository/mailrepository-api/src/main/java/org/apache/james/mailrepository/api/MailRepositoryUrl.java @@ -23,37 +23,63 @@ import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import java.util.List; import java.util.Objects; +import com.google.common.base.Joiner; import com.google.common.base.MoreObjects; import com.google.common.base.Preconditions; import com.google.common.base.Splitter; +import com.google.common.collect.Iterables; public class MailRepositoryUrl { - public static final MailRepositoryUrl fromEncoded(String encodedUrl) throws UnsupportedEncodingException { + private static final int PROTOCOL_PART = 0; + private static final String PROTOCOL_SEPARATOR = "://"; + private static final int SKIP_PROTOCOL = 1; + + public static MailRepositoryUrl fromEncoded(String encodedUrl) throws UnsupportedEncodingException { return new MailRepositoryUrl(URLDecoder.decode(encodedUrl, StandardCharsets.UTF_8.displayName())); } - public static final MailRepositoryUrl from(String url) { + public static MailRepositoryUrl from(String url) { return new MailRepositoryUrl(url); } + public static MailRepositoryUrl fromPathAndProtocol(MailRepositoryPath path, String protocol) { + return new MailRepositoryUrl(path, protocol); + } + private final String value; + private final MailRepositoryPath path; private final Protocol protocol; private MailRepositoryUrl(String value) { Preconditions.checkNotNull(value); - Preconditions.checkArgument(value.contains(":"), "':' is mandatory to delimit protocol"); + Preconditions.checkArgument(value.contains(PROTOCOL_SEPARATOR), "The expected format is: <protocol> \"" + PROTOCOL_SEPARATOR + "\" <path>"); this.value = value; - this.protocol = new Protocol(Splitter.on(':') - .splitToList(value) - .get(0)); + List<String> urlParts = Splitter.on(PROTOCOL_SEPARATOR).splitToList(value); + this.protocol = new Protocol(urlParts.get(PROTOCOL_PART)); + this.path = MailRepositoryPath.from( + Joiner.on(PROTOCOL_SEPARATOR) + .join(Iterables.skip(urlParts, SKIP_PROTOCOL))); + } + + private MailRepositoryUrl(MailRepositoryPath path, String protocol) { + Preconditions.checkNotNull(path); + Preconditions.checkNotNull(protocol); + this.path = path; + this.protocol = new Protocol(protocol); + this.value = protocol + PROTOCOL_SEPARATOR + path.asString(); } public String asString() { return value; } + public MailRepositoryPath getPath() { + return path; + } + public String urlEncoded() throws UnsupportedEncodingException { return URLEncoder.encode(value, StandardCharsets.UTF_8.displayName()); } http://git-wip-us.apache.org/repos/asf/james-project/blob/ee71575a/server/mailrepository/mailrepository-api/src/test/java/org/apache/james/mailrepository/api/MailRepositoryUrlTest.java ---------------------------------------------------------------------- diff --git a/server/mailrepository/mailrepository-api/src/test/java/org/apache/james/mailrepository/api/MailRepositoryUrlTest.java b/server/mailrepository/mailrepository-api/src/test/java/org/apache/james/mailrepository/api/MailRepositoryUrlTest.java index 83766b3..64a6d5e 100644 --- a/server/mailrepository/mailrepository-api/src/test/java/org/apache/james/mailrepository/api/MailRepositoryUrlTest.java +++ b/server/mailrepository/mailrepository-api/src/test/java/org/apache/james/mailrepository/api/MailRepositoryUrlTest.java @@ -28,45 +28,69 @@ import nl.jqno.equalsverifier.EqualsVerifier; public class MailRepositoryUrlTest { @Test - public void shouldMatchBeanContract() { + void shouldMatchBeanContract() { EqualsVerifier.forClass(MailRepositoryUrl.class) - .withIgnoredFields("protocol") + .withIgnoredFields("protocol", "path") .verify(); } @Test - public void constructorShouldThrowWhenNull() { + void constructorShouldThrowWhenNull() { assertThatThrownBy(() -> MailRepositoryUrl.from(null)) .isInstanceOf(NullPointerException.class); } @Test - public void constructorShouldThrowWhenNoSeparator() { + void constructorShouldThrowWhenNoSeparator() { assertThatThrownBy(() -> MailRepositoryUrl.from("invalid")) .isInstanceOf(IllegalArgumentException.class); } @Test - public void getProtocolShouldReturnValue() { + void getProtocolShouldReturnValue() { assertThat(MailRepositoryUrl.from("proto://abc").getProtocol()) .isEqualTo(new Protocol("proto")); } @Test - public void getProtocolShouldReturnValueWhenEmpty() { + void getProtocolShouldReturnValueWhenEmpty() { assertThat(MailRepositoryUrl.from("://abc").getProtocol()) .isEqualTo(new Protocol("")); } @Test - public void fromEncodedShouldReturnDecodedValue() throws Exception { + void fromEncodedShouldReturnDecodedValue() throws Exception { assertThat(MailRepositoryUrl.fromEncoded("url%3A%2F%2FmyRepo")) .isEqualTo(MailRepositoryUrl.from("url://myRepo")); } @Test - public void encodedValueShouldEncodeUnderlyingValue() throws Exception { + void fromPathAndProtocolShouldReturnTheFullValue() { + assertThat(MailRepositoryUrl.fromPathAndProtocol(MailRepositoryPath.from("myRepo"), "url")) + .isEqualTo(MailRepositoryUrl.from("url://myRepo")); + } + + @Test + void encodedValueShouldEncodeUnderlyingValue() throws Exception { assertThat(MailRepositoryUrl.from("url://myRepo").urlEncoded()) .isEqualTo("url%3A%2F%2FmyRepo"); } + + @Test + void getPathShouldReturnValue() { + assertThat(MailRepositoryUrl.from("proto://abc").getPath()) + .isEqualTo(MailRepositoryPath.from("abc")); + } + + @Test + void getPathShouldReturnValueWhenEmtpyPath() { + assertThat(MailRepositoryUrl.from("proto://").getPath()) + .isEqualTo(MailRepositoryPath.from("")); + } + + @Test + void getPathShouldReturnValueWhenSeveralProtocolSeparators() { + assertThat(MailRepositoryUrl.from("proto://abc://def").getPath()) + .isEqualTo(MailRepositoryPath.from("abc://def")); + } } http://git-wip-us.apache.org/repos/asf/james-project/blob/ee71575a/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/WebAdminServerIntegrationTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/WebAdminServerIntegrationTest.java b/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/WebAdminServerIntegrationTest.java index a0b5dde..b385f6f 100644 --- a/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/WebAdminServerIntegrationTest.java +++ b/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/WebAdminServerIntegrationTest.java @@ -119,10 +119,10 @@ public class WebAdminServerIntegrationTest { .then() .statusCode(HttpStatus.OK_200) .body("repository", containsInAnyOrder( - "file://var/mail/error/", - "file://var/mail/relay-denied/", - "file://var/mail/spam/", - "file://var/mail/address-error/")); + "var/mail/error/", + "var/mail/relay-denied/", + "var/mail/spam/", + "var/mail/address-error/")); } @Test @@ -135,10 +135,10 @@ public class WebAdminServerIntegrationTest { .then() .statusCode(HttpStatus.OK_200) .body("repository", containsInAnyOrder( - "file://var/mail/error/", - "file://var/mail/relay-denied/", - "file://var/mail/spam/", - "file://var/mail/address-error/")); + "var/mail/error/", + "var/mail/relay-denied/", + "var/mail/spam/", + "var/mail/address-error/")); } @Test http://git-wip-us.apache.org/repos/asf/james-project/blob/ee71575a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/dto/ExtendedMailRepositoryResponse.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/dto/ExtendedMailRepositoryResponse.java b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/dto/ExtendedMailRepositoryResponse.java index a1775a0..40e1dfa 100644 --- a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/dto/ExtendedMailRepositoryResponse.java +++ b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/dto/ExtendedMailRepositoryResponse.java @@ -19,17 +19,30 @@ package org.apache.james.webadmin.dto; -import org.apache.james.mailrepository.api.MailRepositoryUrl; +import java.io.UnsupportedEncodingException; -public class ExtendedMailRepositoryResponse extends MailRepositoryResponse { +import org.apache.james.mailrepository.api.MailRepositoryPath; +public class ExtendedMailRepositoryResponse implements MailRepositoryResponse { + + private final MailRepositoryPath repository; private final long size; - public ExtendedMailRepositoryResponse(MailRepositoryUrl repository, long size) { - super(repository); + public ExtendedMailRepositoryResponse(MailRepositoryPath repository, long size) { + this.repository = repository; this.size = size; } + @Override + public String getRepository() { + return repository.asString(); + } + + @Override + public String getPath() throws UnsupportedEncodingException { + return repository.urlEncoded(); + } + public long getSize() { return size; } http://git-wip-us.apache.org/repos/asf/james-project/blob/ee71575a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/dto/MailRepositoryResponse.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/dto/MailRepositoryResponse.java b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/dto/MailRepositoryResponse.java index 962ffa0..5cb3cd1 100644 --- a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/dto/MailRepositoryResponse.java +++ b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/dto/MailRepositoryResponse.java @@ -21,21 +21,10 @@ package org.apache.james.webadmin.dto; import java.io.UnsupportedEncodingException; -import org.apache.james.mailrepository.api.MailRepositoryUrl; +public interface MailRepositoryResponse { -public class MailRepositoryResponse { + String getRepository(); - private final MailRepositoryUrl repository; + String getPath() throws UnsupportedEncodingException; - public MailRepositoryResponse(MailRepositoryUrl repository) { - this.repository = repository; - } - - public String getRepository() { - return repository.asString(); - } - - public String getId() throws UnsupportedEncodingException { - return repository.urlEncoded(); - } -} +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/ee71575a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/dto/SingleMailRepositoryResponse.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/dto/SingleMailRepositoryResponse.java b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/dto/SingleMailRepositoryResponse.java new file mode 100644 index 0000000..eb2b5dd --- /dev/null +++ b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/dto/SingleMailRepositoryResponse.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.webadmin.dto; + +import java.io.UnsupportedEncodingException; + +import org.apache.james.mailrepository.api.MailRepositoryPath; + +public class SingleMailRepositoryResponse implements MailRepositoryResponse { + + private final MailRepositoryPath repository; + + public SingleMailRepositoryResponse(MailRepositoryPath repository) { + this.repository = repository; + } + + @Override + public String getRepository() { + return repository.asString(); + } + + @Override + public String getPath() throws UnsupportedEncodingException { + return repository.urlEncoded(); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/ee71575a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/routes/MailRepositoriesRoutes.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/routes/MailRepositoriesRoutes.java b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/routes/MailRepositoriesRoutes.java index c69f599..a6f9740 100644 --- a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/routes/MailRepositoriesRoutes.java +++ b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/routes/MailRepositoriesRoutes.java @@ -38,8 +38,8 @@ import javax.ws.rs.Path; import javax.ws.rs.Produces; import org.apache.james.mailrepository.api.MailKey; +import org.apache.james.mailrepository.api.MailRepositoryPath; import org.apache.james.mailrepository.api.MailRepositoryStore; -import org.apache.james.mailrepository.api.MailRepositoryUrl; import org.apache.james.queue.api.MailQueueFactory; import org.apache.james.task.Task; import org.apache.james.task.TaskId; @@ -122,17 +122,27 @@ public class MailRepositoriesRoutes implements Routes { } @PUT - @Path("/{encodedUrl}") + @Path("/{encodedPath}") @ApiOperation(value = "Create a repository") + @ApiImplicitParams({ + @ApiImplicitParam( + required = true, + dataType = "String", + name = "protocol", + paramType = "query", + example = "?protocol=file", + value = "Specify the storage protocol to use"), + }) @ApiResponses(value = { @ApiResponse(code = HttpStatus.NO_CONTENT_204, message = "The repository is created"), @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side."), }) public void definePutMailRepository() { - service.put(MAIL_REPOSITORIES + "/:encodedUrl", (request, response) -> { - MailRepositoryUrl url = decodedRepositoryUrl(request); + service.put(MAIL_REPOSITORIES + "/:encodedPath", (request, response) -> { + MailRepositoryPath path = decodedRepositoryPath(request); + String protocol = request.queryParams("protocol"); try { - repositoryStoreService.createMailRepository(url); + repositoryStoreService.createMailRepository(path, protocol); response.status(HttpStatus.NO_CONTENT_204); return Constants.EMPTY_BODY; } catch (MailRepositoryStore.MailRepositoryStoreException e) { @@ -140,14 +150,14 @@ public class MailRepositoriesRoutes implements Routes { .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500) .type(ErrorResponder.ErrorType.SERVER_ERROR) .cause(e) - .message(String.format("Error while creating a mail repository with url '%s'", url.asString())) + .message(String.format("Error while creating a mail repository with path '%s' and protocol '%s'", path.asString(), protocol)) .haltError(); } }, jsonTransformer); } @GET - @Path("/{encodedUrl}/mails") + @Path("/{encodedPath}/mails") @ApiOperation(value = "Listing all mails in a repository") @ApiImplicitParams({ @ApiImplicitParam( @@ -174,14 +184,13 @@ public class MailRepositoriesRoutes implements Routes { @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side.") }) public void defineListMails() { - service.get(MAIL_REPOSITORIES + "/:encodedUrl/mails", (request, response) -> { + service.get(MAIL_REPOSITORIES + "/:encodedPath/mails", (request, response) -> { Offset offset = ParametersExtractor.extractOffset(request); Limit limit = ParametersExtractor.extractLimit(request); - String encodedUrl = request.params("encodedUrl"); - MailRepositoryUrl url = MailRepositoryUrl.fromEncoded(encodedUrl); + MailRepositoryPath path = decodedRepositoryPath(request); try { - return repositoryStoreService.listMails(url, offset, limit) - .orElseThrow(() -> repositoryNotFound(encodedUrl, url)); + return repositoryStoreService.listMails(path, offset, limit) + .orElseThrow(() -> repositoryNotFound(request.params("encodedPath"), path)); } catch (MailRepositoryStore.MailRepositoryStoreException | MessagingException e) { throw ErrorResponder.builder() @@ -202,13 +211,13 @@ public class MailRepositoriesRoutes implements Routes { }) public void defineGetMailRepositories() { service.get(MAIL_REPOSITORIES, - (request, response) -> repositoryStoreService.listMailRepositories(), + (request, response) -> repositoryStoreService.listMailRepositories().collect(Guavate.toImmutableList()), jsonTransformer); } @GET @Produces("application/json, message/rfc822") - @Path("/{encodedUrl}/mails/{mailKey}") + @Path("/{encodedPath}/mails/{mailKey}") @ApiOperation(value = "Retrieving a specific mail details (this endpoint can accept both \"application/json\" or \"message/rfc822\")") @ApiResponses(value = { @ApiResponse(code = HttpStatus.OK_200, message = "The list of all mails in a repository", response = List.class), @@ -216,15 +225,15 @@ public class MailRepositoriesRoutes implements Routes { @ApiResponse(code = HttpStatus.NOT_FOUND_404, message = "Not found - Could not retrieve the given mail.") }) public void defineGetMail() { - service.get(MAIL_REPOSITORIES + "/:encodedUrl/mails/:mailKey", Constants.JSON_CONTENT_TYPE, + service.get(MAIL_REPOSITORIES + "/:encodedPath/mails/:mailKey", Constants.JSON_CONTENT_TYPE, (request, response) -> - getMailAsJson(decodedRepositoryUrl(request), new MailKey(request.params("mailKey")), request), + getMailAsJson(decodedRepositoryPath(request), new MailKey(request.params("mailKey")), request), jsonTransformer); - service.get(MAIL_REPOSITORIES + "/:encodedUrl/mails/:mailKey", Constants.RFC822_CONTENT_TYPE, + service.get(MAIL_REPOSITORIES + "/:encodedPath/mails/:mailKey", Constants.RFC822_CONTENT_TYPE, (request, response) -> writeMimeMessage( getMailAsMimeMessage( - decodedRepositoryUrl(request), + decodedRepositoryPath(request), new MailKey(request.params("mailKey"))), response.raw())); } @@ -242,18 +251,18 @@ public class MailRepositoriesRoutes implements Routes { return byteArrayOutputStream.size(); } - private MimeMessage getMailAsMimeMessage(MailRepositoryUrl url, MailKey mailKey) { + private MimeMessage getMailAsMimeMessage(MailRepositoryPath path, MailKey mailKey) { try { - return repositoryStoreService.retrieveMessage(url, mailKey) + return repositoryStoreService.retrieveMessage(path, mailKey) .orElseThrow(mailNotFoundError(mailKey)); } catch (MailRepositoryStore.MailRepositoryStoreException | MessagingException e) { throw internalServerError(e); } } - private MailDto getMailAsJson(MailRepositoryUrl url, MailKey mailKey, Request request) { + private MailDto getMailAsJson(MailRepositoryPath path, MailKey mailKey, Request request) { try { - return repositoryStoreService.retrieveMail(url, mailKey, extractAdditionalFields(request.queryParamOrDefault("additionalFields", ""))) + return repositoryStoreService.retrieveMail(path, mailKey, extractAdditionalFields(request.queryParamOrDefault("additionalFields", ""))) .orElseThrow(mailNotFoundError(mailKey)); } catch (MailRepositoryStore.MailRepositoryStoreException | MessagingException e) { throw internalServerError(e); @@ -290,11 +299,11 @@ public class MailRepositoriesRoutes implements Routes { .haltError(); } - private HaltException repositoryNotFound(String encodedUrl, MailRepositoryUrl url) { + private HaltException repositoryNotFound(String encodedPath, MailRepositoryPath path) { return ErrorResponder.builder() .statusCode(HttpStatus.NOT_FOUND_404) .type(ErrorType.NOT_FOUND) - .message("The repository '" + encodedUrl + "' (decoded value: '" + url.asString() + "') does not exist") + .message("The repository '" + encodedPath + "' (decoded value: '" + path.asString() + "') does not exist") .haltError(); } @@ -308,7 +317,7 @@ public class MailRepositoriesRoutes implements Routes { } @GET - @Path("/{encodedUrl}") + @Path("/{encodedPath}") @ApiOperation(value = "Reading the information of a repository, such as size (can take some time to compute)") @ApiResponses(value = { @ApiResponse(code = HttpStatus.OK_200, message = "The repository information", response = List.class), @@ -316,13 +325,12 @@ public class MailRepositoriesRoutes implements Routes { @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side."), }) public void defineGetMailRepository() { - service.get(MAIL_REPOSITORIES + "/:encodedUrl", (request, response) -> { - String encodedUrl = request.params("encodedUrl"); - MailRepositoryUrl url = MailRepositoryUrl.fromEncoded(encodedUrl); + service.get(MAIL_REPOSITORIES + "/:encodedPath", (request, response) -> { + MailRepositoryPath path = decodedRepositoryPath(request); try { - long size = repositoryStoreService.size(url) - .orElseThrow(() -> repositoryNotFound(encodedUrl, url)); - return new ExtendedMailRepositoryResponse(url, size); + long size = repositoryStoreService.size(path) + .orElseThrow(() -> repositoryNotFound(request.params("encodedPath"), path)); + return new ExtendedMailRepositoryResponse(path, size); } catch (MailRepositoryStore.MailRepositoryStoreException e) { throw ErrorResponder.builder() .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500) @@ -335,19 +343,19 @@ public class MailRepositoriesRoutes implements Routes { } @DELETE - @Path("/{encodedUrl}/mails/{mailKey}") + @Path("/{encodedPath}/mails/{mailKey}") @ApiOperation(value = "Deleting a specific mail from that mailRepository") @ApiResponses(value = { @ApiResponse(code = HttpStatus.OK_200, message = "Mail is no more stored in the repository", response = List.class), @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side."), }) public void defineDeleteMail() { - service.delete(MAIL_REPOSITORIES + "/:encodedUrl/mails/:mailKey", (request, response) -> { - MailRepositoryUrl url = decodedRepositoryUrl(request); + service.delete(MAIL_REPOSITORIES + "/:encodedPath/mails/:mailKey", (request, response) -> { + MailRepositoryPath path = decodedRepositoryPath(request); MailKey mailKey = new MailKey(request.params("mailKey")); try { response.status(HttpStatus.NO_CONTENT_204); - repositoryStoreService.deleteMail(url, mailKey); + repositoryStoreService.deleteMail(path, mailKey); return Constants.EMPTY_BODY; } catch (MailRepositoryStore.MailRepositoryStoreException | MessagingException e) { throw ErrorResponder.builder() @@ -361,7 +369,7 @@ public class MailRepositoriesRoutes implements Routes { } @DELETE - @Path("/{encodedUrl}/mails") + @Path("/{encodedPath}/mails") @ApiOperation(value = "Deleting all mails in that mailRepository") @ApiResponses(value = { @ApiResponse(code = HttpStatus.CREATED_201, message = "All mails are deleted", response = TaskIdDto.class), @@ -369,10 +377,10 @@ public class MailRepositoriesRoutes implements Routes { @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Bad request - unknown action") }) public void defineDeleteAll() { - service.delete(MAIL_REPOSITORIES + "/:encodedUrl/mails", (request, response) -> { - MailRepositoryUrl url = decodedRepositoryUrl(request); + service.delete(MAIL_REPOSITORIES + "/:encodedPath/mails", (request, response) -> { + MailRepositoryPath path = decodedRepositoryPath(request); try { - Task task = repositoryStoreService.createClearMailRepositoryTask(url); + Task task = repositoryStoreService.createClearMailRepositoryTask(path); TaskId taskId = taskManager.submit(task); return TaskIdDto.respond(response, taskId); } catch (MailRepositoryStore.MailRepositoryStoreException | MessagingException e) { @@ -387,7 +395,7 @@ public class MailRepositoriesRoutes implements Routes { } @PATCH - @Path("/{encodedUrl}/mails") + @Path("/{encodedPath}/mails") @ApiOperation(value = "Reprocessing all mails in that mailRepository") @ApiImplicitParams({ @ApiImplicitParam( @@ -421,7 +429,7 @@ public class MailRepositoriesRoutes implements Routes { @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Bad request - unknown action") }) public void defineReprocessAll() { - service.patch(MAIL_REPOSITORIES + "/:encodedUrl/mails", (request, response) -> { + service.patch(MAIL_REPOSITORIES + "/:encodedPath/mails", (request, response) -> { Task task = toAllMailReprocessingTask(request); TaskId taskId = taskManager.submit(task); return TaskIdDto.respond(response, taskId); @@ -429,17 +437,17 @@ public class MailRepositoriesRoutes implements Routes { } private Task toAllMailReprocessingTask(Request request) throws UnsupportedEncodingException, MailRepositoryStore.MailRepositoryStoreException, MessagingException { - MailRepositoryUrl url = decodedRepositoryUrl(request); + MailRepositoryPath path = decodedRepositoryPath(request); enforceActionParameter(request); Optional<String> targetProcessor = Optional.ofNullable(request.queryParams("processor")); String targetQueue = Optional.ofNullable(request.queryParams("queue")).orElse(MailQueueFactory.SPOOL); - Long repositorySize = repositoryStoreService.size(url).orElse(0L); - return new ReprocessingAllMailsTask(reprocessingService, repositorySize, url, targetQueue, targetProcessor); + Long repositorySize = repositoryStoreService.size(path).orElse(0L); + return new ReprocessingAllMailsTask(reprocessingService, repositorySize, path, targetQueue, targetProcessor); } @PATCH - @Path("/{encodedUrl}/mails/{key}") + @Path("/{encodedPath}/mails/{key}") @ApiOperation(value = "Reprocessing a single mail in that mailRepository") @ApiImplicitParams({ @ApiImplicitParam( @@ -473,7 +481,7 @@ public class MailRepositoriesRoutes implements Routes { @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Bad request - unknown action") }) public void defineReprocessOne() { - service.patch(MAIL_REPOSITORIES + "/:encodedUrl/mails/:key", (request, response) -> { + service.patch(MAIL_REPOSITORIES + "/:encodedPath/mails/:key", (request, response) -> { Task task = toOneMailReprocessingTask(request); TaskId taskId = taskManager.submit(task); return TaskIdDto.respond(response, taskId); @@ -481,13 +489,13 @@ public class MailRepositoriesRoutes implements Routes { } private Task toOneMailReprocessingTask(Request request) throws UnsupportedEncodingException { - MailRepositoryUrl url = decodedRepositoryUrl(request); + MailRepositoryPath path = decodedRepositoryPath(request); MailKey key = new MailKey(request.params("key")); enforceActionParameter(request); Optional<String> targetProcessor = Optional.ofNullable(request.queryParams("processor")); String targetQueue = Optional.ofNullable(request.queryParams("queue")).orElse(MailQueueFactory.SPOOL); - return new ReprocessingOneMailTask(reprocessingService, url, targetQueue, key, targetProcessor); + return new ReprocessingOneMailTask(reprocessingService, path, targetQueue, key, targetProcessor); } private void enforceActionParameter(Request request) { @@ -501,10 +509,6 @@ public class MailRepositoriesRoutes implements Routes { } } - private MailRepositoryUrl decodedRepositoryUrl(Request request) throws UnsupportedEncodingException { - return MailRepositoryUrl.fromEncoded(request.params("encodedUrl")); - } - private Set<AdditionalField> extractAdditionalFields(String additionalFieldsParam) throws IllegalArgumentException { return Splitter .on(',') @@ -516,4 +520,7 @@ public class MailRepositoriesRoutes implements Routes { .collect(Guavate.toImmutableSet()); } + private MailRepositoryPath decodedRepositoryPath(Request request) throws UnsupportedEncodingException { + return MailRepositoryPath.fromEncoded(request.params("encodedPath")); + } } http://git-wip-us.apache.org/repos/asf/james-project/blob/ee71575a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/ClearMailRepositoryTask.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/ClearMailRepositoryTask.java b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/ClearMailRepositoryTask.java index 853e530..406330f 100644 --- a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/ClearMailRepositoryTask.java +++ b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/ClearMailRepositoryTask.java @@ -19,33 +19,36 @@ package org.apache.james.webadmin.service; +import java.util.List; import java.util.Optional; import java.util.function.Supplier; import javax.mail.MessagingException; import org.apache.james.mailrepository.api.MailRepository; -import org.apache.james.mailrepository.api.MailRepositoryUrl; +import org.apache.james.mailrepository.api.MailRepositoryPath; import org.apache.james.task.Task; import org.apache.james.task.TaskExecutionDetails; +import com.github.fge.lambdas.Throwing; + public class ClearMailRepositoryTask implements Task { public static final String TYPE = "clearMailRepository"; public static class AdditionalInformation implements TaskExecutionDetails.AdditionalInformation { - private final MailRepositoryUrl repositoryUrl; + private final MailRepositoryPath repositoryPath; private final Supplier<Long> countSupplier; private final long initialCount; - public AdditionalInformation(MailRepositoryUrl repositoryUrl, Supplier<Long> countSupplier) { - this.repositoryUrl = repositoryUrl; + public AdditionalInformation(MailRepositoryPath repositoryPath, Supplier<Long> countSupplier) { + this.repositoryPath = repositoryPath; this.initialCount = countSupplier.get(); this.countSupplier = countSupplier; } - public String getRepositoryUrl() { - return repositoryUrl.asString(); + public String getRepositoryPath() { + return repositoryPath.asString(); } public long getRemainingCount() { @@ -57,18 +60,18 @@ public class ClearMailRepositoryTask implements Task { } } - private final MailRepository mailRepository; + private final List<MailRepository> mailRepositories; private final AdditionalInformation additionalInformation; - public ClearMailRepositoryTask(MailRepository mailRepository, MailRepositoryUrl url) { - this.mailRepository = mailRepository; - this.additionalInformation = new AdditionalInformation(url, this::getRemainingSize); + public ClearMailRepositoryTask(List<MailRepository> mailRepositories, MailRepositoryPath path) { + this.mailRepositories = mailRepositories; + this.additionalInformation = new AdditionalInformation(path, this::getRemainingSize); } @Override public Result run() { try { - mailRepository.removeAll(); + removeAllInAllRepositories(); return Result.COMPLETED; } catch (MessagingException e) { LOGGER.error("Encountered error while clearing repository", e); @@ -76,6 +79,10 @@ public class ClearMailRepositoryTask implements Task { } } + private void removeAllInAllRepositories() throws MessagingException { + mailRepositories.forEach(Throwing.consumer(MailRepository::removeAll)); + } + @Override public String type() { return TYPE; @@ -87,10 +94,10 @@ public class ClearMailRepositoryTask implements Task { } public long getRemainingSize() { - try { - return mailRepository.size(); - } catch (MessagingException e) { - throw new RuntimeException(e); - } + return mailRepositories + .stream() + .map(Throwing.function(MailRepository::size).sneakyThrow()) + .mapToLong(Long::valueOf) + .sum(); } } http://git-wip-us.apache.org/repos/asf/james-project/blob/ee71575a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/MailRepositoryStoreService.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/MailRepositoryStoreService.java b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/MailRepositoryStoreService.java index 6efce69..ff4ee76 100644 --- a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/MailRepositoryStoreService.java +++ b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/MailRepositoryStoreService.java @@ -22,6 +22,8 @@ package org.apache.james.webadmin.service; import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.inject.Inject; import javax.mail.MessagingException; @@ -29,6 +31,7 @@ import javax.mail.internet.MimeMessage; import org.apache.james.mailrepository.api.MailKey; import org.apache.james.mailrepository.api.MailRepository; +import org.apache.james.mailrepository.api.MailRepositoryPath; import org.apache.james.mailrepository.api.MailRepositoryStore; import org.apache.james.mailrepository.api.MailRepositoryUrl; import org.apache.james.task.Task; @@ -39,7 +42,7 @@ import org.apache.james.webadmin.dto.InaccessibleFieldException; import org.apache.james.webadmin.dto.MailDto; import org.apache.james.webadmin.dto.MailDto.AdditionalField; import org.apache.james.webadmin.dto.MailKeyDTO; -import org.apache.james.webadmin.dto.MailRepositoryResponse; +import org.apache.james.webadmin.dto.SingleMailRepositoryResponse; import org.apache.james.webadmin.utils.ErrorResponder; import org.apache.mailet.Mail; import org.eclipse.jetty.http.HttpStatus; @@ -56,56 +59,54 @@ public class MailRepositoryStoreService { this.mailRepositoryStore = mailRepositoryStore; } - public List<MailRepositoryResponse> listMailRepositories() { - return mailRepositoryStore.getUrls() - .map(MailRepositoryResponse::new) - .collect(Guavate.toImmutableList()); + public Stream<SingleMailRepositoryResponse> listMailRepositories() { + return mailRepositoryStore + .getPaths() + .map(SingleMailRepositoryResponse::new); } - public MailRepository createMailRepository(MailRepositoryUrl repositoryUrl) throws MailRepositoryStore.MailRepositoryStoreException { - return mailRepositoryStore.create(repositoryUrl); + public MailRepository createMailRepository(MailRepositoryPath repositoryPath, String protocol) throws MailRepositoryStore.MailRepositoryStoreException { + return mailRepositoryStore.create(MailRepositoryUrl.fromPathAndProtocol(repositoryPath, protocol)); } - public Optional<List<MailKeyDTO>> listMails(MailRepositoryUrl url, Offset offset, Limit limit) throws MailRepositoryStore.MailRepositoryStoreException, MessagingException { - Optional<MailRepository> mailRepository = mailRepositoryStore.get(url); - ThrowingFunction<MailRepository, List<MailKeyDTO>> list = repository -> list(repository, offset, limit); - return mailRepository.map(Throwing.function(list).sneakyThrow()); + public Optional<List<MailKeyDTO>> listMails(MailRepositoryPath path, Offset offset, Limit limit) throws MailRepositoryStore.MailRepositoryStoreException, MessagingException { + ThrowingFunction<MailRepository, Stream<MailKeyDTO>> list = repository -> list(repository, offset, limit); + return Optional.of(getRepositories(path) + .flatMap(Throwing.function(list).sneakyThrow()) + .collect(Guavate.toImmutableList())); } - private List<MailKeyDTO> list(MailRepository mailRepository, Offset offset, Limit limit) throws MessagingException { + private Stream<MailKeyDTO> list(MailRepository mailRepository, Offset offset, Limit limit) throws MessagingException { return limit.applyOnStream( Iterators.toStream(mailRepository.list()) .skip(offset.getOffset())) - .map(MailKeyDTO::new) - .collect(Guavate.toImmutableList()); + .map(MailKeyDTO::new); } - public Optional<Long> size(MailRepositoryUrl url) throws MailRepositoryStore.MailRepositoryStoreException { - Optional<MailRepository> mailRepository = mailRepositoryStore.get(url); - return mailRepository.map(Throwing.function(MailRepository::size).sneakyThrow()); + public Optional<Long> size(MailRepositoryPath path) throws MailRepositoryStore.MailRepositoryStoreException { + return Optional.of(getRepositories(path) + .map(Throwing.function(MailRepository::size).sneakyThrow()) + .mapToLong(Long::valueOf) + .sum()); } - public Optional<MailDto> retrieveMail(MailRepositoryUrl url, MailKey mailKey, Set<AdditionalField> additionalAttributes) throws MailRepositoryStore.MailRepositoryStoreException, MessagingException, InaccessibleFieldException { - MailRepository mailRepository = getRepository(url); - - return Optional.ofNullable(mailRepository.retrieve(mailKey)) + public Optional<MailDto> retrieveMail(MailRepositoryPath path, MailKey mailKey, Set<AdditionalField> additionalAttributes) throws MailRepositoryStore.MailRepositoryStoreException, MessagingException, InaccessibleFieldException { + return fecthMail(path, mailKey) .map(Throwing.function((Mail mail) -> MailDto.fromMail(mail, additionalAttributes)).sneakyThrow()); } - public Optional<MimeMessage> retrieveMessage(MailRepositoryUrl url, MailKey mailKey) throws MailRepositoryStore.MailRepositoryStoreException, MessagingException { - MailRepository mailRepository = getRepository(url); - - return Optional.ofNullable(mailRepository.retrieve(mailKey)) + public Optional<MimeMessage> retrieveMessage(MailRepositoryPath path, MailKey mailKey) throws MailRepositoryStore.MailRepositoryStoreException, MessagingException { + return fecthMail(path, mailKey) .map(Throwing.function(Mail::getMessage).sneakyThrow()); } - public void deleteMail(MailRepositoryUrl url, MailKey mailKey) throws MailRepositoryStore.MailRepositoryStoreException, MessagingException { - getRepository(url) - .remove(mailKey); + public void deleteMail(MailRepositoryPath path, MailKey mailKey) throws MailRepositoryStore.MailRepositoryStoreException, MessagingException { + getRepositories(path) + .forEach(Throwing.consumer((MailRepository repository) -> repository.remove(mailKey)).sneakyThrow()); } - public Task createClearMailRepositoryTask(MailRepositoryUrl url) throws MailRepositoryStore.MailRepositoryStoreException, MessagingException { - return new ClearMailRepositoryTask(getRepository(url), url); + public Task createClearMailRepositoryTask(MailRepositoryPath path) throws MailRepositoryStore.MailRepositoryStoreException, MessagingException { + return new ClearMailRepositoryTask(getRepositories(path).collect(Guavate.toImmutableList()), path); } public MailRepository getRepository(MailRepositoryUrl url) throws MailRepositoryStore.MailRepositoryStoreException { @@ -117,4 +118,25 @@ public class MailRepositoryStoreService { .haltError()); } + public Stream<MailRepository> getRepositories(MailRepositoryPath path) throws MailRepositoryStore.MailRepositoryStoreException { + Stream<MailRepository> byPath = mailRepositoryStore.getByPath(path); + List<MailRepository> repositories = byPath.collect(Collectors.toList()); + if (repositories.isEmpty()) { + ErrorResponder.builder() + .statusCode(HttpStatus.NOT_FOUND_404) + .type(ErrorResponder.ErrorType.NOT_FOUND) + .message(path.asString() + " does not exist") + .haltError(); + } + + return repositories.stream(); + } + + private Optional<Mail> fecthMail(MailRepositoryPath path, MailKey mailKey) throws MailRepositoryStore.MailRepositoryStoreException, MessagingException { + return getRepositories(path) + .map(Throwing.function((MailRepository repository) -> Optional.ofNullable(repository.retrieve(mailKey))).sneakyThrow()) + .filter(Optional::isPresent) + .findFirst() + .orElse(Optional.empty()); + } } http://git-wip-us.apache.org/repos/asf/james-project/blob/ee71575a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/ReprocessingAllMailsTask.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/ReprocessingAllMailsTask.java b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/ReprocessingAllMailsTask.java index 26ad50d..05b8ea1 100644 --- a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/ReprocessingAllMailsTask.java +++ b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/ReprocessingAllMailsTask.java @@ -25,8 +25,8 @@ import java.util.concurrent.atomic.AtomicLong; import javax.mail.MessagingException; import org.apache.james.mailrepository.api.MailKey; +import org.apache.james.mailrepository.api.MailRepositoryPath; import org.apache.james.mailrepository.api.MailRepositoryStore; -import org.apache.james.mailrepository.api.MailRepositoryUrl; import org.apache.james.task.Task; import org.apache.james.task.TaskExecutionDetails; @@ -37,14 +37,14 @@ public class ReprocessingAllMailsTask implements Task { public static final String TYPE = "reprocessingAllTask"; public static class AdditionalInformation implements TaskExecutionDetails.AdditionalInformation { - private final MailRepositoryUrl repositoryUrl; + private final MailRepositoryPath repositoryPath; private final String targetQueue; private final Optional<String> targetProcessor; private final long initialCount; private final AtomicLong processedCount; - public AdditionalInformation(MailRepositoryUrl repositoryUrl, String targetQueue, Optional<String> targetProcessor, long initialCount) { - this.repositoryUrl = repositoryUrl; + public AdditionalInformation(MailRepositoryPath repositoryPath, String targetQueue, Optional<String> targetProcessor, long initialCount) { + this.repositoryPath = repositoryPath; this.targetQueue = targetQueue; this.targetProcessor = targetProcessor; this.initialCount = initialCount; @@ -59,8 +59,8 @@ public class ReprocessingAllMailsTask implements Task { return targetProcessor; } - public String getRepositoryUrl() { - return repositoryUrl.asString(); + public String getRepositoryPath() { + return repositoryPath.asString(); } public long getRemainingCount() { @@ -78,25 +78,25 @@ public class ReprocessingAllMailsTask implements Task { } private final ReprocessingService reprocessingService; - private final MailRepositoryUrl repositoryUrl; + private final MailRepositoryPath repositoryPath; private final String targetQueue; private final Optional<String> targetProcessor; private final AdditionalInformation additionalInformation; public ReprocessingAllMailsTask(ReprocessingService reprocessingService, long repositorySize, - MailRepositoryUrl repositoryUrl, String targetQueue, Optional<String> targetProcessor) { + MailRepositoryPath repositoryPath, String targetQueue, Optional<String> targetProcessor) { this.reprocessingService = reprocessingService; - this.repositoryUrl = repositoryUrl; + this.repositoryPath = repositoryPath; this.targetQueue = targetQueue; this.targetProcessor = targetProcessor; this.additionalInformation = new AdditionalInformation( - repositoryUrl, targetQueue, targetProcessor, repositorySize); + repositoryPath, targetQueue, targetProcessor, repositorySize); } @Override public Result run() { try { - reprocessingService.reprocessAll(repositoryUrl, targetProcessor, targetQueue, additionalInformation::notifyProgress); + reprocessingService.reprocessAll(repositoryPath, targetProcessor, targetQueue, additionalInformation::notifyProgress); return Result.COMPLETED; } catch (MessagingException | MailRepositoryStore.MailRepositoryStoreException e) { LOGGER.error("Encountered error while reprocessing repository", e); http://git-wip-us.apache.org/repos/asf/james-project/blob/ee71575a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/ReprocessingOneMailTask.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/ReprocessingOneMailTask.java b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/ReprocessingOneMailTask.java index 453ff8b..550b59a 100644 --- a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/ReprocessingOneMailTask.java +++ b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/ReprocessingOneMailTask.java @@ -24,8 +24,8 @@ import java.util.Optional; import javax.mail.MessagingException; import org.apache.james.mailrepository.api.MailKey; +import org.apache.james.mailrepository.api.MailRepositoryPath; import org.apache.james.mailrepository.api.MailRepositoryStore; -import org.apache.james.mailrepository.api.MailRepositoryUrl; import org.apache.james.task.Task; import org.apache.james.task.TaskExecutionDetails; @@ -34,13 +34,13 @@ public class ReprocessingOneMailTask implements Task { public static final String TYPE = "reprocessingOneTask"; public static class AdditionalInformation implements TaskExecutionDetails.AdditionalInformation { - private final MailRepositoryUrl repositoryUrl; + private final MailRepositoryPath repositoryPath; private final String targetQueue; private final MailKey mailKey; private final Optional<String> targetProcessor; - public AdditionalInformation(MailRepositoryUrl repositoryUrl, String targetQueue, MailKey mailKey, Optional<String> targetProcessor) { - this.repositoryUrl = repositoryUrl; + public AdditionalInformation(MailRepositoryPath repositoryPath, String targetQueue, MailKey mailKey, Optional<String> targetProcessor) { + this.repositoryPath = repositoryPath; this.targetQueue = targetQueue; this.mailKey = mailKey; this.targetProcessor = targetProcessor; @@ -58,32 +58,32 @@ public class ReprocessingOneMailTask implements Task { return targetProcessor; } - public String getRepositoryUrl() { - return repositoryUrl.asString(); + public String getRepositoryPath() { + return repositoryPath.asString(); } } private final ReprocessingService reprocessingService; - private final MailRepositoryUrl repositoryUrl; + private final MailRepositoryPath repositoryPath; private final String targetQueue; private final MailKey mailKey; private final Optional<String> targetProcessor; private final AdditionalInformation additionalInformation; public ReprocessingOneMailTask(ReprocessingService reprocessingService, - MailRepositoryUrl repositoryUrl, String targetQueue, MailKey mailKey, Optional<String> targetProcessor) { + MailRepositoryPath repositoryPath, String targetQueue, MailKey mailKey, Optional<String> targetProcessor) { this.reprocessingService = reprocessingService; - this.repositoryUrl = repositoryUrl; + this.repositoryPath = repositoryPath; this.targetQueue = targetQueue; this.mailKey = mailKey; this.targetProcessor = targetProcessor; - this.additionalInformation = new AdditionalInformation(repositoryUrl, targetQueue, mailKey, targetProcessor); + this.additionalInformation = new AdditionalInformation(repositoryPath, targetQueue, mailKey, targetProcessor); } @Override public Result run() { try { - reprocessingService.reprocess(repositoryUrl, mailKey, targetProcessor, targetQueue); + reprocessingService.reprocess(repositoryPath, mailKey, targetProcessor, targetQueue); return Result.COMPLETED; } catch (MessagingException | MailRepositoryStore.MailRepositoryStoreException e) { LOGGER.error("Encountered error while reprocessing repository", e); http://git-wip-us.apache.org/repos/asf/james-project/blob/ee71575a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/ReprocessingService.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/ReprocessingService.java b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/ReprocessingService.java index fbe68a4..f02bd3f 100644 --- a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/ReprocessingService.java +++ b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/ReprocessingService.java @@ -27,8 +27,8 @@ import javax.mail.MessagingException; import org.apache.james.mailrepository.api.MailKey; import org.apache.james.mailrepository.api.MailRepository; +import org.apache.james.mailrepository.api.MailRepositoryPath; import org.apache.james.mailrepository.api.MailRepositoryStore; -import org.apache.james.mailrepository.api.MailRepositoryUrl; import org.apache.james.queue.api.MailQueue; import org.apache.james.queue.api.MailQueueFactory; import org.apache.james.util.streams.Iterators; @@ -48,20 +48,23 @@ public class ReprocessingService { this.mailRepositoryStoreService = mailRepositoryStoreService; } - public void reprocessAll(MailRepositoryUrl url, Optional<String> targetProcessor, String targetQueue, Consumer<MailKey> keyListener) throws MailRepositoryStore.MailRepositoryStoreException, MessagingException { - MailRepository repository = mailRepositoryStoreService.getRepository(url); + public void reprocessAll(MailRepositoryPath path, Optional<String> targetProcessor, String targetQueue, Consumer<MailKey> keyListener) throws MailRepositoryStore.MailRepositoryStoreException, MessagingException { MailQueue mailQueue = getMailQueue(targetQueue); - Iterators.toStream(repository.list()) - .peek(keyListener) - .forEach(Throwing.consumer(key -> reprocess(repository, mailQueue, key, targetProcessor))); + mailRepositoryStoreService + .getRepositories(path) + .forEach(Throwing.consumer((MailRepository repository) -> + Iterators.toStream(repository.list()) + .peek(keyListener) + .forEach(Throwing.consumer(key -> reprocess(repository, mailQueue, key, targetProcessor)))).sneakyThrow()); } - public void reprocess(MailRepositoryUrl url, MailKey key, Optional<String> targetProcessor, String targetQueue) throws MailRepositoryStore.MailRepositoryStoreException, MessagingException { - MailRepository repository = mailRepositoryStoreService.getRepository(url); + public void reprocess(MailRepositoryPath path, MailKey key, Optional<String> targetProcessor, String targetQueue) throws MailRepositoryStore.MailRepositoryStoreException, MessagingException { MailQueue mailQueue = getMailQueue(targetQueue); - reprocess(repository, mailQueue, key, targetProcessor); + mailRepositoryStoreService + .getRepositories(path) + .forEach(Throwing.consumer((MailRepository repository) -> reprocess(repository, mailQueue, key, targetProcessor)).sneakyThrow()); } private void reprocess(MailRepository repository, MailQueue mailQueue, MailKey key, Optional<String> targetProcessor) throws MessagingException { --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
