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 bd32e30640 JAMES-3829 Drop FST (#1545) bd32e30640 is described below commit bd32e30640c3db4ba74e39ba46145f95f18aa46b Author: Benoit TELLIER <btell...@linagora.com> AuthorDate: Wed May 3 10:21:38 2023 +0700 JAMES-3829 Drop FST (#1545) --- mailet/api/pom.xml | 16 --- .../java/org/apache/mailet/AttributeValue.java | 25 ++--- .../main/java/org/apache/mailet/Serializer.java | 123 ++++++++++----------- .../java/org/apache/mailet/AttributeValueTest.java | 68 ++++-------- .../transport/mailets/SMIMECheckSignature.java | 95 ++++++++-------- .../james/transport/mailets/SMIMEDecrypt.java | 6 +- .../james/transport/mailets/ICalendarParser.java | 2 +- .../james/transport/mailets/ICALToHeadersTest.java | 8 +- .../transport/mailets/ICALToJsonAttributeTest.java | 32 +++--- .../transport/mailets/ICalendarParserTest.java | 16 ++- .../james/transport/matchers/HasExceptionTest.java | 33 +++--- .../org/apache/james/server/core/MailImpl.java | 6 +- .../mailrepository/jpa/JPAMailRepository.java | 8 +- .../james/mailetcontainer/impl/ProcessorUtil.java | 2 +- .../transport/mailets/jsieve/ActionUtils.java | 16 +-- .../james/mailrepository/blob/MailMetadata.scala | 2 +- .../CassandraMailRepositoryMailDaoV2.java | 7 +- .../apache/james/queue/api/MailQueueContract.java | 18 --- .../james/queue/jms/JMSCacheableMailQueue.java | 6 +- .../apache/james/queue/pulsar/MailMetadata.scala | 2 +- .../james/queue/rabbitmq/MailReferenceDTO.java | 10 +- .../view/cassandra/EnqueuedMailsDaoUtil.java | 10 +- 22 files changed, 224 insertions(+), 287 deletions(-) diff --git a/mailet/api/pom.xml b/mailet/api/pom.xml index 72b41ca35b..b50b0c0919 100644 --- a/mailet/api/pom.xml +++ b/mailet/api/pom.xml @@ -71,22 +71,6 @@ <groupId>com.sun.mail</groupId> <artifactId>javax.mail</artifactId> </dependency> - <dependency> - <groupId>de.ruedigermoeller</groupId> - <artifactId>fst</artifactId> - <version>2.57</version> - <exclusions> - <exclusion> - <groupId>org.objenesis</groupId> - <artifactId>objenesis</artifactId> - </exclusion> - </exclusions> - </dependency> - <dependency> - <groupId>org.objenesis</groupId> - <artifactId>objenesis</artifactId> - <version>3.2</version> - </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> diff --git a/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java b/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java index 5df7218497..b0290e68f4 100644 --- a/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java +++ b/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java @@ -20,7 +20,6 @@ package org.apache.mailet; import java.io.IOException; -import java.io.Serializable; import java.net.URL; import java.time.ZonedDateTime; import java.util.Collection; @@ -128,9 +127,9 @@ public class AttributeValue<T> { return new AttributeValue<>(value, new Serializer.MapSerializer()); } - public static AttributeValue<Serializable> ofSerializable(Serializable value) { - Preconditions.checkNotNull(value, "value should not be null"); - return new AttributeValue<>(value, new Serializer.FSTSerializer()); + public static AttributeValue<Object> ofUnserializable(Object any) { + Preconditions.checkNotNull(any, "value should not be null"); + return new AttributeValue<>(any, new Serializer.NoSerializer()); } @SuppressWarnings({ "unchecked", "rawtypes" }) @@ -178,10 +177,7 @@ public class AttributeValue<T> { if (value instanceof Optional) { return of((Optional) value); } - if (value instanceof Serializable) { - return ofSerializable((Serializable) value); - } - throw new IllegalArgumentException(value.getClass().toString() + " should at least be Serializable"); + throw new IllegalArgumentException(value.getClass().toString() + " is not a managed attibute"); } public static AttributeValue<?> fromJsonString(String json) throws IOException { @@ -253,11 +249,14 @@ public class AttributeValue<T> { return new AttributeValue<>(serializer.duplicate(value), serializer); } - public JsonNode toJson() { - ObjectNode serialized = JsonNodeFactory.instance.objectNode(); - serialized.put("serializer", serializer.getName()); - serialized.replace("value", serializer.serialize(value)); - return serialized; + public Optional<JsonNode> toJson() { + return serializer.serialize(value) + .map(value -> { + ObjectNode serialized = JsonNodeFactory.instance.objectNode(); + serialized.put("serializer", serializer.getName()); + serialized.replace("value", value); + return serialized; + }); } public T getValue() { diff --git a/mailet/api/src/main/java/org/apache/mailet/Serializer.java b/mailet/api/src/main/java/org/apache/mailet/Serializer.java index f9fc2f07d6..cd1397460f 100644 --- a/mailet/api/src/main/java/org/apache/mailet/Serializer.java +++ b/mailet/api/src/main/java/org/apache/mailet/Serializer.java @@ -21,9 +21,7 @@ package org.apache.mailet; import static java.time.format.DateTimeFormatter.ISO_DATE_TIME; -import java.io.IOException; import java.io.Serializable; -import java.io.UncheckedIOException; import java.net.MalformedURLException; import java.net.URL; import java.time.ZonedDateTime; @@ -31,22 +29,19 @@ import java.util.Base64; import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Objects; import java.util.Optional; import java.util.function.Function; import java.util.stream.Stream; +import org.apache.commons.lang3.NotImplementedException; import org.apache.commons.lang3.tuple.Pair; import org.apache.james.mailbox.model.MessageIdDto; import org.apache.james.util.streams.Iterators; -import org.nustaq.serialization.FSTConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.BooleanNode; import com.fasterxml.jackson.databind.node.DoubleNode; @@ -67,7 +62,7 @@ import com.google.common.collect.ImmutableMap; */ @SuppressWarnings("EqualsHashCode") public interface Serializer<T> { - JsonNode serialize(T object); + Optional<JsonNode> serialize(T object); Optional<T> deserialize(JsonNode json); @@ -95,6 +90,7 @@ public interface Serializer<T> { URL_SERIALIZER, new CollectionSerializer<>(), new MapSerializer<>(), + // To be dropped in 3.9.0 new FSTSerializer(), new OptionalSerializer<>()) .collect(ImmutableMap.toImmutableMap(Serializer::getName, Function.identity())); @@ -107,8 +103,8 @@ public interface Serializer<T> { class BooleanSerializer implements Serializer<Boolean> { @Override - public JsonNode serialize(Boolean object) { - return BooleanNode.valueOf(object); + public Optional<JsonNode> serialize(Boolean object) { + return Optional.of(BooleanNode.valueOf(object)); } @Override @@ -145,8 +141,8 @@ public interface Serializer<T> { class StringSerializer implements Serializer<String> { @Override - public JsonNode serialize(String object) { - return TextNode.valueOf(object); + public Optional<JsonNode> serialize(String object) { + return Optional.of(TextNode.valueOf(object)); } @Override @@ -183,8 +179,8 @@ public interface Serializer<T> { class IntSerializer implements Serializer<Integer> { @Override - public JsonNode serialize(Integer object) { - return IntNode.valueOf(object); + public Optional<JsonNode> serialize(Integer object) { + return Optional.of(IntNode.valueOf(object)); } @Override @@ -221,8 +217,8 @@ public interface Serializer<T> { class LongSerializer implements Serializer<Long> { @Override - public JsonNode serialize(Long object) { - return LongNode.valueOf(object); + public Optional<JsonNode> serialize(Long object) { + return Optional.of(LongNode.valueOf(object)); } @Override @@ -261,8 +257,8 @@ public interface Serializer<T> { class FloatSerializer implements Serializer<Float> { @Override - public JsonNode serialize(Float object) { - return FloatNode.valueOf(object); + public Optional<JsonNode> serialize(Float object) { + return Optional.of(FloatNode.valueOf(object)); } @Override @@ -301,8 +297,8 @@ public interface Serializer<T> { class DoubleSerializer implements Serializer<Double> { @Override - public JsonNode serialize(Double object) { - return DoubleNode.valueOf(object); + public Optional<JsonNode> serialize(Double object) { + return Optional.of(DoubleNode.valueOf(object)); } @Override @@ -339,9 +335,9 @@ public interface Serializer<T> { class DateSerializer implements Serializer<ZonedDateTime> { @Override - public JsonNode serialize(ZonedDateTime object) { + public Optional<JsonNode> serialize(ZonedDateTime object) { String serialized = object.format(ISO_DATE_TIME); - return TextNode.valueOf(serialized); + return Optional.of(TextNode.valueOf(serialized)); } @Override @@ -380,7 +376,7 @@ public interface Serializer<T> { class MessageIdDtoSerializer implements Serializer<MessageIdDto> { @Override - public JsonNode serialize(MessageIdDto serializable) { + public Optional<JsonNode> serialize(MessageIdDto serializable) { return STRING_SERIALIZER .serialize(serializable.asString()); } @@ -419,12 +415,12 @@ public interface Serializer<T> { private static final Logger LOGGER = LoggerFactory.getLogger(ArbitrarySerializableSerializer.class); @Override - public JsonNode serialize(T serializable) { + public Optional<JsonNode> serialize(T serializable) { ArbitrarySerializable.Serializable<T> serialized = serializable.serialize(); ObjectNode serializedJson = JsonNodeFactory.instance.objectNode(); serializedJson.put("deserializer", serialized.getDeserializer().getName()); - serializedJson.replace("value", serialized.getValue().toJson()); - return serializedJson; + serializedJson.replace("value", serialized.getValue().toJson().get()); + return Optional.of(serializedJson); } @Override @@ -474,13 +470,13 @@ public interface Serializer<T> { @Override public T duplicate(T value) { - return deserialize(serialize(value)).get(); + return deserialize(serialize(value).get()).get(); } } class UrlSerializer implements Serializer<URL> { @Override - public JsonNode serialize(URL object) { + public Optional<JsonNode> serialize(URL object) { return STRING_SERIALIZER.serialize(object.toString()); } @@ -520,11 +516,12 @@ public interface Serializer<T> { class CollectionSerializer<U> implements Serializer<Collection<AttributeValue<U>>> { @Override - public JsonNode serialize(Collection<AttributeValue<U>> object) { + public Optional<JsonNode> serialize(Collection<AttributeValue<U>> object) { List<JsonNode> jsons = object.stream() .map(AttributeValue::toJson) + .flatMap(Optional::stream) .collect(ImmutableList.toImmutableList()); - return new ArrayNode(JsonNodeFactory.instance, jsons); + return Optional.of(new ArrayNode(JsonNodeFactory.instance, jsons)); } @SuppressWarnings("unchecked") @@ -564,10 +561,11 @@ public interface Serializer<T> { class MapSerializer<U> implements Serializer<Map<String, AttributeValue<U>>> { @Override - public JsonNode serialize(Map<String, AttributeValue<U>> object) { + public Optional<JsonNode> serialize(Map<String, AttributeValue<U>> object) { Map<String, JsonNode> jsonMap = object.entrySet().stream() - .collect(ImmutableMap.toImmutableMap(Entry::getKey, entry -> entry.getValue().toJson())); - return new ObjectNode(JsonNodeFactory.instance, jsonMap); + .flatMap(entry -> entry.getValue().toJson().map(value -> Pair.of(entry.getKey(), value)).stream()) + .collect(ImmutableMap.toImmutableMap(Pair::getKey, Pair::getValue)); + return Optional.of(new ObjectNode(JsonNodeFactory.instance, jsonMap)); } @SuppressWarnings("unchecked") @@ -610,9 +608,9 @@ public interface Serializer<T> { class OptionalSerializer<U> implements Serializer<Optional<AttributeValue<U>>> { @Override - public JsonNode serialize(Optional<AttributeValue<U>> object) { + public Optional<JsonNode> serialize(Optional<AttributeValue<U>> object) { return object.map(AttributeValue::toJson) - .orElse(NullNode.getInstance()); + .orElse(Optional.of(NullNode.getInstance())); } @SuppressWarnings("unchecked") @@ -650,45 +648,24 @@ public interface Serializer<T> { } class FSTSerializer implements Serializer<Serializable> { - static final FSTConfiguration CONFIGURATION = FSTConfiguration.createJsonConfiguration(); - @Override - public JsonNode serialize(Serializable object) { - String json = CONFIGURATION.asJsonString(object); - try { - return new ObjectMapper().reader().readTree(json); - } catch (IOException e) { - throw new UncheckedIOException(e); - } + public Optional<JsonNode> serialize(Serializable object) { + return Optional.empty(); } @Override public Optional<Serializable> deserialize(JsonNode json) { - try { - return Optional.of((Serializable) CONFIGURATION.asObject(new ObjectMapper().writer().writeValueAsBytes(json))); - } catch (JsonProcessingException e) { - throw new UncheckedIOException(e); - } - } - - @Override - public Serializable duplicate(Serializable value) { - return deserialize(serialize(value)).get(); + return Optional.empty(); } @Override public String getName() { - return "FSTSerializer"; + return "NoSerializer"; } @Override - public boolean equals(Object other) { - return this.getClass() == other.getClass(); - } - - @Override - public int hashCode() { - return Objects.hash(getClass()); + public Serializable duplicate(Serializable value) { + throw new NotImplementedException(); } } @@ -697,7 +674,7 @@ public interface Serializer<T> { class BytesSerializer implements Serializer<byte[]> { @Override - public JsonNode serialize(byte[] object) { + public Optional<JsonNode> serialize(byte[] object) { return STRING_SERIALIZER.serialize(Base64.getEncoder().encodeToString(object)); } @@ -728,4 +705,26 @@ public interface Serializer<T> { } } + class NoSerializer implements Serializer<Object> { + @Override + public Optional<JsonNode> serialize(Object object) { + return Optional.empty(); + } + + @Override + public Optional<Object> deserialize(JsonNode json) { + return Optional.empty(); + } + + @Override + public String getName() { + return "NoSerializer"; + } + + @Override + public Object duplicate(Object value) { + return value; + } + } + } diff --git a/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java b/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java index be41e3765e..384b5a5d21 100644 --- a/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java +++ b/mailet/api/src/test/java/org/apache/mailet/AttributeValueTest.java @@ -61,7 +61,7 @@ class AttributeValueTest { void stringShouldBeSerializedAndBack() { AttributeValue<String> expected = AttributeValue.of("value"); - JsonNode json = expected.toJson(); + JsonNode json = expected.toJson().get(); AttributeValue<?> actual = AttributeValue.fromJson(json); assertThat(actual).isEqualTo(expected); @@ -71,7 +71,7 @@ class AttributeValueTest { void emptyStringShouldBeSerializedAndBack() { AttributeValue<String> expected = AttributeValue.of(""); - JsonNode json = expected.toJson(); + JsonNode json = expected.toJson().get(); AttributeValue<?> actual = AttributeValue.fromJson(json); assertThat(actual).isEqualTo(expected); @@ -105,7 +105,7 @@ class AttributeValueTest { void trueShouldBeSerializedAndBack() { AttributeValue<Boolean> expected = AttributeValue.of(true); - JsonNode json = expected.toJson(); + JsonNode json = expected.toJson().get(); AttributeValue<?> actual = AttributeValue.fromJson(json); assertThat(actual).isEqualTo(expected); @@ -115,7 +115,7 @@ class AttributeValueTest { void falseShouldBeSerializedAndBack() { AttributeValue<Boolean> expected = AttributeValue.of(true); - JsonNode json = expected.toJson(); + JsonNode json = expected.toJson().get(); AttributeValue<?> actual = AttributeValue.fromJson(json); assertThat(actual).isEqualTo(expected); @@ -149,7 +149,7 @@ class AttributeValueTest { void intShouldBeSerializedAndBack() { AttributeValue<Integer> expected = AttributeValue.of(42); - JsonNode json = expected.toJson(); + JsonNode json = expected.toJson().get(); AttributeValue<?> actual = AttributeValue.fromJson(json); assertThat(actual).isEqualTo(expected); @@ -196,7 +196,7 @@ class AttributeValueTest { void longShouldBeSerializedAndBack() { AttributeValue<Long> expected = AttributeValue.of(42L); - JsonNode json = expected.toJson(); + JsonNode json = expected.toJson().get(); AttributeValue<?> actual = AttributeValue.fromJson(json); assertThat(actual).isEqualTo(expected); @@ -206,7 +206,7 @@ class AttributeValueTest { void longShouldBeSerializedAndBackForLongMaxValue() { AttributeValue<Long> expected = AttributeValue.of(Long.MAX_VALUE); - JsonNode json = expected.toJson(); + JsonNode json = expected.toJson().get(); AttributeValue<?> actual = AttributeValue.fromJson(json); assertThat(actual).isEqualTo(expected); @@ -246,7 +246,7 @@ class AttributeValueTest { void floatShouldBeSerializedAndBack() { AttributeValue<Float> expected = AttributeValue.of(1.0f); - JsonNode json = expected.toJson(); + JsonNode json = expected.toJson().get(); AttributeValue<?> actual = AttributeValue.fromJson(json); assertThat(actual).isEqualTo(expected); @@ -286,7 +286,7 @@ class AttributeValueTest { void doubleShouldBeSerializedAndBack() { AttributeValue<Double> expected = AttributeValue.of(1.0d); - JsonNode json = expected.toJson(); + JsonNode json = expected.toJson().get(); AttributeValue<?> actual = AttributeValue.fromJson(json); assertThat(actual).isEqualTo(expected); @@ -296,7 +296,7 @@ class AttributeValueTest { void doubleShouldBeSerializedAndBackForMaxValue() { AttributeValue<Double> expected = AttributeValue.of(Double.MAX_VALUE); - JsonNode json = expected.toJson(); + JsonNode json = expected.toJson().get(); AttributeValue<?> actual = AttributeValue.fromJson(json); assertThat(actual).isEqualTo(expected); @@ -336,7 +336,7 @@ class AttributeValueTest { void dateShouldBeSerializedAndBack() { AttributeValue<ZonedDateTime> expected = AttributeValue.of(ZonedDateTime.parse("2015-10-30T16:12:00Z")); - JsonNode json = expected.toJson(); + JsonNode json = expected.toJson().get(); AttributeValue<?> actual = AttributeValue.fromJson(json); assertThat(actual).isEqualTo(expected); @@ -376,7 +376,7 @@ class AttributeValueTest { void queueSerializableShouldBeSerializedAndBack() { AttributeValue<TestArbitrarySerializable> expected = AttributeValue.of(new TestArbitrarySerializable(42)); - JsonNode json = expected.toJson(); + JsonNode json = expected.toJson().get(); AttributeValue<?> actual = AttributeValue.fromJson(json); assertThat(actual).isEqualTo(expected); @@ -399,7 +399,7 @@ class AttributeValueTest { void urlShouldBeSerializedAndBack() throws MalformedURLException { AttributeValue<URL> expected = AttributeValue.of(new URL("https://james.apache.org/")); - JsonNode json = expected.toJson(); + JsonNode json = expected.toJson().get(); AttributeValue<?> actual = AttributeValue.fromJson(json); assertThat(actual).isEqualTo(expected); @@ -439,7 +439,7 @@ class AttributeValueTest { void messageIdShouldBeSerializedAndBack() { AttributeValue<MessageIdDto> expected = AttributeValue.of(new MessageIdDto(TestMessageId.of(42))); - JsonNode json = expected.toJson(); + JsonNode json = expected.toJson().get(); AttributeValue<?> actual = AttributeValue.fromJson(json); assertThat(actual).isEqualTo(expected); @@ -479,7 +479,7 @@ class AttributeValueTest { void emptyStringListShouldBeSerializedAndBack() { AttributeValue<?> expected = AttributeValue.ofAny(ImmutableList.<String>of()); - JsonNode json = expected.toJson(); + JsonNode json = expected.toJson().get(); AttributeValue<?> actual = AttributeValue.fromJson(json); assertThat(actual).isEqualTo(expected); @@ -489,7 +489,7 @@ class AttributeValueTest { void listShouldBeSerializedAndBack() { AttributeValue<?> expected = AttributeValue.of(ImmutableList.of(AttributeValue.of("first"), AttributeValue.of("second"))); - JsonNode json = expected.toJson(); + JsonNode json = expected.toJson().get(); AttributeValue<?> actual = AttributeValue.fromJson(json); assertThat(actual).isEqualTo(expected); @@ -540,7 +540,7 @@ class AttributeValueTest { @Test void emptyMapShouldBeSerializedAndBack() { AttributeValue<?> expected = AttributeValue.of(ImmutableMap.of()); - JsonNode json = expected.toJson(); + JsonNode json = expected.toJson().get(); AttributeValue<?> actual = AttributeValue.fromJson(json); assertThat(actual).isEqualTo(expected); @@ -549,7 +549,7 @@ class AttributeValueTest { @Test void mapWithPrimitiveTypesShouldBeSerializedAndBack() { AttributeValue<?> expected = AttributeValue.of(ImmutableMap.of("a", AttributeValue.of("value"), "b", AttributeValue.of(12))); - JsonNode json = expected.toJson(); + JsonNode json = expected.toJson().get(); AttributeValue<?> actual = AttributeValue.fromJson(json); assertThat(actual).isEqualTo(expected); @@ -603,7 +603,7 @@ class AttributeValueTest { @Test void emptyOptionalShouldBeSerializedAndBack() { AttributeValue<?> expected = AttributeValue.of(Optional.empty()); - JsonNode json = expected.toJson(); + JsonNode json = expected.toJson().get(); AttributeValue<?> actual = AttributeValue.fromJson(json); assertThat(actual).isEqualTo(expected); @@ -612,7 +612,7 @@ class AttributeValueTest { @Test void optionalShouldBeSerializedAndBack() { AttributeValue<?> expected = AttributeValue.of(Optional.of(AttributeValue.of(42))); - JsonNode json = expected.toJson(); + JsonNode json = expected.toJson().get(); AttributeValue<?> actual = AttributeValue.fromJson(json); assertThat(actual).isEqualTo(expected); @@ -652,34 +652,6 @@ class AttributeValueTest { } } - @Nested - class SerializableSerialization { - @Test - void filledSerializabletrueShouldBeSerializedAndBack() { - AttributeValue<java.io.Serializable> expected = AttributeValue.ofSerializable(new TestSerializable("me")); - - JsonNode json = expected.toJson(); - AttributeValue<?> actual = AttributeValue.fromJson(json); - - assertThat(actual).isEqualTo(expected); - } - - @Test - void nullSerializableShouldThrowAnException() { - assertThatNullPointerException() - .isThrownBy(() -> AttributeValue.ofSerializable((java.io.Serializable) null)); - } - - @Test - void fromJsonStringShouldReturnBooleanAttributeValueWhenBoolean() throws Exception { - AttributeValue<java.io.Serializable> expected = AttributeValue.ofSerializable(new TestSerializable("me")); - - AttributeValue<?> actual = AttributeValue.fromJsonString("{\"serializer\":\"FSTSerializer\",\"value\":{\"typ\":\"org.apache.mailet.AttributeValueTest$TestSerializable\",\"obj\":{\"name\":\"me\"}}}"); - - assertThat(actual).isEqualTo(expected); - } - } - @Test void fromJsonStringShouldThrowOnUnknownSerializer() { assertThatIllegalStateException() diff --git a/mailet/crypto/src/main/java/org/apache/james/transport/mailets/SMIMECheckSignature.java b/mailet/crypto/src/main/java/org/apache/james/transport/mailets/SMIMECheckSignature.java index 7197186ff5..d49f5a1c2d 100644 --- a/mailet/crypto/src/main/java/org/apache/james/transport/mailets/SMIMECheckSignature.java +++ b/mailet/crypto/src/main/java/org/apache/james/transport/mailets/SMIMECheckSignature.java @@ -22,6 +22,7 @@ package org.apache.james.transport.mailets; import java.io.IOException; +import java.security.cert.CertificateEncodingException; import java.util.ArrayList; import java.util.List; @@ -107,16 +108,9 @@ public class SMIMECheckSignature extends GenericMailet { private static final Logger LOGGER = LoggerFactory.getLogger(SMIMECheckSignature.class); private KeyStoreHolder trustedCertificateStore; - private boolean stripSignature = false; private boolean onlyTrusted = true; - private AttributeName mailAttribute = AttributeName.of("org.apache.james.SMIMECheckSignature"); - - public SMIMECheckSignature() { - super(); - - } @Override public void init() throws MessagingException { @@ -168,18 +162,8 @@ public class SMIMECheckSignature extends GenericMailet { List<SMIMESignerInfo> signers = null; try { - Object obj = message.getContent(); - SMIMESigned signed; - if (obj instanceof MimeMultipart) { - signed = new SMIMESigned((MimeMultipart) message.getContent()); - } else if (obj instanceof SMIMESigned) { - signed = (SMIMESigned) obj; - } else if (obj instanceof byte[]) { - signed = new SMIMESigned(message); - } else { - signed = null; - } - + SMIMESigned signed = asSMIMESigned(message); + if (signed != null) { signers = trustedCertificateStore.verifySignatures(signed); strippedMessage = signed.getContent(); @@ -187,10 +171,8 @@ public class SMIMECheckSignature extends GenericMailet { LOGGER.info("Content not identified as signed"); } - // These errors are logged but they don't cause the - // message to change its state. The message - // is considered as not signed and the process will - // go on. + // These errors are logged but they don't cause the message to change its state. The message + // is considered as not signed and the process will go on. } catch (CMSException | SMIMEException e) { LOGGER.error("Error during the analysis of the signed message", e); signers = null; @@ -205,16 +187,9 @@ public class SMIMECheckSignature extends GenericMailet { // If at least one mail signer is found // the mail attributes are set. if (signers != null) { - ArrayList<AttributeValue<?>> signerinfolist = new ArrayList<>(); + ArrayList<AttributeValue<?>> signerinfolist = signerInfoList(signers); - for (SMIMESignerInfo info : signers) { - if (info.isSignValid() - && (!onlyTrusted || info.getCertPath() != null)) { - signerinfolist.add(AttributeValue.ofSerializable(info.getSignerCertificate())); - } - } - - if (signerinfolist.size() > 0) { + if (!signerinfolist.isEmpty()) { mail.setAttribute(new Attribute(mailAttribute, AttributeValue.of(signerinfolist))); } else { // if no valid signers are found the message is not modified. @@ -223,21 +198,53 @@ public class SMIMECheckSignature extends GenericMailet { } if (stripSignature && strippedMessage != null) { - try { - Object obj = strippedMessage.getContent(); - if (obj instanceof Multipart) { - message.setContent((Multipart) obj); - } else { - message.setContent(obj, strippedMessage.getContentType()); + stripSignature(mail, message, strippedMessage); + } + } + + private ArrayList<AttributeValue<?>> signerInfoList(List<SMIMESignerInfo> signers) { + ArrayList<AttributeValue<?>> signerinfolist = new ArrayList<>(); + + for (SMIMESignerInfo info : signers) { + if (info.isSignValid() + && (!onlyTrusted || info.getCertPath() != null)) { + try { + signerinfolist.add(AttributeValue.of(info.getSignerCertificate().getEncoded())); + } catch (CertificateEncodingException e) { + LOGGER.warn("Failed to encode certificate", e); } - message.saveChanges(); - mail.setMessage(message); - } catch (Exception e) { - throw new MessagingException( - "Error during the extraction of the signed content from the message.", - e); } } + return signerinfolist; } + private void stripSignature(Mail mail, MimeMessage message, MimeBodyPart strippedMessage) throws MessagingException { + try { + Object obj = strippedMessage.getContent(); + if (obj instanceof Multipart) { + message.setContent((Multipart) obj); + } else { + message.setContent(obj, strippedMessage.getContentType()); + } + message.saveChanges(); + mail.setMessage(message); + } catch (Exception e) { + throw new MessagingException("Error during the extraction of the signed content from the message.", e); + } + } + + private SMIMESigned asSMIMESigned(MimeMessage message) throws IOException, MessagingException, CMSException, SMIMEException { + Object obj = message.getContent(); + SMIMESigned signed; + if (obj instanceof MimeMultipart) { + signed = new SMIMESigned((MimeMultipart) message.getContent()); + } else if (obj instanceof SMIMESigned) { + signed = (SMIMESigned) obj; + } else if (obj instanceof byte[]) { + signed = new SMIMESigned(message); + } else { + signed = null; + } + return signed; + } } diff --git a/mailet/crypto/src/main/java/org/apache/james/transport/mailets/SMIMEDecrypt.java b/mailet/crypto/src/main/java/org/apache/james/transport/mailets/SMIMEDecrypt.java index b95efdb060..e4dd423636 100644 --- a/mailet/crypto/src/main/java/org/apache/james/transport/mailets/SMIMEDecrypt.java +++ b/mailet/crypto/src/main/java/org/apache/james/transport/mailets/SMIMEDecrypt.java @@ -163,7 +163,11 @@ public class SMIMEDecrypt extends GenericMailet { // it is possible to reuse the same matchers to analyze // the result of the operation. ArrayList<AttributeValue<?>> list = new ArrayList<>(1); - list.add(AttributeValue.ofSerializable(keyHolder.getCertificate())); + try { + list.add(AttributeValue.of(keyHolder.getCertificate().getEncoded())); + } catch (CertificateEncodingException e) { + LOGGER.warn("Failed to encode certificate", e); + } mail.setAttribute(new Attribute(mailAttribute, AttributeValue.of(list))); // I start the message stripping. diff --git a/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICalendarParser.java b/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICalendarParser.java index 2bc812c110..aaf373494c 100644 --- a/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICalendarParser.java +++ b/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICalendarParser.java @@ -123,7 +123,7 @@ public class ICalendarParser extends GenericMailet { Map<String, AttributeValue<?>> calendars = icsAttachments.entrySet() .stream() .flatMap(entry -> createCalendar(entry.getKey(), entry.getValue().getValue())) - .collect(ImmutableMap.toImmutableMap(Pair::getKey, pair -> AttributeValue.ofSerializable(pair.getValue()))); + .collect(ImmutableMap.toImmutableMap(Pair::getKey, pair -> AttributeValue.ofUnserializable(pair.getValue()))); mail.setAttribute(new Attribute(destinationAttributeName, AttributeValue.of(calendars))); } diff --git a/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICALToHeadersTest.java b/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICALToHeadersTest.java index 93d04de746..c1f96268ad 100644 --- a/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICALToHeadersTest.java +++ b/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICALToHeadersTest.java @@ -134,7 +134,7 @@ class ICALToHeadersTest { void serviceShouldWriteSingleICalendarToHeaders() throws Exception { Calendar calendar = new CalendarBuilder().build(ClassLoader.getSystemResourceAsStream("ics/meeting.ics")); Map<String, AttributeValue<?>> icals = ImmutableMap.<String, AttributeValue<?>>builder() - .put("key", AttributeValue.ofSerializable(calendar)) + .put("key", AttributeValue.ofUnserializable(calendar)) .build(); testee.init(FakeMailetConfig.builder().build()); @@ -161,7 +161,7 @@ class ICALToHeadersTest { void serviceShouldNotWriteHeaderWhenPropertyIsAbsent() throws Exception { Calendar calendar = new CalendarBuilder().build(ClassLoader.getSystemResourceAsStream("ics/meeting_without_dtstamp.ics")); Map<String, AttributeValue<?>> icals = ImmutableMap.<String, AttributeValue<?>>builder() - .put("key", AttributeValue.ofSerializable(calendar)) + .put("key", AttributeValue.ofUnserializable(calendar)) .build(); testee.init(FakeMailetConfig.builder().build()); @@ -188,8 +188,8 @@ class ICALToHeadersTest { Calendar calendar = new CalendarBuilder().build(ClassLoader.getSystemResourceAsStream("ics/meeting.ics")); Calendar calendar2 = new CalendarBuilder().build(ClassLoader.getSystemResourceAsStream("ics/meeting_2.ics")); Map<String, AttributeValue<?>> icals = ImmutableMap.<String, AttributeValue<?>>builder() - .put("key", AttributeValue.ofSerializable(calendar)) - .put("key2", AttributeValue.ofSerializable(calendar2)) + .put("key", AttributeValue.ofUnserializable(calendar)) + .put("key2", AttributeValue.ofUnserializable(calendar2)) .build(); testee.init(FakeMailetConfig.builder().build()); diff --git a/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICALToJsonAttributeTest.java b/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICALToJsonAttributeTest.java index a23dd83e01..f85a3de513 100644 --- a/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICALToJsonAttributeTest.java +++ b/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICALToJsonAttributeTest.java @@ -206,7 +206,7 @@ public class ICALToJsonAttributeTest { testee.init(FakeMailetConfig.builder().build()); AttributeValue<byte[]> ics = AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics")); - AttributeValue<Serializable> calendar = AttributeValue.ofSerializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); + AttributeValue<Object> calendar = AttributeValue.ofUnserializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); Map<String, AttributeValue<?>> icals = ImmutableMap.of("key", calendar); Map<String, AttributeValue<?>> rawIcals = ImmutableMap.of("key", ics); Mail mail = FakeMail.builder() @@ -226,7 +226,7 @@ public class ICALToJsonAttributeTest { testee.init(FakeMailetConfig.builder().build()); AttributeValue<byte[]> ics = AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/no_event.ics")); - AttributeValue<Serializable> calendar = AttributeValue.ofSerializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); + AttributeValue<Object> calendar = AttributeValue.ofUnserializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); Map<String, AttributeValue<?>> icals = ImmutableMap.of("key", calendar); Map<String, AttributeValue<?>> rawIcals = ImmutableMap.of("key", ics); Mail mail = FakeMail.builder() @@ -248,7 +248,7 @@ public class ICALToJsonAttributeTest { testee.init(FakeMailetConfig.builder().build()); AttributeValue<byte[]> ics = AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics")); - AttributeValue<Serializable> calendar = AttributeValue.ofSerializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); + AttributeValue<Object> calendar = AttributeValue.ofUnserializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); Map<String, AttributeValue<?>> icals = ImmutableMap.of("key", calendar); Map<String, AttributeValue<?>> rawIcals = ImmutableMap.of("key", ics); Mail mail = FakeMail.builder() @@ -268,7 +268,7 @@ public class ICALToJsonAttributeTest { testee.init(FakeMailetConfig.builder().build()); AttributeValue<byte[]> ics = AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics")); - AttributeValue<Serializable> calendar = AttributeValue.ofSerializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); + AttributeValue<Object> calendar = AttributeValue.ofUnserializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); Map<String, AttributeValue<?>> icals = ImmutableMap.of("key", calendar); Map<String, AttributeValue<?>> rawIcals = ImmutableMap.of("key", ics); MailAddress recipient = MailAddressFixture.ANY_AT_JAMES2; @@ -310,7 +310,7 @@ public class ICALToJsonAttributeTest { testee.init(FakeMailetConfig.builder().build()); AttributeValue<byte[]> ics = AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics")); - AttributeValue<Serializable> calendar = AttributeValue.ofSerializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); + AttributeValue<Object> calendar = AttributeValue.ofUnserializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); Map<String, AttributeValue<?>> icals = ImmutableMap.of("key", calendar); Map<String, AttributeValue<?>> rawIcals = ImmutableMap.of("key", ics); MailAddress recipient = MailAddressFixture.ANY_AT_JAMES2; @@ -361,7 +361,7 @@ public class ICALToJsonAttributeTest { testee.init(FakeMailetConfig.builder().build()); AttributeValue<byte[]> ics = AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics")); - AttributeValue<Serializable> calendar = AttributeValue.ofSerializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); + AttributeValue<Object> calendar = AttributeValue.ofUnserializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); Map<String, AttributeValue<?>> icals = ImmutableMap.of("key", calendar); Map<String, AttributeValue<?>> rawIcals = ImmutableMap.of("key", ics); MailAddress recipient = MailAddressFixture.ANY_AT_JAMES2; @@ -399,7 +399,7 @@ public class ICALToJsonAttributeTest { void serviceShouldAttachJsonForSeveralRecipient() throws Exception { testee.init(FakeMailetConfig.builder().build()); AttributeValue<byte[]> ics = AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics")); - AttributeValue<Serializable> calendar = AttributeValue.ofSerializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); + AttributeValue<Object> calendar = AttributeValue.ofUnserializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); Map<String, AttributeValue<?>> icals = ImmutableMap.of("key", calendar); Map<String, AttributeValue<?>> rawIcals = ImmutableMap.of("key", ics); Mail mail = FakeMail.builder() @@ -437,8 +437,8 @@ public class ICALToJsonAttributeTest { AttributeValue<byte[]> ics = AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics")); AttributeValue<byte[]> ics2 = AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting_2.ics")); - AttributeValue<Serializable> calendar = AttributeValue.ofSerializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); - AttributeValue<Serializable> calendar2 = AttributeValue.ofSerializable(new CalendarBuilder().build(new ByteArrayInputStream(ics2.getValue()))); + AttributeValue<Object> calendar = AttributeValue.ofUnserializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); + AttributeValue<Object> calendar2 = AttributeValue.ofUnserializable(new CalendarBuilder().build(new ByteArrayInputStream(ics2.getValue()))); Map<String, AttributeValue<?>> icals = ImmutableMap.of("key", calendar, "key2", calendar2); Map<String, AttributeValue<?>> rawIcals = ImmutableMap.of("key", ics, "key2", ics2); MailAddress recipient = MailAddressFixture.OTHER_AT_JAMES; @@ -488,8 +488,8 @@ public class ICALToJsonAttributeTest { AttributeValue<byte[]> ics = AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics")); AttributeValue<byte[]> ics2 = AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting_without_uid.ics")); - AttributeValue<Serializable> calendar = AttributeValue.ofSerializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); - AttributeValue<Serializable> calendar2 = AttributeValue.ofSerializable(new CalendarBuilder().build(new ByteArrayInputStream(ics2.getValue()))); + AttributeValue<Object> calendar = AttributeValue.ofUnserializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); + AttributeValue<Object> calendar2 = AttributeValue.ofUnserializable(new CalendarBuilder().build(new ByteArrayInputStream(ics2.getValue()))); Map<String, AttributeValue<?>> icals = ImmutableMap.of("key", calendar, "key2", calendar2); Map<String, AttributeValue<?>> rawIcals = ImmutableMap.of("key", ics, "key2", ics2); MailAddress recipient = MailAddressFixture.OTHER_AT_JAMES; @@ -528,8 +528,8 @@ public class ICALToJsonAttributeTest { AttributeValue<byte[]> ics = AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics")); AttributeValue<byte[]> ics2 = AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting_2.ics")); - AttributeValue<Serializable> calendar = AttributeValue.ofSerializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); - AttributeValue<Serializable> calendar2 = AttributeValue.ofSerializable(new CalendarBuilder().build(new ByteArrayInputStream(ics2.getValue()))); + AttributeValue<Object> calendar = AttributeValue.ofUnserializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); + AttributeValue<Object> calendar2 = AttributeValue.ofUnserializable(new CalendarBuilder().build(new ByteArrayInputStream(ics2.getValue()))); Map<String, AttributeValue<?>> icals = ImmutableMap.of("key", calendar, "key2", calendar2); Map<String, AttributeValue<?>> rawIcals = ImmutableMap.of("key", ics); MailAddress recipient = MailAddressFixture.OTHER_AT_JAMES; @@ -567,7 +567,7 @@ public class ICALToJsonAttributeTest { testee.init(FakeMailetConfig.builder().build()); AttributeValue<byte[]> ics = AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics")); - AttributeValue<Serializable> calendar = AttributeValue.ofSerializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); + AttributeValue<Object> calendar = AttributeValue.ofUnserializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); Map<String, AttributeValue<?>> icals = ImmutableMap.of("key", calendar); Map<String, AttributeValue<?>> rawIcals = ImmutableMap.of("key", ics); MailAddress recipient = MailAddressFixture.ANY_AT_JAMES2; @@ -607,7 +607,7 @@ public class ICALToJsonAttributeTest { testee.init(FakeMailetConfig.builder().build()); AttributeValue<byte[]> ics = AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics")); - AttributeValue<Serializable> calendar = AttributeValue.ofSerializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); + AttributeValue<Object> calendar = AttributeValue.ofUnserializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); Map<String, AttributeValue<?>> icals = ImmutableMap.of("key", calendar); Map<String, AttributeValue<?>> rawIcals = ImmutableMap.of("key", ics); MailAddress recipient = MailAddressFixture.ANY_AT_JAMES2; @@ -645,7 +645,7 @@ public class ICALToJsonAttributeTest { testee.init(FakeMailetConfig.builder().build()); AttributeValue<byte[]> ics = AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics")); - AttributeValue<Serializable> calendar = AttributeValue.ofSerializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); + AttributeValue<Object> calendar = AttributeValue.ofUnserializable(new CalendarBuilder().build(new ByteArrayInputStream(ics.getValue()))); Map<String, AttributeValue<?>> icals = ImmutableMap.of("key", calendar); Map<String, AttributeValue<?>> rawIcals = ImmutableMap.of("key", ics); MailAddress recipient = MailAddressFixture.ANY_AT_JAMES2; diff --git a/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICalendarParserTest.java b/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICalendarParserTest.java index 11ced1038f..19407af5a3 100644 --- a/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICalendarParserTest.java +++ b/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICalendarParserTest.java @@ -89,7 +89,7 @@ class ICalendarParserTest { static final String WRONG_ICAL_VALUE = "anyValue"; @SuppressWarnings("unchecked") - static final Class<Map<String, AttributeValue<Serializable>>> MAP_STRING_CALENDAR_CLASS = (Class<Map<String, AttributeValue<Serializable>>>) (Object) Map.class; + static final Class<Map<String, AttributeValue<Object>>> MAP_STRING_CALENDAR_CLASS = (Class<Map<String, AttributeValue<Object>>>) (Object) Map.class; ICalendarParser mailet = new ICalendarParser(); @@ -262,13 +262,11 @@ class ICalendarParserTest { mailet.service(mail); - Optional<Map<String, AttributeValue<Serializable>>> expectedCalendars = AttributeUtils.getValueAndCastFromMail(mail, DESTINATION_CUSTOM_ATTRIBUTE_NAME, MAP_STRING_CALENDAR_CLASS); - Map.Entry<String, AttributeValue<Serializable>> expectedCalendar = Maps.immutableEntry("key2", AttributeValue.ofSerializable(new Calendar())); + Optional<Map<String, AttributeValue<Object>>> expectedCalendars = AttributeUtils.getValueAndCastFromMail(mail, DESTINATION_CUSTOM_ATTRIBUTE_NAME, MAP_STRING_CALENDAR_CLASS); assertThat(expectedCalendars).hasValueSatisfying(calendars -> assertThat(calendars) - .hasSize(1) - .containsExactly(expectedCalendar)); + .hasSize(1)); } @Test @@ -291,7 +289,7 @@ class ICalendarParserTest { mailet.service(mail); - Optional<Map<String, AttributeValue<Serializable>>> expectedCalendars = AttributeUtils.getValueAndCastFromMail(mail, DESTINATION_CUSTOM_ATTRIBUTE_NAME, MAP_STRING_CALENDAR_CLASS); + Optional<Map<String, AttributeValue<Object>>> expectedCalendars = AttributeUtils.getValueAndCastFromMail(mail, DESTINATION_CUSTOM_ATTRIBUTE_NAME, MAP_STRING_CALENDAR_CLASS); assertThat(expectedCalendars).hasValueSatisfying(calendars -> assertThat(calendars) @@ -300,7 +298,7 @@ class ICalendarParserTest { } @Test - void getMailetInfoShouldReturn() throws MessagingException { + void getMailetInfoShouldReturn() { assertThat(mailet.getMailetInfo()).isEqualTo("Calendar Parser"); } @@ -325,13 +323,13 @@ class ICalendarParserTest { mailet.service(mail); - Optional<Map<String, AttributeValue<Serializable>>> expectedCalendars = AttributeUtils.getValueAndCastFromMail(mail, DESTINATION_CUSTOM_ATTRIBUTE_NAME, MAP_STRING_CALENDAR_CLASS); + Optional<Map<String, AttributeValue<Object>>> expectedCalendars = AttributeUtils.getValueAndCastFromMail(mail, DESTINATION_CUSTOM_ATTRIBUTE_NAME, MAP_STRING_CALENDAR_CLASS); assertThat(expectedCalendars).hasValueSatisfying(calendars -> assertThat(calendars) .hasSize(1)); } private Attribute makeCustomSourceAttribute(Serializable attachments) { - return new Attribute(SOURCE_CUSTOM_ATTRIBUTE_NAME, AttributeValue.ofSerializable(attachments)); + return new Attribute(SOURCE_CUSTOM_ATTRIBUTE_NAME, AttributeValue.ofUnserializable(attachments)); } } diff --git a/mailet/standard/src/test/java/org/apache/james/transport/matchers/HasExceptionTest.java b/mailet/standard/src/test/java/org/apache/james/transport/matchers/HasExceptionTest.java index e4b4c683f4..18929b6d52 100644 --- a/mailet/standard/src/test/java/org/apache/james/transport/matchers/HasExceptionTest.java +++ b/mailet/standard/src/test/java/org/apache/james/transport/matchers/HasExceptionTest.java @@ -36,8 +36,7 @@ import org.apache.mailet.base.test.MailUtil; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class HasExceptionTest { - +class HasExceptionTest { private FakeMail mockedMail; private Matcher testee; @@ -49,8 +48,8 @@ public class HasExceptionTest { } @Test - public void matchShouldReturnAddressesWhenSpecifiedExceptionHasOccurred() throws MessagingException { - mockedMail.setAttribute(new Attribute(Mail.MAILET_ERROR, AttributeValue.ofSerializable(new AddressException()))); + void matchShouldReturnAddressesWhenSpecifiedExceptionHasOccurred() throws MessagingException { + mockedMail.setAttribute(new Attribute(Mail.MAILET_ERROR, AttributeValue.ofUnserializable(new AddressException()))); FakeMatcherConfig matcherConfig = FakeMatcherConfig.builder() .matcherName("HasException") @@ -63,8 +62,8 @@ public class HasExceptionTest { } @Test - public void matchShouldReturnAddressesWhenSubclassOfSpecifiedExceptionHasOccurred() throws MessagingException { - mockedMail.setAttribute(new Attribute(Mail.MAILET_ERROR, AttributeValue.ofSerializable(new AddressException()))); + void matchShouldReturnAddressesWhenSubclassOfSpecifiedExceptionHasOccurred() throws MessagingException { + mockedMail.setAttribute(new Attribute(Mail.MAILET_ERROR, AttributeValue.ofUnserializable(new AddressException()))); FakeMatcherConfig matcherConfig = FakeMatcherConfig.builder() .matcherName("HasException") @@ -77,8 +76,8 @@ public class HasExceptionTest { } @Test - public void matchShouldReturnEmptyWhenOtherExceptionHasOccurred() throws MessagingException { - mockedMail.setAttribute(new Attribute(Mail.MAILET_ERROR, AttributeValue.ofSerializable(new java.lang.RuntimeException()))); + void matchShouldReturnEmptyWhenOtherExceptionHasOccurred() throws MessagingException { + mockedMail.setAttribute(new Attribute(Mail.MAILET_ERROR, AttributeValue.ofUnserializable(new java.lang.RuntimeException()))); testee.init(FakeMatcherConfig.builder() .matcherName("HasException") @@ -89,8 +88,8 @@ public class HasExceptionTest { } @Test - public void matchShouldReturnEmptyWhenSuperclassOfSpecifiedExceptionHasOccurred() throws MessagingException { - mockedMail.setAttribute(new Attribute(Mail.MAILET_ERROR, AttributeValue.ofSerializable(new javax.mail.MessagingException()))); + void matchShouldReturnEmptyWhenSuperclassOfSpecifiedExceptionHasOccurred() throws MessagingException { + mockedMail.setAttribute(new Attribute(Mail.MAILET_ERROR, AttributeValue.ofUnserializable(new javax.mail.MessagingException()))); FakeMatcherConfig matcherConfig = FakeMatcherConfig.builder() .matcherName("HasException") @@ -103,7 +102,7 @@ public class HasExceptionTest { } @Test - public void matchShouldReturnEmptyWhenNoExceptionHasOccurred() throws MessagingException { + void matchShouldReturnEmptyWhenNoExceptionHasOccurred() throws MessagingException { FakeMatcherConfig matcherConfig = FakeMatcherConfig.builder() .matcherName("HasException") .condition("java.lang.Exception") @@ -115,8 +114,8 @@ public class HasExceptionTest { } @Test - public void matchShouldReturnEmptyWhenNonExceptionIsAttached() throws MessagingException { - mockedMail.setAttribute(new Attribute(Mail.MAILET_ERROR, AttributeValue.of(new java.lang.String()))); + void matchShouldReturnEmptyWhenNonExceptionIsAttached() throws MessagingException { + mockedMail.setAttribute(new Attribute(Mail.MAILET_ERROR, AttributeValue.of(""))); FakeMatcherConfig matcherConfig = FakeMatcherConfig.builder() .matcherName("HasException") @@ -129,7 +128,7 @@ public class HasExceptionTest { } @Test - public void initShouldRaiseMessagingExceptionWhenInvalidClassName() throws MessagingException { + void initShouldRaiseMessagingExceptionWhenInvalidClassName() { FakeMatcherConfig matcherConfig = FakeMatcherConfig.builder() .matcherName("HasException") .condition("java.lang.InvalidClassName") @@ -139,7 +138,7 @@ public class HasExceptionTest { } @Test - public void initShouldRaiseMessagingExceptionWhenClassNameIsNotException() throws MessagingException { + void initShouldRaiseMessagingExceptionWhenClassNameIsNotException() { FakeMatcherConfig matcherConfig = FakeMatcherConfig.builder() .matcherName("HasException") .condition("java.lang.String") @@ -149,8 +148,8 @@ public class HasExceptionTest { } @Test - public void initShouldRaiseMessagingExceptionWhenClassNameIsNotFullyQualified() throws MessagingException { - mockedMail.setAttribute(new Attribute(Mail.MAILET_ERROR, AttributeValue.ofSerializable(new javax.mail.MessagingException()))); + void initShouldRaiseMessagingExceptionWhenClassNameIsNotFullyQualified() { + mockedMail.setAttribute(new Attribute(Mail.MAILET_ERROR, AttributeValue.ofUnserializable(new javax.mail.MessagingException()))); FakeMatcherConfig matcherConfig = FakeMatcherConfig.builder() .matcherName("HasException") diff --git a/server/container/core/src/main/java/org/apache/james/server/core/MailImpl.java b/server/container/core/src/main/java/org/apache/james/server/core/MailImpl.java index 9ae9876544..a47b7da297 100644 --- a/server/container/core/src/main/java/org/apache/james/server/core/MailImpl.java +++ b/server/container/core/src/main/java/org/apache/james/server/core/MailImpl.java @@ -44,6 +44,7 @@ import javax.mail.internet.MimeMessage; import javax.mail.internet.ParseException; import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.lang3.tuple.Pair; import org.apache.james.core.MailAddress; import org.apache.james.core.MaybeSender; import org.apache.james.core.builder.MimeMessageBuilder; @@ -685,9 +686,8 @@ public class MailImpl implements Disposable, Mail { private Map<String, String> getAttributesAsJson() { return attributes.values() .stream() - .collect(Collectors.toMap( - attribute -> attribute.getName().asString(), - attribute -> attribute.getValue().toJson().toString())); + .flatMap(entry -> entry.getValue().toJson().map(value -> Pair.of(entry.getName().asString(), value.toString())).stream()) + .collect(ImmutableMap.toImmutableMap(Pair::getKey, Pair::getValue)); } /** diff --git a/server/data/data-jpa/src/main/java/org/apache/james/mailrepository/jpa/JPAMailRepository.java b/server/data/data-jpa/src/main/java/org/apache/james/mailrepository/jpa/JPAMailRepository.java index 575592e441..667a0e4ab1 100644 --- a/server/data/data-jpa/src/main/java/org/apache/james/mailrepository/jpa/JPAMailRepository.java +++ b/server/data/data-jpa/src/main/java/org/apache/james/mailrepository/jpa/JPAMailRepository.java @@ -44,6 +44,7 @@ import javax.persistence.NoResultException; import org.apache.commons.configuration2.HierarchicalConfiguration; import org.apache.commons.configuration2.ex.ConfigurationException; import org.apache.commons.configuration2.tree.ImmutableNode; +import org.apache.commons.lang3.tuple.Pair; import org.apache.james.backends.jpa.EntityManagerUtils; import org.apache.james.core.MailAddress; import org.apache.james.lifecycle.api.Configurable; @@ -70,6 +71,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; /** * Implementation of a MailRepository on a database via JPA. @@ -183,9 +185,9 @@ public class JPAMailRepository implements MailRepository, Configurable, Initiali } private String serializeAttributes(Stream<Attribute> attributes) { - Map<String, JsonNode> map = attributes.collect(Collectors.toMap( - attribute -> attribute.getName().asString(), - attribute -> attribute.getValue().toJson())); + Map<String, JsonNode> map = attributes + .flatMap(entry -> entry.getValue().toJson().map(value -> Pair.of(entry.getName().asString(), value)).stream()) + .collect(ImmutableMap.toImmutableMap(Pair::getKey, Pair::getValue)); return new ObjectNode(JsonNodeFactory.instance, map).toString(); } diff --git a/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/ProcessorUtil.java b/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/ProcessorUtil.java index 787b464f3f..f16141ae8e 100644 --- a/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/ProcessorUtil.java +++ b/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/ProcessorUtil.java @@ -65,7 +65,7 @@ public class ProcessorUtil { String errorString = sout.toString(); mail.setErrorMessage(errorString); logger.error(errorString); - mail.setAttribute(new Attribute(Mail.MAILET_ERROR, AttributeValue.ofSerializable(me))); + mail.setAttribute(new Attribute(Mail.MAILET_ERROR, AttributeValue.ofUnserializable(me))); } /** diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/ActionUtils.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/ActionUtils.java index b3849441b4..c013e92906 100644 --- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/ActionUtils.java +++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/ActionUtils.java @@ -42,10 +42,6 @@ public class ActionUtils { /** * Answers the sole intended recipient for aMail. - * - * @param aMail - * @return String - * @throws MessagingException */ public static MailAddress getSoleRecipient(Mail aMail) throws MessagingException { if (aMail.getRecipients() == null) { @@ -53,7 +49,7 @@ public class ActionUtils { + ". Exactly 1 recipient is expected."); } else if (1 != aMail.getRecipients().size()) { throw new MessagingException("Invalid number of recipients - " - + Integer.toString(aMail.getRecipients().size()) + + aMail.getRecipients().size() + ". Exactly 1 recipient is expected."); } return aMail.getRecipients().iterator().next(); @@ -62,18 +58,14 @@ public class ActionUtils { /** * Detect and handle locally looping mail. External loop detection is left * to the MTA. - * - * @param aMail - * @param anAttributeSuffix - * @throws MessagingException */ public static void detectAndHandleLocalLooping(Mail aMail, String anAttributeSuffix) throws MessagingException { MailAddress thisRecipient = getSoleRecipient(aMail); AttributeName attributeName = AttributeName.of(ATTRIBUTE_PREFIX + anAttributeSuffix); AttributeUtils - .getValueAndCastFromMail(aMail, attributeName, MailAddress.class) - .filter(lastRecipient -> lastRecipient.equals(thisRecipient)) + .getValueAndCastFromMail(aMail, attributeName, String.class) + .filter(Throwing.predicate(lastRecipient -> new MailAddress(lastRecipient).equals(thisRecipient))) .ifPresent(Throwing.consumer(any -> { MessagingException ex = new MessagingException( "This message is looping! Message ID: " @@ -81,6 +73,6 @@ public class ActionUtils { LOGGER.warn(ex.getMessage(), ex); throw ex; }).sneakyThrow()); - aMail.setAttribute(new Attribute(attributeName, AttributeValue.ofSerializable(thisRecipient))); + aMail.setAttribute(new Attribute(attributeName, AttributeValue.of(thisRecipient.asString()))); } } diff --git a/server/mailrepository/mailrepository-blob/src/main/scala/org/apache/james/mailrepository/blob/MailMetadata.scala b/server/mailrepository/mailrepository-blob/src/main/scala/org/apache/james/mailrepository/blob/MailMetadata.scala index 92df76ef0b..a66de9d7ee 100644 --- a/server/mailrepository/mailrepository-blob/src/main/scala/org/apache/james/mailrepository/blob/MailMetadata.scala +++ b/server/mailrepository/mailrepository-blob/src/main/scala/org/apache/james/mailrepository/blob/MailMetadata.scala @@ -54,7 +54,7 @@ private[blob] object MailMetadata { private def serializedAttributes(mail: Mail): Map[String, String] = mail.attributes().toScala(LazyList) - .map(attribute => attribute.getName.asString() -> attribute.getValue.toJson.toString) + .flatMap(attribute => attribute.getValue.toJson.toScala.map(value => attribute.getName.asString() -> value.toString)) .toMap private def fromPerRecipientHeaders(mail: Mail): Map[String, Iterable[Header]] = { diff --git a/server/mailrepository/mailrepository-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryMailDaoV2.java b/server/mailrepository/mailrepository-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryMailDaoV2.java index 27461392c3..d8fac3d3de 100644 --- a/server/mailrepository/mailrepository-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryMailDaoV2.java +++ b/server/mailrepository/mailrepository-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryMailDaoV2.java @@ -76,6 +76,7 @@ import com.datastax.oss.driver.api.core.cql.Row; import com.datastax.oss.driver.api.core.data.TupleValue; import com.datastax.oss.driver.api.core.type.DataTypes; import com.datastax.oss.driver.api.core.type.TupleType; +import com.fasterxml.jackson.databind.JsonNode; import com.github.fge.lambdas.Throwing; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; @@ -277,7 +278,7 @@ public class CassandraMailRepositoryMailDaoV2 { private ImmutableMap<String, String> toRawAttributeMap(Mail mail) { return mail.attributes() - .map(attribute -> Pair.of(attribute.getName().asString(), toJson(attribute.getValue()))) + .flatMap(attribute -> attribute.getValue().toJson().map(JsonNode::toString).map(value -> Pair.of(attribute.getName().asString(), value)).stream()) .collect(ImmutableMap.toImmutableMap(Pair::getLeft, Pair::getRight)); } @@ -302,10 +303,6 @@ public class CassandraMailRepositoryMailDaoV2 { return result; } - private String toJson(AttributeValue<?> attributeValue) { - return attributeValue.toJson().toString(); - } - private MailAddress toMailAddress(String rawValue) { try { return new MailAddress(rawValue); diff --git a/server/queue/queue-api/src/test/java/org/apache/james/queue/api/MailQueueContract.java b/server/queue/queue-api/src/test/java/org/apache/james/queue/api/MailQueueContract.java index 76dbdba531..dd218c89d7 100644 --- a/server/queue/queue-api/src/test/java/org/apache/james/queue/api/MailQueueContract.java +++ b/server/queue/queue-api/src/test/java/org/apache/james/queue/api/MailQueueContract.java @@ -335,24 +335,6 @@ public interface MailQueueContract { .containsOnly(header, header2); } - @Test - default void queueShouldPreserveNonStringMailAttribute() throws Exception { - Attribute attribute = Attribute.convertToAttribute("any", new SerializableAttribute("value")); - enQueue(defaultMail() - .name("mail") - .attribute(attribute) - .build()); - - MailQueue.MailQueueItem mailQueueItem = Flux.from(getMailQueue().deQueue()).blockFirst(); - assertThat(mailQueueItem.getMail().getAttribute(attribute.getName())) - .hasValueSatisfying(item -> { - assertThat(item) - .isEqualTo(attribute); - assertThat(item.getValue().value()) - .isInstanceOf(SerializableAttribute.class); - }); - } - @Test default void dequeueShouldBeFifo() throws Exception { String firstExpectedName = "name1"; diff --git a/server/queue/queue-jms/src/main/java/org/apache/james/queue/jms/JMSCacheableMailQueue.java b/server/queue/queue-jms/src/main/java/org/apache/james/queue/jms/JMSCacheableMailQueue.java index b69177e5c4..af3f80bd05 100644 --- a/server/queue/queue-jms/src/main/java/org/apache/james/queue/jms/JMSCacheableMailQueue.java +++ b/server/queue/queue-jms/src/main/java/org/apache/james/queue/jms/JMSCacheableMailQueue.java @@ -78,6 +78,7 @@ import org.reactivestreams.Publisher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.databind.JsonNode; import com.github.fge.lambdas.Throwing; import com.google.common.base.Joiner; import com.google.common.base.Splitter; @@ -363,9 +364,8 @@ public class JMSCacheableMailQueue implements ManageableMailQueue, JMSSupport, M String sender = mail.getMaybeSender().asString(""); props.putAll(mail.attributes() - .collect(ImmutableMap.toImmutableMap( - attribute -> attribute.getName().asString(), - attribute -> attribute.getValue().toJson().toString()))); + .flatMap(attribute -> attribute.getValue().toJson().map(JsonNode::toString).map(s -> Pair.of(attribute.getName().asString(), s)).stream()) + .collect(ImmutableMap.toImmutableMap(Pair::getKey, Pair::getValue))); ImmutableList<String> attributeNames = mail.attributeNames() .map(AttributeName::asString) diff --git a/server/queue/queue-pulsar/src/main/scala/org/apache/james/queue/pulsar/MailMetadata.scala b/server/queue/queue-pulsar/src/main/scala/org/apache/james/queue/pulsar/MailMetadata.scala index 67a4a80847..6b6c5d712f 100644 --- a/server/queue/queue-pulsar/src/main/scala/org/apache/james/queue/pulsar/MailMetadata.scala +++ b/server/queue/queue-pulsar/src/main/scala/org/apache/james/queue/pulsar/MailMetadata.scala @@ -50,7 +50,7 @@ private[pulsar] object MailMetadata { private def serializedAttributes(mail: Mail): Map[String, String] = mail.attributes().toScala(LazyList) - .map(attribute => attribute.getName.asString() -> attribute.getValue.toJson.toString) + .flatMap(attribute => attribute.getValue.toJson.toScala.map(value => attribute.getName.asString() -> value.toString)) .toMap private def fromPerRecipientHeaders(mail: Mail): Map[String, Iterable[Header]] = { diff --git a/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/MailReferenceDTO.java b/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/MailReferenceDTO.java index b40a7de1b8..798166f91e 100644 --- a/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/MailReferenceDTO.java +++ b/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/MailReferenceDTO.java @@ -25,7 +25,6 @@ import java.util.Date; import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.function.Function; import java.util.stream.Stream; import org.apache.commons.lang3.tuple.Pair; @@ -42,6 +41,7 @@ import org.apache.mailet.PerRecipientHeaders; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; import com.github.fge.lambdas.Throwing; import com.github.fge.lambdas.consumers.ThrowingBiConsumer; import com.google.common.collect.ImmutableList; @@ -83,11 +83,9 @@ class MailReferenceDTO { } private static ImmutableMap<String, String> serializedAttributes(Mail mail) { - Function<Attribute, String> name = attribute -> attribute.getName().asString(); - Function<Attribute, String> value = attribute -> attribute.getValue().toJson().toString(); - return mail - .attributes() - .collect(ImmutableMap.toImmutableMap(name, value)); + return mail.attributes() + .flatMap(attribute -> attribute.getValue().toJson().map(JsonNode::toString).map(value -> Pair.of(attribute.getName().asString(), value)).stream()) + .collect(ImmutableMap.toImmutableMap(Pair::getLeft, Pair::getRight)); } private final String enqueueId; diff --git a/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/view/cassandra/EnqueuedMailsDaoUtil.java b/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/view/cassandra/EnqueuedMailsDaoUtil.java index 3eb2b407e6..57c65213a6 100644 --- a/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/view/cassandra/EnqueuedMailsDaoUtil.java +++ b/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/view/cassandra/EnqueuedMailsDaoUtil.java @@ -72,6 +72,7 @@ import org.apache.mailet.PerRecipientHeaders; import com.datastax.oss.driver.api.core.cql.Row; import com.datastax.oss.driver.api.core.data.TupleValue; import com.datastax.oss.driver.api.core.type.TupleType; +import com.fasterxml.jackson.databind.JsonNode; import com.github.fge.lambdas.Throwing; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; @@ -185,12 +186,15 @@ public class EnqueuedMailsDaoUtil { static ImmutableMap<String, ByteBuffer> toRawAttributeMap(Mail mail) { return mail.attributes() - .map(attribute -> Pair.of(attribute.getName().asString(), toByteBuffer(attribute.getValue()))) + .flatMap(attribute -> toByteBuffer(attribute.getValue()).map(buffer -> Pair.of(attribute.getName().asString(), buffer)).stream()) .collect(ImmutableMap.toImmutableMap(Pair::getLeft, Pair::getRight)); } - private static ByteBuffer toByteBuffer(AttributeValue<?> attributeValue) { - return ByteBuffer.wrap(attributeValue.toJson().toString().getBytes(StandardCharsets.UTF_8)); + private static Optional<ByteBuffer> toByteBuffer(AttributeValue<?> attributeValue) { + return attributeValue.toJson() + .map(JsonNode::toString) + .map(s -> s.getBytes(StandardCharsets.UTF_8)) + .map(ByteBuffer::wrap); } static ImmutableList<TupleValue> toTupleList(TupleType userHeaderNameHeaderValueTriple, PerRecipientHeaders perRecipientHeaders) { --------------------------------------------------------------------- To unsubscribe, e-mail: notifications-unsubscr...@james.apache.org For additional commands, e-mail: notifications-h...@james.apache.org