JAMES-2608 Store attributes as Json

Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/3b223d53
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/3b223d53
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/3b223d53

Branch: refs/heads/master
Commit: 3b223d537508d9a79aa50640cc23d87726508c29
Parents: 1ebe3fd
Author: Antoine Duprat <[email protected]>
Authored: Mon Dec 17 11:34:23 2018 +0100
Committer: Raphael Ouazana <[email protected]>
Committed: Wed Dec 19 09:24:12 2018 +0100

----------------------------------------------------------------------
 .../CassandraMailRepositoryMailDaoV2.java       |  47 ++----
 .../CassandraMailRepositoryModule.java          |   5 +-
 .../CassandraMailRepositoryMailDAOTest.java     | 163 +++++++++++++------
 3 files changed, 126 insertions(+), 89 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/3b223d53/server/mailrepository/mailrepository-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryMailDaoV2.java
----------------------------------------------------------------------
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 156fa85..36e8e28 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
@@ -44,13 +44,6 @@ import static 
org.apache.james.mailrepository.cassandra.MailRepositoryTableV2.RE
 import static 
org.apache.james.mailrepository.cassandra.MailRepositoryTableV2.SENDER;
 import static 
org.apache.james.mailrepository.cassandra.MailRepositoryTableV2.STATE;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
-import java.nio.ByteBuffer;
 import java.util.Collection;
 import java.util.Date;
 import java.util.List;
@@ -69,7 +62,9 @@ import org.apache.james.core.MailAddress;
 import org.apache.james.mailrepository.api.MailKey;
 import org.apache.james.mailrepository.api.MailRepositoryUrl;
 import org.apache.james.server.core.MailImpl;
-import org.apache.james.util.streams.Iterators;
+import org.apache.mailet.Attribute;
+import org.apache.mailet.AttributeName;
+import org.apache.mailet.AttributeValue;
 import org.apache.mailet.Mail;
 import org.apache.mailet.PerRecipientHeaders;
 import org.apache.mailet.PerRecipientHeaders.Header;
@@ -183,7 +178,7 @@ public class CassandraMailRepositoryMailDaoV2 implements 
CassandraMailRepository
         String errorMessage = row.getString(ERROR_MESSAGE);
         String name = row.getString(MAIL_KEY);
         Date lastUpdated = row.getTimestamp(LAST_UPDATED);
-        Map<String, ByteBuffer> rawAttributes = row.getMap(ATTRIBUTES, 
String.class, ByteBuffer.class);
+        Map<String, String> rawAttributes = row.getMap(ATTRIBUTES, 
String.class, String.class);
         PerRecipientHeaders perRecipientHeaders = 
fromList(row.getList(PER_RECIPIENT_SPECIFIC_HEADERS, TupleValue.class));
 
         MailImpl.Builder mailBuilder = MailImpl.builder()
@@ -203,21 +198,20 @@ public class CassandraMailRepositoryMailDaoV2 implements 
CassandraMailRepository
             blobIdFactory.from(row.getString(BODY_BLOB_ID)));
     }
 
