You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by rc...@apache.org on 2020/12/11 10:44:08 UTC
[james-project] 04/15: JAMES-2578 PerRecipientHeaders: No longer
rely on Java serialization for JMS and ActiveMQ
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 56e7f67f83d2d196c1f6209727f14911c9fb9e17
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Mon Dec 7 14:19:47 2020 +0700
JAMES-2578 PerRecipientHeaders: No longer rely on Java serialization for JMS and ActiveMQ
---
.../org/apache/mailet/PerRecipientHeaders.java | 36 +++++++++++++++++---
.../james/queue/jms/JMSCacheableMailQueue.java | 39 +++++++++++++++++-----
2 files changed, 61 insertions(+), 14 deletions(-)
diff --git a/mailet/api/src/main/java/org/apache/mailet/PerRecipientHeaders.java b/mailet/api/src/main/java/org/apache/mailet/PerRecipientHeaders.java
index 4e0a434..0f70335 100644
--- a/mailet/api/src/main/java/org/apache/mailet/PerRecipientHeaders.java
+++ b/mailet/api/src/main/java/org/apache/mailet/PerRecipientHeaders.java
@@ -21,14 +21,17 @@ package org.apache.mailet;
import java.io.Serializable;
import java.util.Collection;
+import java.util.List;
import org.apache.james.core.MailAddress;
import com.github.steveash.guavate.Guavate;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Joiner;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
@@ -74,12 +77,8 @@ public class PerRecipientHeaders implements Serializable {
}
public static class Header implements Serializable {
- private final String name;
- private final String value;
- public static Builder builder() {
- return new Builder();
- }
+ public static final String SEPARATOR = ": ";
public static class Builder {
private String name;
@@ -102,8 +101,31 @@ public class PerRecipientHeaders implements Serializable {
}
}
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static Header fromString(String value) {
+ Preconditions.checkArgument(value.contains(SEPARATOR), "Header is string form needs to contain ': ' separator");
+
+ List<String> parts = Splitter.on(SEPARATOR).splitToList(value);
+
+ return new Header(
+ parts.get(0),
+ Joiner.on(SEPARATOR)
+ .join(parts.stream()
+ .skip(1)
+ .collect(Guavate.toImmutableList())));
+ }
+
+ private final String name;
+ private final String value;
+
@VisibleForTesting
Header(String name, String value) {
+ Preconditions.checkArgument(!name.contains(":"), "Header name should not contain separator");
+ Preconditions.checkArgument(!name.contains("\n"), "Header name should not contain line break");
+
this.name = name;
this.value = value;
}
@@ -116,6 +138,10 @@ public class PerRecipientHeaders implements Serializable {
return value;
}
+ public String asString() {
+ return name + SEPARATOR + value;
+ }
+
@Override
public final boolean equals(Object o) {
if (o instanceof Header) {
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 e6950c7..a680e2c 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
@@ -32,7 +32,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
-import java.util.Optional;
import java.util.StringTokenizer;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
@@ -53,6 +52,7 @@ import javax.mail.internet.AddressException;
import javax.mail.internet.MimeMessage;
import org.apache.commons.collections.iterators.EnumerationIterator;
+import org.apache.commons.lang3.tuple.Pair;
import org.apache.james.core.MailAddress;
import org.apache.james.core.MaybeSender;
import org.apache.james.lifecycle.api.Disposable;
@@ -68,7 +68,6 @@ import org.apache.james.queue.api.MailQueueName;
import org.apache.james.queue.api.ManageableMailQueue;
import org.apache.james.server.core.MailImpl;
import org.apache.james.server.core.MimeMessageCopyOnWriteProxy;
-import org.apache.james.util.SerializationUtil;
import org.apache.mailet.Attribute;
import org.apache.mailet.AttributeName;
import org.apache.mailet.AttributeUtils;
@@ -341,11 +340,13 @@ public class JMSCacheableMailQueue implements ManageableMailQueue, JMSSupport, M
props.put(JAMES_MAIL_MESSAGE_SIZE, mail.getMessageSize());
props.put(JAMES_MAIL_NAME, mail.getName());
- // won't serialize the empty headers so it is mandatory
- // to handle nulls when reconstructing mail from message
- if (!mail.getPerRecipientSpecificHeaders().getHeadersByRecipient().isEmpty()) {
- props.put(JAMES_MAIL_PER_RECIPIENT_HEADERS, SerializationUtil.serialize(mail.getPerRecipientSpecificHeaders()));
- }
+ mail.getPerRecipientSpecificHeaders().getHeadersByRecipient()
+ .asMap()
+ .forEach((recipient, headers) -> props.put(JAMES_MAIL_PER_RECIPIENT_HEADERS + "-" + recipient.asString(),
+ Joiner.on('\n')
+ .join(headers.stream()
+ .map(PerRecipientHeaders.Header::asString)
+ .collect(Guavate.toImmutableList()))));
String recipientsAsString = joiner.join(mail.getRecipients());
@@ -413,9 +414,29 @@ public class JMSCacheableMailQueue implements ManageableMailQueue, JMSSupport, M
MailImpl.Builder builder = MailImpl.builder().name(name);
builder.errorMessage(message.getStringProperty(JAMES_MAIL_ERROR_MESSAGE));
builder.lastUpdated(new Date(message.getLongProperty(JAMES_MAIL_LAST_UPDATED)));
+ Enumeration<String> properties = message.getPropertyNames();
- Optional.ofNullable(SerializationUtil.<PerRecipientHeaders>deserialize(message.getStringProperty(JAMES_MAIL_PER_RECIPIENT_HEADERS)))
- .ifPresent(builder::addAllHeadersForRecipients);
+ PerRecipientHeaders perRecipientHeaders = new PerRecipientHeaders();
+ ImmutableList.copyOf(properties.asIterator())
+ .stream()
+ .filter(property -> property.startsWith(JAMES_MAIL_PER_RECIPIENT_HEADERS + "-"))
+ .flatMap(property -> {
+ try {
+ MailAddress address = new MailAddress(property.substring(JAMES_MAIL_PER_RECIPIENT_HEADERS.length() + 1));
+ String headers = message.getStringProperty(property);
+ return Splitter.on('\n').splitToList(headers)
+ .stream()
+ .map(PerRecipientHeaders.Header::fromString)
+ .map(header -> Pair.of(address, header));
+ } catch (AddressException | JMSException e) {
+ LOGGER.error("Error deserializing per-recipient header", e);
+ return Stream.empty();
+ }
+ })
+ .forEach(pair -> perRecipientHeaders.addHeaderForRecipient(pair.getValue(), pair.getKey()));
+ if (!perRecipientHeaders.getHeadersByRecipient().isEmpty()) {
+ builder.addAllHeadersForRecipients(perRecipientHeaders);
+ }
String recipients = message.getStringProperty(JAMES_MAIL_RECIPIENTS);
StringTokenizer recipientTokenizer = new StringTokenizer(recipients, JAMES_MAIL_SEPARATOR);
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org