This is an automated email from the ASF dual-hosted git repository. btellier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
The following commit(s) were added to refs/heads/master by this push: new 0f484fb222 JAMES-4079 Fix RecipientRewriteTable adds duplicate mapping (#2449) 0f484fb222 is described below commit 0f484fb22249750cc2f9ea04ca2c248435a66fbe Author: amichair <amich...@amichais.net> AuthorDate: Mon Oct 14 10:03:53 2024 +0300 JAMES-4079 Fix RecipientRewriteTable adds duplicate mapping (#2449) --- .../cassandra/CassandraRecipientRewriteTable.java | 8 -- .../james/rrt/file/XMLRecipientRewriteTable.java | 9 -- .../rrt/file/XMLRecipientRewriteTableTest.java | 5 ++ .../james/rrt/jpa/JPARecipientRewriteTable.java | 13 --- .../rrt/lib/AbstractRecipientRewriteTable.java | 8 +- .../rrt/lib/RecipientRewriteTableContract.java | 14 +++ .../rrt/memory/MemoryRecipientRewriteTable.java | 99 ++++------------------ 7 files changed, 44 insertions(+), 112 deletions(-) diff --git a/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java b/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java index 6eda5a3213..390da1f6ca 100644 --- a/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java +++ b/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java @@ -24,7 +24,6 @@ import java.util.stream.Stream; import jakarta.inject.Inject; import org.apache.commons.lang3.tuple.Pair; -import org.apache.james.core.Domain; import org.apache.james.rrt.api.RecipientRewriteTableException; import org.apache.james.rrt.lib.AbstractRecipientRewriteTable; import org.apache.james.rrt.lib.Mapping; @@ -79,13 +78,6 @@ public class CassandraRecipientRewriteTable extends AbstractRecipientRewriteTabl .block(); } - @Override - protected Mappings mapAddress(String user, Domain domain) { - return cassandraRecipientRewriteTableDAO.retrieveMappings(MappingSource.fromUser(user, domain)).blockOptional() - .or(() -> cassandraRecipientRewriteTableDAO.retrieveMappings(MappingSource.fromDomain(domain)).blockOptional()) - .orElse(MappingsImpl.empty()); - } - @Override public Stream<MappingSource> listSources(Mapping mapping) throws RecipientRewriteTableException { Preconditions.checkArgument(listSourcesSupportedType.contains(mapping.getType()), diff --git a/server/data/data-file/src/main/java/org/apache/james/rrt/file/XMLRecipientRewriteTable.java b/server/data/data-file/src/main/java/org/apache/james/rrt/file/XMLRecipientRewriteTable.java index fe815e72fd..f8c986120c 100644 --- a/server/data/data-file/src/main/java/org/apache/james/rrt/file/XMLRecipientRewriteTable.java +++ b/server/data/data-file/src/main/java/org/apache/james/rrt/file/XMLRecipientRewriteTable.java @@ -25,7 +25,6 @@ import java.util.Optional; import org.apache.commons.configuration2.HierarchicalConfiguration; import org.apache.commons.configuration2.ex.ConfigurationException; import org.apache.commons.configuration2.tree.ImmutableNode; -import org.apache.james.core.Domain; import org.apache.james.rrt.api.RecipientRewriteTableException; import org.apache.james.rrt.lib.AbstractRecipientRewriteTable; import org.apache.james.rrt.lib.Mapping; @@ -60,14 +59,6 @@ public class XMLRecipientRewriteTable extends AbstractRecipientRewriteTable { } } - @Override - protected Mappings mapAddress(String user, Domain domain) { - return Optional.ofNullable(mappings) - .map(mappings -> RecipientRewriteTableUtil.getTargetString(user, domain, mappings)) - .map(MappingsImpl::fromRawString) - .orElse(MappingsImpl.empty()); - } - @Override public Mappings getStoredMappings(MappingSource source) { return Optional.ofNullable(mappings) diff --git a/server/data/data-file/src/test/java/org/apache/james/rrt/file/XMLRecipientRewriteTableTest.java b/server/data/data-file/src/test/java/org/apache/james/rrt/file/XMLRecipientRewriteTableTest.java index 01c6aee368..461441225d 100644 --- a/server/data/data-file/src/test/java/org/apache/james/rrt/file/XMLRecipientRewriteTableTest.java +++ b/server/data/data-file/src/test/java/org/apache/james/rrt/file/XMLRecipientRewriteTableTest.java @@ -78,6 +78,11 @@ class XMLRecipientRewriteTableTest implements RecipientRewriteTableContract { public void testStoreAndGetMappings() { } + @Test + @Disabled("XMLRecipientRewriteTable is read only") + public void testStoreDuplicateMapping() { + } + @Test @Disabled("XMLRecipientRewriteTable is read only") public void testStoreAndRetrieveRegexMapping() { diff --git a/server/data/data-jpa/src/main/java/org/apache/james/rrt/jpa/JPARecipientRewriteTable.java b/server/data/data-jpa/src/main/java/org/apache/james/rrt/jpa/JPARecipientRewriteTable.java index 9ba6b3500d..2e3a28c6b1 100644 --- a/server/data/data-jpa/src/main/java/org/apache/james/rrt/jpa/JPARecipientRewriteTable.java +++ b/server/data/data-jpa/src/main/java/org/apache/james/rrt/jpa/JPARecipientRewriteTable.java @@ -113,19 +113,6 @@ public class JPARecipientRewriteTable extends AbstractRecipientRewriteTable { } } - @Override - protected Mappings mapAddress(String user, Domain domain) throws RecipientRewriteTableException { - Mappings userDomainMapping = getStoredMappings(MappingSource.fromUser(user, domain)); - if (userDomainMapping != null && !userDomainMapping.isEmpty()) { - return userDomainMapping; - } - Mappings domainMapping = getStoredMappings(MappingSource.fromDomain(domain)); - if (domainMapping != null && !domainMapping.isEmpty()) { - return domainMapping; - } - return MappingsImpl.empty(); - } - @Override @SuppressWarnings("unchecked") public Mappings getStoredMappings(MappingSource source) throws RecipientRewriteTableException { diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java index 020f4379d4..feb85ca65c 100644 --- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java +++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java @@ -406,7 +406,13 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT * It must never return null but throw RecipientRewriteTableException on errors and return an empty Mappings * object if no mapping is found. */ - protected abstract Mappings mapAddress(String user, Domain domain) throws RecipientRewriteTableException; + protected Mappings mapAddress(String user, Domain domain) throws RecipientRewriteTableException { + Mappings mappings = getStoredMappings(MappingSource.fromUser(user, domain)); + if (mappings.isEmpty()) { + mappings = getStoredMappings(MappingSource.fromDomain(domain)); + } + return mappings; + } private void checkDomainMappingSourceIsManaged(MappingSource source) throws RecipientRewriteTableException { Optional<Domain> notManagedSourceDomain = source.availableDomain() diff --git a/server/data/data-library/src/test/java/org/apache/james/rrt/lib/RecipientRewriteTableContract.java b/server/data/data-library/src/test/java/org/apache/james/rrt/lib/RecipientRewriteTableContract.java index 1acc5cab38..edff932426 100644 --- a/server/data/data-library/src/test/java/org/apache/james/rrt/lib/RecipientRewriteTableContract.java +++ b/server/data/data-library/src/test/java/org/apache/james/rrt/lib/RecipientRewriteTableContract.java @@ -104,6 +104,20 @@ public interface RecipientRewriteTableContract { assertThat(virtualUserTable().getResolvedMappings("prefix_abc", domain)).isNotEmpty(); } + @Test + default void testStoreDuplicateMapping() throws Exception { + Domain domain = Domain.of("james"); + MappingSource source = MappingSource.fromUser(USER, domain); + + Mapping mapping = Mapping.group(ADDRESS); + Mapping mapping2 = Mapping.group(ADDRESS); + + virtualUserTable().addMapping(source, mapping); + virtualUserTable().addMapping(source, mapping2); + + assertThat(virtualUserTable().mapAddress(USER, domain).size()).isEqualTo(1); + } + @Test default void testQuotedLocalPart() { assertThatCode(() -> virtualUserTable().getResolvedMappings("\"a@b\"", Domain.of("test"))).doesNotThrowAnyException(); diff --git a/server/data/data-memory/src/main/java/org/apache/james/rrt/memory/MemoryRecipientRewriteTable.java b/server/data/data-memory/src/main/java/org/apache/james/rrt/memory/MemoryRecipientRewriteTable.java index 68996362e0..b5a57fbdfd 100644 --- a/server/data/data-memory/src/main/java/org/apache/james/rrt/memory/MemoryRecipientRewriteTable.java +++ b/server/data/data-memory/src/main/java/org/apache/james/rrt/memory/MemoryRecipientRewriteTable.java @@ -19,113 +19,50 @@ package org.apache.james.rrt.memory; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; +import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.Map; -import java.util.Optional; -import java.util.stream.Stream; +import java.util.Set; +import java.util.stream.Collectors; -import org.apache.commons.lang3.tuple.Pair; -import org.apache.james.core.Domain; -import org.apache.james.core.Username; import org.apache.james.rrt.lib.AbstractRecipientRewriteTable; import org.apache.james.rrt.lib.Mapping; import org.apache.james.rrt.lib.MappingSource; import org.apache.james.rrt.lib.Mappings; import org.apache.james.rrt.lib.MappingsImpl; -import com.google.common.base.Objects; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Multimaps; - public class MemoryRecipientRewriteTable extends AbstractRecipientRewriteTable { - private static class InMemoryMappingEntry { - private final MappingSource source; - private final Mapping mapping; - - public InMemoryMappingEntry(MappingSource source, Mapping mapping) { - this.source = source; - this.mapping = mapping; - } - - public MappingSource getSource() { - return source; - } - - public Mapping getMapping() { - return mapping; - } - - @Override - public boolean equals(Object o) { - if (o == null || this.getClass() != o.getClass()) { - return false; - } - - InMemoryMappingEntry that = (InMemoryMappingEntry) o; - - return Objects.equal(this.source, that.source) - && Objects.equal(this.mapping, that.mapping); - } - - @Override - public int hashCode() { - return Objects.hashCode(source, mapping); - } - } + private final Map<MappingSource, Set<Mapping>> table = new HashMap<>(); - private final List<InMemoryMappingEntry> mappingEntries; - - public MemoryRecipientRewriteTable() { - mappingEntries = new ArrayList<>(); + private Mappings toMappings(Set<Mapping> mappings) { + return mappings == null ? MappingsImpl.empty() : MappingsImpl.fromMappings(mappings.stream()); } @Override public void addMapping(MappingSource source, Mapping mapping) { - mappingEntries.add(new InMemoryMappingEntry(source, mapping)); + table.computeIfAbsent(source, s -> new LinkedHashSet<>()).add(mapping); } @Override public void removeMapping(MappingSource source, Mapping mapping) { - mappingEntries.remove(new InMemoryMappingEntry(source, mapping)); + Set<Mapping> mappings = table.get(source); + if (mappings != null) { + mappings.remove(mapping); + if (mappings.isEmpty()) { + table.remove(source); + } + } } @Override public Mappings getStoredMappings(MappingSource mappingSource) { - return retrieveMappings(mappingSource) - .orElse(MappingsImpl.empty()); - } - - @Override - protected Mappings mapAddress(String user, Domain domain) { - return retrieveMappings(MappingSource.fromUser(Username.fromLocalPartWithDomain(user, domain))) - .or(() -> retrieveMappings(MappingSource.fromDomain(domain))) - .orElse(MappingsImpl.empty()); + return toMappings(table.get(mappingSource)); } @Override public Map<MappingSource, Mappings> getAllMappings() { - return Multimaps.index(mappingEntries, InMemoryMappingEntry::getSource) - .asMap() - .entrySet() - .stream() - .map(entry -> Pair.of(entry.getKey(), toMappings(entry.getValue()))) - .collect(ImmutableMap.toImmutableMap(Pair::getKey, Pair::getValue)); - } - - private MappingsImpl toMappings(Collection<InMemoryMappingEntry> inMemoryMappingEntries) { - return MappingsImpl.fromMappings(inMemoryMappingEntries - .stream() - .map(InMemoryMappingEntry::getMapping)); + return table.entrySet().stream() + .collect(Collectors.toMap(e -> e.getKey(), e -> toMappings(e.getValue()))); } - - private Optional<Mappings> retrieveMappings(MappingSource mappingSource) { - Stream<Mapping> userEntries = mappingEntries.stream() - .filter(mappingEntry -> mappingEntry.source.equals(mappingSource)) - .map(InMemoryMappingEntry::getMapping); - return MappingsImpl.fromMappings(userEntries).toOptional(); - } - } --------------------------------------------------------------------- To unsubscribe, e-mail: notifications-unsubscr...@james.apache.org For additional commands, e-mail: notifications-h...@james.apache.org