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
commit 781b1dc8055a1cf1b62999208e795f4cabd4e75d Author: Benoit Tellier <[email protected]> AuthorDate: Mon Mar 11 11:30:49 2019 +0700 JAMES-2665 MailImpl should support any AttributeValue when being serialized To ensure that, we should rely on Jsonable when serializing attributes. A fallback to java serialization upon failure ensures no compatibility issues are met. --- .../org/apache/james/server/core/MailImpl.java | 47 +++++++++++++++++++++- .../org/apache/james/server/core/MailImplTest.java | 3 -- 2 files changed, 45 insertions(+), 5 deletions(-) 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 f6046d9..de17b86 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 @@ -20,6 +20,7 @@ package org.apache.james.server.core; import java.io.IOException; +import java.io.ObjectInputStream; import java.io.OptionalDataException; import java.io.OutputStream; import java.io.Serializable; @@ -593,6 +594,36 @@ public class MailImpl implements Disposable, Mail { remoteHost = (String) in.readObject(); remoteAddr = (String) in.readObject(); setLastUpdated((Date) in.readObject()); + try { + setAttributesUsingJsonable(in); + } catch (Exception e) { + setAttributesUsingJavaSerializable(in); + } + perRecipientSpecificHeaders = (PerRecipientHeaders) in.readObject(); + } + + /** + * Newest mailet API introduced {@link AttributeValue} which can encapsulate any class, possible not serializable. + * + * As such, algorithm relying on out of the box serialization can not handle non serializable attribute values as well as + * nested AttributeValue. + * + * Thus, rather than Java deserializing attributes we deserialize them as Json using AttributeValue capabilities. + */ + private void setAttributesUsingJsonable(ObjectInputStream in) throws IOException, ClassNotFoundException { + Map<String, String> attributesAsJson = (Map<String, String>) in.readObject(); + + this.attributes = attributesAsJson.entrySet().stream() + .map(Throwing.function(entry -> new Attribute(AttributeName.of(entry.getKey()), AttributeValue.fromJsonString(entry.getValue())))) + .collect(Collectors.toMap( + Attribute::getName, + Function.identity())); + } + + /** + * Fallback to Java deserialization if {@link MailImpl#setAttributesUsingJsonable(ObjectInputStream)} fails. + */ + private void setAttributesUsingJavaSerializable(ObjectInputStream in) throws IOException, ClassNotFoundException { // the following is under try/catch to be backwards compatible // with messages created with James version <= 2.2.0a8 try { @@ -604,7 +635,6 @@ public class MailImpl implements Disposable, Mail { throw ode; } } - perRecipientSpecificHeaders = (PerRecipientHeaders) in.readObject(); } /** @@ -622,7 +652,7 @@ public class MailImpl implements Disposable, Mail { out.writeObject(remoteHost); out.writeObject(remoteAddr); out.writeObject(lastUpdated); - out.writeObject(getAttributesRaw()); + out.writeObject(getAttributesAsJson()); out.writeObject(perRecipientSpecificHeaders); } @@ -654,6 +684,19 @@ public class MailImpl implements Disposable, Mail { } /** + * Newly serialized emails are serialized using {@link AttributeValue}. + * + * Upon deserialization, fallback to Java deserialization is handled to not introduce retro-compatibility issues. + */ + private Map<String, String> getAttributesAsJson() { + return attributes.values() + .stream() + .collect(Collectors.toMap( + attribute -> attribute.getName().asString(), + attribute -> attribute.getValue().toJson().toString())); + } + + /** * <p> * This method is necessary, when Mail repositories needs to deal explicitly * with retriving Mail attributes as a Serializable diff --git a/server/container/core/src/test/java/org/apache/james/server/core/MailImplTest.java b/server/container/core/src/test/java/org/apache/james/server/core/MailImplTest.java index 8dc8635..3e0811e 100644 --- a/server/container/core/src/test/java/org/apache/james/server/core/MailImplTest.java +++ b/server/container/core/src/test/java/org/apache/james/server/core/MailImplTest.java @@ -43,7 +43,6 @@ import org.apache.mailet.Mail; import org.apache.mailet.base.MailAddressFixture; import org.apache.mailet.base.test.MailUtil; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import com.github.fge.lambdas.Throwing; @@ -322,7 +321,6 @@ public class MailImplTest extends ContractMailTest { .isEqualToComparingFieldByField(mail); } - @Disabled("JAMES-2665: Throws java.io.NotSerializableException: java.util.Optional") @Test void mailImplShouldBeSerializableWithOptionalAttribute() throws Exception { MailImpl mail = MailImpl.builder() @@ -344,7 +342,6 @@ public class MailImplTest extends ContractMailTest { .isEqualToComparingFieldByField(mail); } - @Disabled("JAMES-2665: Throws java.io.NotSerializableException: java.io.NotSerializableException: org.apache.mailet.AttributeValue") @Test void mailImplShouldBeSerializableWithCollectionAttribute() throws Exception { MailImpl mail = MailImpl.builder() --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
