You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by bt...@apache.org on 2019/03/20 02:01:48 UTC
[james-project] 08/09: JAMES-2665 MailImpl should support any
AttributeValue when being serialized
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 <bt...@linagora.com>
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: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org