-    private Map<String, Serializable> toAttributes(Map<String, ByteBuffer> 
rowAttributes) {
+    private List<Attribute> toAttributes(Map<String, String> rowAttributes) {
         return rowAttributes.entrySet()
             .stream()
-            .map(entry -> Pair.of(entry.getKey(), 
fromByteBuffer(entry.getValue())))
-            .collect(Guavate.toImmutableMap(Pair::getLeft, Pair::getRight));
+            .map(Throwing.function(entry -> new 
Attribute(AttributeName.of(entry.getKey()), 
AttributeValue.fromJsonString(entry.getValue()))))
+            .collect(Guavate.toImmutableList());
     }
 
     private ImmutableList<String> asStringList(Collection<MailAddress> 
mailAddresses) {
         return 
mailAddresses.stream().map(MailAddress::asString).collect(Guavate.toImmutableList());
     }
 
-    private ImmutableMap<String, ByteBuffer> toRawAttributeMap(Mail mail) {
-        return Iterators.toStream(mail.getAttributeNames())
-            .map(name -> Pair.of(name, mail.getAttribute(name)))
-            .map(pair -> Pair.of(pair.getLeft(), 
toByteBuffer(pair.getRight())))
+    private ImmutableMap<String, String> toRawAttributeMap(Mail mail) {
+        return mail.attributes()
+            .map(attribute -> Pair.of(attribute.getName().asString(), 
toJson(attribute.getValue())))
             .collect(Guavate.toImmutableMap(Pair::getLeft, Pair::getRight));
     }
 
@@ -242,25 +236,8 @@ public class CassandraMailRepositoryMailDaoV2 implements 
CassandraMailRepository
         return result;
     }
 
-    private ByteBuffer toByteBuffer(Serializable serializable) {
-        try {
-            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-            new ObjectOutputStream(outputStream).writeObject(serializable);
-            return ByteBuffer.wrap(outputStream.toByteArray());
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    private Serializable fromByteBuffer(ByteBuffer byteBuffer) {
-        try {
-            byte[] data = new byte[byteBuffer.remaining()];
-            byteBuffer.get(data);
-            ObjectInputStream objectInputStream = new ObjectInputStream(new 
ByteArrayInputStream(data));
-            return (Serializable) objectInputStream.readObject();
-        } catch (IOException | ClassNotFoundException e) {
-            throw new RuntimeException(e);
-        }
+    private String toJson(AttributeValue<?> attributeValue) {
+        return attributeValue.toJson().toString();
     }
 
     private MailAddress toMailAddress(String rawValue) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/3b223d53/server/mailrepository/mailrepository-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryModule.java
----------------------------------------------------------------------
diff --git 
a/server/mailrepository/mailrepository-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryModule.java
 
b/server/mailrepository/mailrepository-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryModule.java
index f2c44f4..6e6c3cd 100644
--- 
a/server/mailrepository/mailrepository-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryModule.java
+++ 
b/server/mailrepository/mailrepository-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryModule.java
@@ -71,7 +71,8 @@ public interface CassandraMailRepositoryModule {
         .table(MailRepositoryTableV2.CONTENT_TABLE_NAME)
         .comment("Stores the mails for a given repository. " +
             "Content is stored with other blobs. " +
-            "This v2 version was introduced to support multiple headers for 
each user")
+            "This v2 version was introduced to support multiple headers for 
each user. " +
+            "The attributes are store as Json introduced in Mailet API v3.2.")
         .statement(statement -> statement
             .addPartitionKey(MailRepositoryTable.REPOSITORY_NAME, text())
             .addPartitionKey(MailRepositoryTable.MAIL_KEY, text())
@@ -79,7 +80,7 @@ public interface CassandraMailRepositoryModule {
             .addColumn(MailRepositoryTable.STATE, text())
             .addColumn(MailRepositoryTable.HEADER_BLOB_ID, text())
             .addColumn(MailRepositoryTable.BODY_BLOB_ID, text())
-            .addColumn(MailRepositoryTable.ATTRIBUTES, map(text(), blob()))
+            .addColumn(MailRepositoryTable.ATTRIBUTES, map(text(), text()))
             .addColumn(MailRepositoryTable.ERROR_MESSAGE, text())
             .addColumn(MailRepositoryTable.SENDER, text())
             .addColumn(MailRepositoryTable.RECIPIENTS, list(text()))

http://git-wip-us.apache.org/repos/asf/james-project/blob/3b223d53/server/mailrepository/mailrepository-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryMailDAOTest.java
----------------------------------------------------------------------
diff --git 
a/server/mailrepository/mailrepository-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryMailDAOTest.java
 
b/server/mailrepository/mailrepository-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryMailDAOTest.java
index a50c69e..a04b8ed 100644
--- 
a/server/mailrepository/mailrepository-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryMailDAOTest.java
+++ 
b/server/mailrepository/mailrepository-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryMailDAOTest.java
@@ -22,6 +22,8 @@ package org.apache.james.mailrepository.cassandra;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.SoftAssertions.assertSoftly;
 
+import java.util.Collection;
+import java.util.List;
 import java.util.Optional;
 
 import javax.mail.MessagingException;
@@ -32,6 +34,9 @@ import org.apache.james.blob.api.BlobId;
 import org.apache.james.blob.api.TestBlobId;
 import org.apache.james.mailrepository.api.MailKey;
 import org.apache.james.mailrepository.api.MailRepositoryUrl;
+import org.apache.mailet.Attribute;
+import org.apache.mailet.AttributeName;
+import org.apache.mailet.AttributeValue;
 import org.apache.mailet.Mail;
 import org.apache.mailet.PerRecipientHeaders;
 import org.apache.mailet.base.MailAddressFixture;
@@ -57,58 +62,6 @@ class CassandraMailRepositoryMailDAOTest {
         abstract CassandraMailRepositoryMailDaoAPI testee();
 
         @Test
-        void readShouldReturnAllMailMetadata() throws Exception {
-            CassandraMailRepositoryMailDaoAPI testee = testee();
-
-            BlobId blobIdBody = BLOB_ID_FACTORY.from("blobHeader");
-            BlobId blobIdHeader = BLOB_ID_FACTORY.from("blobBody");
-            String errorMessage = "error message";
-            String state = "state";
-            String remoteAddr = "remoteAddr";
-            String remoteHost = "remoteHost";
-            PerRecipientHeaders.Header header = 
PerRecipientHeaders.Header.builder().name("headerName").value("headerValue").build();
-            String attributeName = "att1";
-            ImmutableList<String> attributeValue = ImmutableList.of("value1", 
"value2");
-
-            testee.store(URL,
-                FakeMail.builder()
-                    .name(KEY_1.asString())
-                    .sender(MailAddressFixture.SENDER)
-                    .recipients(MailAddressFixture.RECIPIENT1, 
MailAddressFixture.RECIPIENT2)
-                    .errorMessage(errorMessage)
-                    .state(state)
-                    .remoteAddr(remoteAddr)
-                    .remoteHost(remoteHost)
-                    .addHeaderForRecipient(header, 
MailAddressFixture.RECIPIENT1)
-                    .attribute(attributeName, attributeValue)
-                    .build(),
-                blobIdHeader,
-                blobIdBody)
-                .join();
-
-            CassandraMailRepositoryMailDAO.MailDTO mailDTO = testee.read(URL, 
KEY_1).join().get();
-
-            Mail partialMail = mailDTO.getMailBuilder().build();
-            assertSoftly(softly -> {
-                
softly.assertThat(mailDTO.getBodyBlobId()).isEqualTo(blobIdBody);
-                
softly.assertThat(mailDTO.getHeaderBlobId()).isEqualTo(blobIdHeader);
-                
softly.assertThat(partialMail.getName()).isEqualTo(KEY_1.asString());
-                
softly.assertThat(partialMail.getErrorMessage()).isEqualTo(errorMessage);
-                softly.assertThat(partialMail.getState()).isEqualTo(state);
-                
softly.assertThat(partialMail.getRemoteAddr()).isEqualTo(remoteAddr);
-                
softly.assertThat(partialMail.getRemoteHost()).isEqualTo(remoteHost);
-                
softly.assertThat(partialMail.getAttributeNames()).containsOnly(attributeName);
-                
softly.assertThat(partialMail.getAttribute(attributeName)).isEqualTo(attributeValue);
-                
softly.assertThat(partialMail.getPerRecipientSpecificHeaders().getRecipientsWithSpecificHeaders())
-                    .containsOnly(MailAddressFixture.RECIPIENT1);
-                
softly.assertThat(partialMail.getPerRecipientSpecificHeaders().getHeadersForRecipient(MailAddressFixture.RECIPIENT1))
-                    .containsOnly(header);
-                
softly.assertThat(partialMail.getMaybeSender().asOptional()).contains(MailAddressFixture.SENDER);
-                
softly.assertThat(partialMail.getRecipients()).containsOnly(MailAddressFixture.RECIPIENT1,
 MailAddressFixture.RECIPIENT2);
-            });
-        }
-
-        @Test
         void storeShouldAcceptMailWithOnlyName() throws Exception {
             CassandraMailRepositoryMailDaoAPI testee = testee();
             BlobId blobIdBody = BLOB_ID_FACTORY.from("blobHeader");
@@ -174,6 +127,58 @@ class CassandraMailRepositoryMailDAOTest {
         CassandraMailRepositoryMailDaoAPI testee() {
             return testee;
         }
+
+        @Test
+        void readShouldReturnAllMailMetadata() throws Exception {
+            CassandraMailRepositoryMailDaoAPI testee = testee();
+
+            BlobId blobIdBody = BLOB_ID_FACTORY.from("blobHeader");
+            BlobId blobIdHeader = BLOB_ID_FACTORY.from("blobBody");
+            String errorMessage = "error message";
+            String state = "state";
+            String remoteAddr = "remoteAddr";
+            String remoteHost = "remoteHost";
+            PerRecipientHeaders.Header header = 
PerRecipientHeaders.Header.builder().name("headerName").value("headerValue").build();
+            String attributeName = "att1";
+            ImmutableList<String> attributeValue = ImmutableList.of("value1", 
"value2");
+
+            testee.store(URL,
+                FakeMail.builder()
+                    .name(KEY_1.asString())
+                    .sender(MailAddressFixture.SENDER)
+                    .recipients(MailAddressFixture.RECIPIENT1, 
MailAddressFixture.RECIPIENT2)
+                    .errorMessage(errorMessage)
+                    .state(state)
+                    .remoteAddr(remoteAddr)
+                    .remoteHost(remoteHost)
+                    .addHeaderForRecipient(header, 
MailAddressFixture.RECIPIENT1)
+                    .attribute(attributeName, attributeValue)
+                    .build(),
+                blobIdHeader,
+                blobIdBody)
+                .join();
+
+            CassandraMailRepositoryMailDAO.MailDTO mailDTO = testee.read(URL, 
KEY_1).join().get();
+
+            Mail partialMail = mailDTO.getMailBuilder().build();
+            assertSoftly(softly -> {
+                
softly.assertThat(mailDTO.getBodyBlobId()).isEqualTo(blobIdBody);
+                
softly.assertThat(mailDTO.getHeaderBlobId()).isEqualTo(blobIdHeader);
+                
softly.assertThat(partialMail.getName()).isEqualTo(KEY_1.asString());
+                
softly.assertThat(partialMail.getErrorMessage()).isEqualTo(errorMessage);
+                softly.assertThat(partialMail.getState()).isEqualTo(state);
+                
softly.assertThat(partialMail.getRemoteAddr()).isEqualTo(remoteAddr);
+                
softly.assertThat(partialMail.getRemoteHost()).isEqualTo(remoteHost);
+                
softly.assertThat(partialMail.getAttributeNames()).containsOnly(attributeName);
+                
softly.assertThat(partialMail.getAttribute(attributeName)).isEqualTo(attributeValue);
+                
softly.assertThat(partialMail.getPerRecipientSpecificHeaders().getRecipientsWithSpecificHeaders())
+                    .containsOnly(MailAddressFixture.RECIPIENT1);
+                
softly.assertThat(partialMail.getPerRecipientSpecificHeaders().getHeadersForRecipient(MailAddressFixture.RECIPIENT1))
+                    .containsOnly(header);
+                
softly.assertThat(partialMail.getMaybeSender().asOptional()).contains(MailAddressFixture.SENDER);
+                
softly.assertThat(partialMail.getRecipients()).containsOnly(MailAddressFixture.RECIPIENT1,
 MailAddressFixture.RECIPIENT2);
+            });
+        }
     }
 
     @Nested
@@ -190,6 +195,60 @@ class CassandraMailRepositoryMailDAOTest {
         CassandraMailRepositoryMailDaoAPI testee() {
             return testee;
         }
+
+        @Test
+        void readShouldReturnAllMailMetadata() throws Exception {
+            CassandraMailRepositoryMailDaoAPI testee = testee();
+
+            BlobId blobIdBody = BLOB_ID_FACTORY.from("blobHeader");
+            BlobId blobIdHeader = BLOB_ID_FACTORY.from("blobBody");
+            String errorMessage = "error message";
+            String state = "state";
+            String remoteAddr = "remoteAddr";
+            String remoteHost = "remoteHost";
+            PerRecipientHeaders.Header header = 
PerRecipientHeaders.Header.builder().name("headerName").value("headerValue").build();
+            String attributeName = "att1";
+            List<AttributeValue<?>> attributeValue = 
ImmutableList.of(AttributeValue.of("value1"), AttributeValue.of("value2"));
+            Attribute attribute = new 
Attribute(AttributeName.of(attributeName), AttributeValue.of(attributeValue));
+            List<Attribute> attributes = ImmutableList.of(attribute);
+
+            testee.store(URL,
+                FakeMail.builder()
+                    .name(KEY_1.asString())
+                    .sender(MailAddressFixture.SENDER)
+                    .recipients(MailAddressFixture.RECIPIENT1, 
MailAddressFixture.RECIPIENT2)
+                    .errorMessage(errorMessage)
+                    .state(state)
+                    .remoteAddr(remoteAddr)
+                    .remoteHost(remoteHost)
+                    .addHeaderForRecipient(header, 
MailAddressFixture.RECIPIENT1)
+                    .attributes(attributes)
+                    .build(),
+                blobIdHeader,
+                blobIdBody)
+                .join();
+
+            CassandraMailRepositoryMailDAO.MailDTO mailDTO = testee.read(URL, 
KEY_1).join().get();
+
+            Mail partialMail = mailDTO.getMailBuilder().build();
+            assertSoftly(softly -> {
+                
softly.assertThat(mailDTO.getBodyBlobId()).isEqualTo(blobIdBody);
+                
softly.assertThat(mailDTO.getHeaderBlobId()).isEqualTo(blobIdHeader);
+                
softly.assertThat(partialMail.getName()).isEqualTo(KEY_1.asString());
+                
softly.assertThat(partialMail.getErrorMessage()).isEqualTo(errorMessage);
+                softly.assertThat(partialMail.getState()).isEqualTo(state);
+                
softly.assertThat(partialMail.getRemoteAddr()).isEqualTo(remoteAddr);
+                
softly.assertThat(partialMail.getRemoteHost()).isEqualTo(remoteHost);
+                
softly.assertThat(partialMail.getAttributeNames()).containsOnly(attributeName);
+                
softly.assertThat(partialMail.getAttribute(AttributeName.of(attributeName))).contains(attribute);
+                
softly.assertThat(partialMail.getPerRecipientSpecificHeaders().getRecipientsWithSpecificHeaders())
+                    .containsOnly(MailAddressFixture.RECIPIENT1);
+                
softly.assertThat(partialMail.getPerRecipientSpecificHeaders().getHeadersForRecipient(MailAddressFixture.RECIPIENT1))
+                    .containsOnly(header);
+                
softly.assertThat(partialMail.getMaybeSender().asOptional()).contains(MailAddressFixture.SENDER);
+                
softly.assertThat(partialMail.getRecipients()).containsOnly(MailAddressFixture.RECIPIENT1,
 MailAddressFixture.RECIPIENT2);
+            });
+        }
     }
 
     @Nested


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to