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 2018/01/19 02:19:25 UTC

[01/13] james-project git commit: JAMES-2310 explicitly use LineBasedFrameDecoder in LineDelimiterBasedChannelHandlerFactory

Repository: james-project
Updated Branches:
  refs/heads/master 4247d887d -> ea12b94b5


JAMES-2310 explicitly use LineBasedFrameDecoder in LineDelimiterBasedChannelHandlerFactory


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

Branch: refs/heads/master
Commit: c668025c1456d29f8445ba98e1db4ccdc989a1a2
Parents: a2b0345
Author: TzeKei Lee <ch...@gmail.com>
Authored: Wed Jan 17 17:07:24 2018 +0800
Committer: benwa <bt...@linagora.com>
Committed: Fri Jan 19 09:04:31 2018 +0700

----------------------------------------------------------------------
 .../netty/LineDelimiterBasedChannelHandlerFactory.java         | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/c668025c/protocols/netty/src/main/java/org/apache/james/protocols/netty/LineDelimiterBasedChannelHandlerFactory.java
----------------------------------------------------------------------
diff --git a/protocols/netty/src/main/java/org/apache/james/protocols/netty/LineDelimiterBasedChannelHandlerFactory.java b/protocols/netty/src/main/java/org/apache/james/protocols/netty/LineDelimiterBasedChannelHandlerFactory.java
index 63e39b5..ca3ead7 100644
--- a/protocols/netty/src/main/java/org/apache/james/protocols/netty/LineDelimiterBasedChannelHandlerFactory.java
+++ b/protocols/netty/src/main/java/org/apache/james/protocols/netty/LineDelimiterBasedChannelHandlerFactory.java
@@ -20,10 +20,10 @@ package org.apache.james.protocols.netty;
 
 import org.jboss.netty.channel.ChannelHandler;
 import org.jboss.netty.channel.ChannelPipeline;
-import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
-import org.jboss.netty.handler.codec.frame.Delimiters;
+import org.jboss.netty.handler.codec.frame.LineBasedFrameDecoder;
 
 public class LineDelimiterBasedChannelHandlerFactory implements ChannelHandlerFactory {
+    private static final Boolean FAIL_FAST = true;
     private final int maxLineLength;
 
     public LineDelimiterBasedChannelHandlerFactory(int maxLineLength) {
@@ -32,7 +32,7 @@ public class LineDelimiterBasedChannelHandlerFactory implements ChannelHandlerFa
 
     @Override
     public ChannelHandler create(ChannelPipeline pipeline) {
-        return new DelimiterBasedFrameDecoder(maxLineLength, false, Delimiters.lineDelimiter());
+        return new LineBasedFrameDecoder(maxLineLength, false, !FAIL_FAST);
     }
 
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[08/13] james-project git commit: JAMES-2287 Cassandra ObjectStore implementation

Posted by bt...@apache.org.
JAMES-2287 Cassandra ObjectStore implementation


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

Branch: refs/heads/master
Commit: 4e8bcc66db98fa52328efbc4d5e070140702f1d5
Parents: 12074ca
Author: Antoine Duprat <ad...@linagora.com>
Authored: Tue Jan 16 13:09:53 2018 +0100
Committer: benwa <bt...@linagora.com>
Committed: Fri Jan 19 09:07:27 2018 +0700

----------------------------------------------------------------------
 mailbox/cassandra/pom.xml                       |  26 ++-
 .../CassandraMailboxSessionMapperFactory.java   |   2 +-
 .../mail/CassandraAttachmentDAOV2.java          |   9 +-
 .../mail/CassandraAttachmentMapper.java         |   1 +
 .../cassandra/mail/CassandraBlobsDAO.java       | 208 ------------------
 .../cassandra/mail/CassandraMessageDAO.java     |   6 +-
 .../mail/migration/AttachmentV2Migration.java   |   2 +-
 .../cassandra/mail/utils/DataChunker.java       |  52 -----
 .../cassandra/modules/CassandraBlobModule.java  |  69 ------
 .../mailbox/cassandra/table/BlobTable.java      |  32 ---
 .../CassandraCombinationManagerTest.java        |   2 +-
 .../CassandraMailboxManagerStressTest.java      |   2 +-
 .../cassandra/CassandraMailboxManagerTest.java  |   2 +-
 .../CassandraMessageIdManagerQuotaTest.java     |   2 +-
 ...CassandraMessageIdManagerSideEffectTest.java |   2 +-
 .../CassandraMessageIdManagerStorageTest.java   |   2 +-
 .../CassandraSubscriptionManagerTest.java       |   2 +-
 ...estCassandraMailboxSessionMapperFactory.java |   2 +-
 .../mail/CassandraAnnotationMapperTest.java     |   2 +-
 .../mail/CassandraAttachmentFallbackTest.java   |  11 +-
 .../mail/CassandraAttachmentMapperTest.java     |   2 +-
 .../cassandra/mail/CassandraBlobsDAOTest.java   | 132 ------------
 .../mail/CassandraGenericMailboxMapperTest.java |   2 +-
 .../CassandraMailboxManagerAttachmentTest.java  |   2 +-
 .../mail/CassandraMailboxMapperAclTest.java     |   2 +-
 .../cassandra/mail/CassandraMessageDAOTest.java |   3 +-
 .../mail/CassandraMessageIdMapperTest.java      |   2 +-
 .../mail/CassandraMessageMapperTest.java        |   2 +-
 .../mail/CassandraMessageMoveTest.java          |   2 +-
 ...assandraMessageWithAttachmentMapperTest.java |   2 +-
 .../AttachmentMessageIdCreationTest.java        |   4 +-
 .../migration/AttachmentV2MigrationTest.java    |   4 +-
 .../cassandra/mail/utils/DataChunkerTest.java   | 117 -----------
 .../cassandra/host/CassandraHostSystem.java     |   2 +-
 server/blob/blob-cassandra/pom.xml              |  20 ++
 .../apache/james/blob/cassandra/BlobTable.java  |  32 +++
 .../blob/cassandra/CassandraBlobModule.java     |  68 ++++++
 .../james/blob/cassandra/CassandraBlobsDAO.java | 210 +++++++++++++++++++
 .../james/blob/cassandra/utils/DataChunker.java |  52 +++++
 .../blob/cassandra/CassandraBlobsDAOTest.java   |  86 ++++++++
 .../blob/cassandra/utils/DataChunkerTest.java   | 110 ++++++++++
 .../modules/mailbox/CassandraMailboxModule.java |   4 +-
 42 files changed, 643 insertions(+), 653 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/pom.xml
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/pom.xml b/mailbox/cassandra/pom.xml
index 4377f83..0826db3 100644
--- a/mailbox/cassandra/pom.xml
+++ b/mailbox/cassandra/pom.xml
@@ -68,6 +68,12 @@
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
+            <artifactId>james-server-data-api</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
             <artifactId>james-server-task</artifactId>
         </dependency>
         <dependency>
@@ -106,11 +112,6 @@
             <artifactId>javax.inject</artifactId>
         </dependency>
         <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
             <groupId>net.javacrumbs.json-unit</groupId>
             <artifactId>json-unit</artifactId>
             <version>1.5.5</version>
@@ -142,6 +143,21 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.platform</groupId>
+            <artifactId>junit-platform-launcher</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.vintage</groupId>
+            <artifactId>junit-vintage-engine</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>org.mockito</groupId>
             <artifactId>mockito-core</artifactId>
             <scope>test</scope>

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
index 47b8bf1..3969700 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
@@ -23,6 +23,7 @@ import javax.inject.Inject;
 
 import org.apache.james.backends.cassandra.init.CassandraConfiguration;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
+import org.apache.james.blob.cassandra.CassandraBlobsDAO;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.cassandra.mail.CassandraACLMapper;
 import org.apache.james.mailbox.cassandra.mail.CassandraAnnotationMapper;
@@ -32,7 +33,6 @@ import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAOV2;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentMapper;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentMessageIdDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentOwnerDAO;
-import org.apache.james.mailbox.cassandra.mail.CassandraBlobsDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraDeletedMessageDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraFirstUnseenDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraIndexTableHandler;

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2.java
index 5a9727a..8a40ef8 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2.java
@@ -38,6 +38,7 @@ import java.util.concurrent.CompletableFuture;
 import javax.inject.Inject;
 
 import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor;
+import org.apache.james.blob.api.BlobId;
 import org.apache.james.blob.cassandra.CassandraBlobId;
 import org.apache.james.mailbox.model.Attachment;
 import org.apache.james.mailbox.model.AttachmentId;
@@ -50,11 +51,11 @@ import com.google.common.base.Preconditions;
 public class CassandraAttachmentDAOV2 {
     public static class DAOAttachment {
         private final AttachmentId attachmentId;
-        private final CassandraBlobId blobId;
+        private final BlobId blobId;
         private final String type;
         private final long size;
 
-        private DAOAttachment(AttachmentId attachmentId, CassandraBlobId blobId, String type, long size) {
+        private DAOAttachment(AttachmentId attachmentId, BlobId blobId, String type, long size) {
             this.attachmentId = attachmentId;
             this.blobId = blobId;
             this.type = type;
@@ -65,7 +66,7 @@ public class CassandraAttachmentDAOV2 {
             return attachmentId;
         }
 
-        public CassandraBlobId getBlobId() {
+        public BlobId getBlobId() {
             return blobId;
         }
 
@@ -104,7 +105,7 @@ public class CassandraAttachmentDAOV2 {
         }
     }
 
-    public static DAOAttachment from(Attachment attachment, CassandraBlobId blobId) {
+    public static DAOAttachment from(Attachment attachment, BlobId blobId) {
         return new DAOAttachment(
             attachment.getAttachmentId(),
             blobId,

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java
index 1eccb88..d9a282f 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java
@@ -28,6 +28,7 @@ import java.util.stream.Stream;
 
 import javax.inject.Inject;
 
+import org.apache.james.blob.cassandra.CassandraBlobsDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAOV2.DAOAttachment;
 import org.apache.james.mailbox.exception.AttachmentNotFoundException;
 import org.apache.james.mailbox.exception.MailboxException;

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraBlobsDAO.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraBlobsDAO.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraBlobsDAO.java
deleted file mode 100644
index 5fc09aa..0000000
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraBlobsDAO.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.mailbox.cassandra.mail;
-
-import static com.datastax.driver.core.querybuilder.QueryBuilder.bindMarker;
-import static com.datastax.driver.core.querybuilder.QueryBuilder.eq;
-import static com.datastax.driver.core.querybuilder.QueryBuilder.insertInto;
-import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
-
-import java.nio.ByteBuffer;
-import java.util.Optional;
-import java.util.concurrent.CompletableFuture;
-import java.util.stream.IntStream;
-import java.util.stream.Stream;
-
-import javax.inject.Inject;
-
-import org.apache.commons.lang3.tuple.Pair;
-import org.apache.james.backends.cassandra.init.CassandraConfiguration;
-import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor;
-import org.apache.james.blob.cassandra.CassandraBlobId;
-import org.apache.james.mailbox.cassandra.mail.utils.DataChunker;
-import org.apache.james.mailbox.cassandra.table.BlobTable;
-import org.apache.james.mailbox.cassandra.table.BlobTable.BlobParts;
-import org.apache.james.util.FluentFutureStream;
-import org.apache.james.util.OptionalUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.datastax.driver.core.PreparedStatement;
-import com.datastax.driver.core.Row;
-import com.datastax.driver.core.Session;
-import com.github.steveash.guavate.Guavate;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.primitives.Bytes;
-
-public class CassandraBlobsDAO {
-    private static final Logger LOGGER = LoggerFactory.getLogger(CassandraBlobsDAO.class);
-    private final CassandraAsyncExecutor cassandraAsyncExecutor;
-    private final PreparedStatement insert;
-    private final PreparedStatement insertPart;
-    private final PreparedStatement select;
-    private final PreparedStatement selectPart;
-    private final DataChunker dataChunker;
-    private final CassandraConfiguration configuration;
-
-    @Inject
-    public CassandraBlobsDAO(Session session, CassandraConfiguration cassandraConfiguration) {
-        this.cassandraAsyncExecutor = new CassandraAsyncExecutor(session);
-        this.configuration = cassandraConfiguration;
-        this.dataChunker = new DataChunker();
-        this.insert = prepareInsert(session);
-        this.select = prepareSelect(session);
-
-        this.insertPart = prepareInsertPart(session);
-        this.selectPart = prepareSelectPart(session);
-    }
-
-    @VisibleForTesting
-    public CassandraBlobsDAO(Session session) {
-        this(session, CassandraConfiguration.DEFAULT_CONFIGURATION);
-    }
-
-    private PreparedStatement prepareSelect(Session session) {
-        return session.prepare(select()
-            .from(BlobTable.TABLE_NAME)
-            .where(eq(BlobTable.ID, bindMarker(BlobTable.ID))));
-    }
-
-    private PreparedStatement prepareSelectPart(Session session) {
-        return session.prepare(select()
-            .from(BlobParts.TABLE_NAME)
-            .where(eq(BlobTable.ID, bindMarker(BlobTable.ID)))
-            .and(eq(BlobParts.CHUNK_NUMBER, bindMarker(BlobParts.CHUNK_NUMBER))));
-    }
-
-    private PreparedStatement prepareInsert(Session session) {
-        return session.prepare(insertInto(BlobTable.TABLE_NAME)
-            .value(BlobTable.ID, bindMarker(BlobTable.ID))
-            .value(BlobTable.NUMBER_OF_CHUNK, bindMarker(BlobTable.NUMBER_OF_CHUNK)));
-    }
-
-    private PreparedStatement prepareInsertPart(Session session) {
-        return session.prepare(insertInto(BlobParts.TABLE_NAME)
-            .value(BlobTable.ID, bindMarker(BlobTable.ID))
-            .value(BlobParts.CHUNK_NUMBER, bindMarker(BlobParts.CHUNK_NUMBER))
-            .value(BlobParts.DATA, bindMarker(BlobParts.DATA)));
-    }
-
-    public CompletableFuture<CassandraBlobId> save(byte[] data) {
-        Preconditions.checkNotNull(data);
-
-        CassandraBlobId blobId = CassandraBlobId.forPayload(data);
-        return saveBlobParts(data, blobId)
-            .thenCompose(numberOfChunk -> saveBlobPartsReferences(blobId, numberOfChunk))
-            .thenApply(any -> blobId);
-    }
-
-    private CompletableFuture<Integer> saveBlobParts(byte[] data, CassandraBlobId blobId) {
-        return FluentFutureStream.of(
-            dataChunker.chunk(data, configuration.getBlobPartSize())
-                .map(pair -> writePart(pair.getRight(), blobId, pair.getKey())
-                    .thenApply(partId -> Pair.of(pair.getKey(), partId))))
-            .completableFuture()
-            .thenApply(stream ->
-                getLastOfStream(stream)
-                    .map(numOfChunkAndPartId -> numOfChunkAndPartId.getLeft() + 1)
-                    .orElse(0));
-    }
-
-    private static <T> Optional<T> getLastOfStream(Stream<T> stream) {
-        return stream.reduce((first, second) -> second);
-    }
-
-    private CompletableFuture<Void> writePart(ByteBuffer data, CassandraBlobId blobId, int position) {
-        return cassandraAsyncExecutor.executeVoid(
-            insertPart.bind()
-                .setString(BlobTable.ID, blobId.asString())
-                .setInt(BlobParts.CHUNK_NUMBER, position)
-                .setBytes(BlobParts.DATA, data));
-    }
-
-    private CompletableFuture<Void> saveBlobPartsReferences(CassandraBlobId blobId, int numberOfChunk) {
-        return cassandraAsyncExecutor.executeVoid(insert.bind()
-            .setString(BlobTable.ID, blobId.asString())
-            .setInt(BlobTable.NUMBER_OF_CHUNK, numberOfChunk));
-    }
-
-    public CompletableFuture<byte[]> read(CassandraBlobId blobId) {
-        return cassandraAsyncExecutor.executeSingleRow(
-            select.bind()
-                .setString(BlobTable.ID, blobId.asString()))
-            .thenCompose(row -> toDataParts(row, blobId))
-            .thenApply(this::concatenateDataParts);
-    }
-
-    private CompletableFuture<Stream<BlobPart>> toDataParts(Optional<Row> blobRowOptional, CassandraBlobId blobId) {
-        return blobRowOptional.map(blobRow -> {
-            int numOfChunk = blobRow.getInt(BlobTable.NUMBER_OF_CHUNK);
-            return FluentFutureStream.of(
-                IntStream.range(0, numOfChunk)
-                    .mapToObj(position -> readPart(blobId, position)))
-                .completableFuture();
-        }).orElseGet(() -> {
-            LOGGER.warn("Could not retrieve blob metadata for {}", blobId);
-            return CompletableFuture.completedFuture(Stream.empty());
-        });
-    }
-
-    private byte[] concatenateDataParts(Stream<BlobPart> blobParts) {
-        ImmutableList<byte[]> parts = blobParts
-            .map(blobPart -> OptionalUtils.executeIfEmpty(
-                blobPart.row,
-                () -> LOGGER.warn("Missing blob part for blobId {} and position {}", blobPart.blobId, blobPart.position)))
-            .flatMap(OptionalUtils::toStream)
-            .map(this::rowToData)
-            .collect(Guavate.toImmutableList());
-
-        return Bytes.concat(parts.toArray(new byte[parts.size()][]));
-    }
-
-    private byte[] rowToData(Row row) {
-        byte[] data = new byte[row.getBytes(BlobParts.DATA).remaining()];
-        row.getBytes(BlobParts.DATA).get(data);
-        return data;
-    }
-
-    private CompletableFuture<BlobPart> readPart(CassandraBlobId blobId, int position) {
-        return cassandraAsyncExecutor.executeSingleRow(
-            selectPart.bind()
-                .setString(BlobTable.ID, blobId.asString())
-                .setInt(BlobParts.CHUNK_NUMBER, position))
-            .thenApply(row -> new BlobPart(blobId, position, row));
-    }
-
-    private static class BlobPart {
-        private final CassandraBlobId blobId;
-        private final int position;
-        private final Optional<Row> row;
-
-        public BlobPart(CassandraBlobId blobId, int position, Optional<Row> row) {
-            Preconditions.checkNotNull(blobId);
-            Preconditions.checkArgument(position >= 0, "position need to be positive");
-            this.blobId = blobId;
-            this.position = position;
-            this.row = row;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java
index c80f982..72fe82e 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java
@@ -59,7 +59,9 @@ import org.apache.james.backends.cassandra.init.CassandraConfiguration;
 import org.apache.james.backends.cassandra.init.CassandraTypesProvider;
 import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
+import org.apache.james.blob.api.BlobId;
 import org.apache.james.blob.cassandra.CassandraBlobId;
+import org.apache.james.blob.cassandra.CassandraBlobsDAO;
 import org.apache.james.mailbox.cassandra.ids.CassandraMessageId;
 import org.apache.james.mailbox.cassandra.mail.utils.Limit;
 import org.apache.james.mailbox.cassandra.table.CassandraMessageV2Table;
@@ -176,7 +178,7 @@ public class CassandraMessageDAO {
             cassandraAsyncExecutor.executeVoid(boundWriteStatement(message, pair)));
     }
 
-    private CompletableFuture<Pair<CassandraBlobId, CassandraBlobId>> saveContent(MailboxMessage message) throws MailboxException {
+    private CompletableFuture<Pair<BlobId, BlobId>> saveContent(MailboxMessage message) throws MailboxException {
         try {
             return CompletableFutureUtil.combine(
                 blobsDAO.save(
@@ -191,7 +193,7 @@ public class CassandraMessageDAO {
         }
     }
 
-    private BoundStatement boundWriteStatement(MailboxMessage message, Pair<CassandraBlobId, CassandraBlobId> pair) {
+    private BoundStatement boundWriteStatement(MailboxMessage message, Pair<BlobId, BlobId> pair) {
         CassandraMessageId messageId = (CassandraMessageId) message.getMessageId();
         return insert.bind()
             .setUUID(MESSAGE_ID, messageId.get())

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2Migration.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2Migration.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2Migration.java
index 0d33e36..651b381 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2Migration.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2Migration.java
@@ -22,9 +22,9 @@ package org.apache.james.mailbox.cassandra.mail.migration;
 import javax.inject.Inject;
 
 import org.apache.james.backends.cassandra.migration.Migration;
+import org.apache.james.blob.cassandra.CassandraBlobsDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAOV2;
-import org.apache.james.mailbox.cassandra.mail.CassandraBlobsDAO;
 import org.apache.james.mailbox.model.Attachment;
 import org.apache.james.task.Task;
 import org.slf4j.Logger;

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/utils/DataChunker.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/utils/DataChunker.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/utils/DataChunker.java
deleted file mode 100644
index 57e0bfc..0000000
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/utils/DataChunker.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.mailbox.cassandra.mail.utils;
-
-import java.nio.ByteBuffer;
-import java.util.stream.IntStream;
-import java.util.stream.Stream;
-
-import org.apache.commons.lang3.tuple.Pair;
-
-import com.google.common.base.Preconditions;
-
-public class DataChunker {
-
-    public Stream<Pair<Integer, ByteBuffer>> chunk(byte[] data, int chunkSize) {
-        Preconditions.checkNotNull(data);
-        Preconditions.checkArgument(chunkSize > 0, "ChunkSize can not be negative");
-
-        int size = data.length;
-        int fullChunkCount = size / chunkSize;
-
-        return Stream.concat(
-            IntStream.range(0, fullChunkCount)
-                .mapToObj(i -> Pair.of(i, ByteBuffer.wrap(data, i * chunkSize, chunkSize))),
-            lastChunk(data, chunkSize * fullChunkCount, fullChunkCount));
-    }
-
-    private Stream<Pair<Integer, ByteBuffer>> lastChunk(byte[] data, int offset, int index) {
-        if (offset == data.length && index > 0) {
-            return Stream.empty();
-        }
-        return Stream.of(Pair.of(index, ByteBuffer.wrap(data, offset, data.length - offset)));
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraBlobModule.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraBlobModule.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraBlobModule.java
deleted file mode 100644
index b672e34..0000000
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraBlobModule.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.mailbox.cassandra.modules;
-
-import java.util.List;
-
-import org.apache.james.backends.cassandra.components.CassandraModule;
-import org.apache.james.backends.cassandra.components.CassandraTable;
-import org.apache.james.backends.cassandra.components.CassandraType;
-import org.apache.james.mailbox.cassandra.table.BlobTable;
-
-import com.datastax.driver.core.DataType;
-import com.datastax.driver.core.schemabuilder.SchemaBuilder;
-import com.google.common.collect.ImmutableList;
-
-public class CassandraBlobModule implements CassandraModule {
-
-    private final List<CassandraTable> tables;
-    private final List<CassandraType> types;
-
-    public CassandraBlobModule() {
-        tables = ImmutableList.of(
-            new CassandraTable(BlobTable.TABLE_NAME,
-                SchemaBuilder.createTable(BlobTable.TABLE_NAME)
-                    .ifNotExists()
-                    .addPartitionKey(BlobTable.ID, DataType.text())
-                    .addClusteringColumn(BlobTable.NUMBER_OF_CHUNK, DataType.cint())
-                    .withOptions()
-                    .comment("Holds information for retrieving all blob parts composing this blob. " +
-                        "Messages` headers and bodies are stored as blobparts.")),
-            new CassandraTable(BlobTable.BlobParts.TABLE_NAME,
-                SchemaBuilder.createTable(BlobTable.BlobParts.TABLE_NAME)
-                    .ifNotExists()
-                    .addPartitionKey(BlobTable.ID, DataType.text())
-                    .addClusteringColumn(BlobTable.BlobParts.CHUNK_NUMBER, DataType.cint())
-                    .addColumn(BlobTable.BlobParts.DATA, DataType.blob())
-                    .withOptions()
-                    .comment("Holds blob parts composing blobs ." +
-                        "Messages` headers and bodies are stored, chunked in blobparts.")));
-        types = ImmutableList.of();
-    }
-
-    @Override
-    public List<CassandraTable> moduleTables() {
-        return tables;
-    }
-
-    @Override
-    public List<CassandraType> moduleTypes() {
-        return types;
-    }
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/BlobTable.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/BlobTable.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/BlobTable.java
deleted file mode 100644
index 1c0b0e9..0000000
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/BlobTable.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.mailbox.cassandra.table;
-
-public interface BlobTable {
-    String TABLE_NAME = "blobs";
-    String ID = "id";
-    String NUMBER_OF_CHUNK = "position";
-
-    interface BlobParts {
-        String TABLE_NAME = "blobParts";
-        String CHUNK_NUMBER = "chunkNumber";
-        String DATA = "data";
-    }
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraCombinationManagerTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraCombinationManagerTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraCombinationManagerTest.java
index bf341fe..7ac4e73 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraCombinationManagerTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraCombinationManagerTest.java
@@ -24,12 +24,12 @@ import static org.mockito.Mockito.mock;
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
 import org.apache.james.mailbox.MailboxListener;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule;
-import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraDeletedMessageModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraFirstUnseenModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule;

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerStressTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerStressTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerStressTest.java
index c8f0092..b460538 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerStressTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerStressTest.java
@@ -22,13 +22,13 @@ package org.apache.james.mailbox.cassandra;
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxManagerStressTest;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule;
-import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraDeletedMessageModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraFirstUnseenModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule;

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java
index 13da244..cba1f6e 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java
@@ -21,13 +21,13 @@ package org.apache.james.mailbox.cassandra;
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxManagerTest;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule;
-import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraDeletedMessageModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraFirstUnseenModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule;

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerQuotaTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerQuotaTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerQuotaTest.java
index 15384f5..9d18c8e 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerQuotaTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerQuotaTest.java
@@ -22,11 +22,11 @@ package org.apache.james.mailbox.cassandra;
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule;
-import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraDeletedMessageModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraFirstUnseenModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule;

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerSideEffectTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerSideEffectTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerSideEffectTest.java
index 14877ed..24e64c2 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerSideEffectTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerSideEffectTest.java
@@ -22,11 +22,11 @@ package org.apache.james.mailbox.cassandra;
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule;
-import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraDeletedMessageModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraFirstUnseenModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule;

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerStorageTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerStorageTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerStorageTest.java
index 2132688..bd83a42 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerStorageTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerStorageTest.java
@@ -25,12 +25,12 @@ import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.ContainerLifecycleConfiguration;
 import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
 import org.apache.james.mailbox.MailboxListener;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule;
-import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraDeletedMessageModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraFirstUnseenModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule;

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManagerTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManagerTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManagerTest.java
index 3736666..c55cc11 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManagerTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManagerTest.java
@@ -24,6 +24,7 @@ import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.init.CassandraConfiguration;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
+import org.apache.james.blob.cassandra.CassandraBlobsDAO;
 import org.apache.james.mailbox.AbstractSubscriptionManagerTest;
 import org.apache.james.mailbox.SubscriptionManager;
 import org.apache.james.mailbox.cassandra.mail.CassandraACLMapper;
@@ -32,7 +33,6 @@ import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAOV2;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentMessageIdDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentOwnerDAO;
-import org.apache.james.mailbox.cassandra.mail.CassandraBlobsDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraDeletedMessageDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraFirstUnseenDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraMailboxCounterDAO;

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/TestCassandraMailboxSessionMapperFactory.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/TestCassandraMailboxSessionMapperFactory.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/TestCassandraMailboxSessionMapperFactory.java
index cbf4d0f..a6d854c 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/TestCassandraMailboxSessionMapperFactory.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/TestCassandraMailboxSessionMapperFactory.java
@@ -22,6 +22,7 @@ package org.apache.james.mailbox.cassandra;
 import org.apache.james.backends.cassandra.init.CassandraConfiguration;
 import org.apache.james.backends.cassandra.init.CassandraTypesProvider;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
+import org.apache.james.blob.cassandra.CassandraBlobsDAO;
 import org.apache.james.mailbox.cassandra.ids.CassandraMessageId;
 import org.apache.james.mailbox.cassandra.mail.CassandraACLMapper;
 import org.apache.james.mailbox.cassandra.mail.CassandraApplicableFlagDAO;
@@ -29,7 +30,6 @@ import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAOV2;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentMessageIdDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentOwnerDAO;
-import org.apache.james.mailbox.cassandra.mail.CassandraBlobsDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraDeletedMessageDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraFirstUnseenDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraMailboxCounterDAO;

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAnnotationMapperTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAnnotationMapperTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAnnotationMapperTest.java
index 7e4e320..ec23ad8 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAnnotationMapperTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAnnotationMapperTest.java
@@ -22,11 +22,11 @@ package org.apache.james.mailbox.cassandra.mail;
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule;
-import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraDeletedMessageModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraFirstUnseenModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule;

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentFallbackTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentFallbackTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentFallbackTest.java
index 4c42a2d..0658b1a 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentFallbackTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentFallbackTest.java
@@ -29,10 +29,11 @@ import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.init.CassandraConfiguration;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
-import org.apache.james.blob.cassandra.CassandraBlobId;
+import org.apache.james.blob.api.BlobId;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
+import org.apache.james.blob.cassandra.CassandraBlobsDAO;
 import org.apache.james.mailbox.cassandra.ids.CassandraMessageId;
 import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule;
-import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule;
 import org.apache.james.mailbox.exception.AttachmentNotFoundException;
 import org.apache.james.mailbox.model.Attachment;
 import org.apache.james.mailbox.model.AttachmentId;
@@ -108,7 +109,7 @@ public class CassandraAttachmentFallbackTest {
             .bytes("{\"property\":`\"different\"}".getBytes(StandardCharsets.UTF_8))
             .build();
 
-        CassandraBlobId blobId = blobsDAO.save(attachment.getBytes()).join();
+        BlobId blobId = blobsDAO.save(attachment.getBytes()).join();
         attachmentDAOV2.storeAttachment(CassandraAttachmentDAOV2.from(attachment, blobId)).join();
         attachmentDAO.storeAttachment(otherAttachment).join();
 
@@ -143,7 +144,7 @@ public class CassandraAttachmentFallbackTest {
             .bytes("{\"property\":`\"different\"}".getBytes(StandardCharsets.UTF_8))
             .build();
 
-        CassandraBlobId blobId = blobsDAO.save(attachment.getBytes()).join();
+        BlobId blobId = blobsDAO.save(attachment.getBytes()).join();
         attachmentDAOV2.storeAttachment(CassandraAttachmentDAOV2.from(attachment, blobId)).join();
         attachmentDAO.storeAttachment(otherAttachment).join();
 
@@ -178,7 +179,7 @@ public class CassandraAttachmentFallbackTest {
             .bytes("{\"property\":`\"different\"}".getBytes(StandardCharsets.UTF_8))
             .build();
 
-        CassandraBlobId blobId = blobsDAO.save(attachment.getBytes()).join();
+        BlobId blobId = blobsDAO.save(attachment.getBytes()).join();
         attachmentDAOV2.storeAttachment(CassandraAttachmentDAOV2.from(attachment, blobId)).join();
         attachmentDAO.storeAttachment(otherAttachment).join();
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapperTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapperTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapperTest.java
index 85acca5..9325241 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapperTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapperTest.java
@@ -22,12 +22,12 @@ package org.apache.james.mailbox.cassandra.mail;
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.ids.CassandraMessageId;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule;
-import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraDeletedMessageModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraFirstUnseenModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule;

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraBlobsDAOTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraBlobsDAOTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraBlobsDAOTest.java
deleted file mode 100644
index e92316a..0000000
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraBlobsDAOTest.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.mailbox.cassandra.mail;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-
-import org.apache.james.backends.cassandra.CassandraCluster;
-import org.apache.james.backends.cassandra.DockerCassandraRule;
-import org.apache.james.backends.cassandra.init.CassandraConfiguration;
-import org.apache.james.blob.cassandra.CassandraBlobId;
-import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
-
-import com.google.common.base.Strings;
-
-public class CassandraBlobsDAOTest {
-    private static final int CHUNK_SIZE = 1024;
-    private static final int MULTIPLE_CHUNK_SIZE = 3;
-
-    @ClassRule public static DockerCassandraRule cassandraServer = new DockerCassandraRule();
-    
-    private CassandraCluster cassandra;
-    private CassandraBlobsDAO testee;
-
-    @Before
-    public void setUp() {
-        cassandra = CassandraCluster.create(
-                new CassandraBlobModule(), cassandraServer.getIp(), cassandraServer.getBindingPort());
-        
-        testee = new CassandraBlobsDAO(cassandra.getConf(),
-            CassandraConfiguration.builder()
-                .blobPartSize(CHUNK_SIZE)
-                .build());
-    }
-
-    @After
-    public void tearDown() {
-        cassandra.close();
-    }
-
-    @Test
-    public void saveShouldReturnEmptyWhenNullData() throws Exception {
-        assertThatThrownBy(() -> testee.save(null))
-            .isInstanceOf(NullPointerException.class);
-    }
-
-    @Test
-    public void saveShouldSaveEmptyData() throws Exception {
-        CassandraBlobId blobId = testee.save(new byte[]{}).join();
-
-        byte[] bytes = testee.read(blobId).join();
-
-        assertThat(new String(bytes, StandardCharsets.UTF_8)).isEmpty();
-    }
-
-    @Test
-    public void saveShouldSaveBlankData() throws Exception {
-        CassandraBlobId blobId = testee.save("".getBytes(StandardCharsets.UTF_8)).join();
-
-        byte[] bytes = testee.read(blobId).join();
-
-        assertThat(new String(bytes, StandardCharsets.UTF_8)).isEmpty();
-    }
-
-    @Test
-    public void saveShouldReturnBlobId() throws Exception {
-        CassandraBlobId blobId = testee.save("toto".getBytes(StandardCharsets.UTF_8)).join();
-
-        assertThat(blobId).isEqualTo(CassandraBlobId.from("31f7a65e315586ac198bd798b6629ce4903d0899476d5741a9f32e2e521b6a66"));
-    }
-
-    @Test
-    public void readShouldBeEmptyWhenNoExisting() throws IOException {
-        byte[] bytes = testee.read(CassandraBlobId.from("unknown")).join();
-
-        assertThat(bytes).isEmpty();
-    }
-
-    @Test
-    public void readShouldReturnSavedData() throws IOException {
-        CassandraBlobId blobId = testee.save("toto".getBytes(StandardCharsets.UTF_8)).join();
-
-        byte[] bytes = testee.read(blobId).join();
-
-        assertThat(new String(bytes, StandardCharsets.UTF_8)).isEqualTo("toto");
-    }
-
-    @Test
-    public void readShouldReturnLongSavedData() throws IOException {
-        String longString = Strings.repeat("0123456789\n", 1000);
-        CassandraBlobId blobId = testee.save(longString.getBytes(StandardCharsets.UTF_8)).join();
-
-        byte[] bytes = testee.read(blobId).join();
-
-        assertThat(new String(bytes, StandardCharsets.UTF_8)).isEqualTo(longString);
-    }
-
-    @Test
-    public void readShouldReturnSplitSavedDataByChunk() throws IOException {
-        String longString = Strings.repeat("0123456789\n", MULTIPLE_CHUNK_SIZE);
-        CassandraBlobId blobId = testee.save(longString.getBytes(StandardCharsets.UTF_8)).join();
-
-        byte[] bytes = testee.read(blobId).join();
-
-        assertThat(new String(bytes, StandardCharsets.UTF_8)).isEqualTo(longString);
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraGenericMailboxMapperTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraGenericMailboxMapperTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraGenericMailboxMapperTest.java
index 24eaff9..836768b 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraGenericMailboxMapperTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraGenericMailboxMapperTest.java
@@ -22,11 +22,11 @@ package org.apache.james.mailbox.cassandra.mail;
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule;
-import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraDeletedMessageModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraFirstUnseenModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule;

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxManagerAttachmentTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxManagerAttachmentTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxManagerAttachmentTest.java
index 40f7cd2..d7f1a41 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxManagerAttachmentTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxManagerAttachmentTest.java
@@ -25,6 +25,7 @@ import static org.mockito.Mockito.when;
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.acl.SimpleGroupMembershipResolver;
 import org.apache.james.mailbox.acl.UnionMailboxACLResolver;
@@ -35,7 +36,6 @@ import org.apache.james.mailbox.cassandra.ids.CassandraMessageId;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule;
-import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraDeletedMessageModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraFirstUnseenModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule;

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperAclTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperAclTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperAclTest.java
index 9490386..286d90e 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperAclTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperAclTest.java
@@ -22,11 +22,11 @@ package org.apache.james.mailbox.cassandra.mail;
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule;
-import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraDeletedMessageModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraFirstUnseenModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule;

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAOTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAOTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAOTest.java
index 2fa731d..eee499f 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAOTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAOTest.java
@@ -38,12 +38,13 @@ import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
+import org.apache.james.blob.cassandra.CassandraBlobsDAO;
 import org.apache.james.mailbox.MessageUid;
 import org.apache.james.mailbox.cassandra.ids.CassandraId;
 import org.apache.james.mailbox.cassandra.ids.CassandraMessageId;
 import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAO.MessageIdAttachmentIds;
 import org.apache.james.mailbox.cassandra.mail.utils.Limit;
-import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraMessageModule;
 import org.apache.james.mailbox.model.Attachment;
 import org.apache.james.mailbox.model.ComposedMessageId;

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapperTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapperTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapperTest.java
index 72c4544..b7499bb 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapperTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapperTest.java
@@ -22,11 +22,11 @@ package org.apache.james.mailbox.cassandra.mail;
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule;
-import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraDeletedMessageModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraFirstUnseenModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule;

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapperTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapperTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapperTest.java
index 0fdde79..e5f472f 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapperTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapperTest.java
@@ -23,11 +23,11 @@ import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.ContainerLifecycleConfiguration;
 import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule;
-import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraDeletedMessageModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraFirstUnseenModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule;

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMoveTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMoveTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMoveTest.java
index 8f62042..0f41fa3 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMoveTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMoveTest.java
@@ -22,11 +22,11 @@ package org.apache.james.mailbox.cassandra.mail;
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule;
-import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraDeletedMessageModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraFirstUnseenModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule;

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageWithAttachmentMapperTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageWithAttachmentMapperTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageWithAttachmentMapperTest.java
index 2d35c39..9efe448 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageWithAttachmentMapperTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageWithAttachmentMapperTest.java
@@ -22,11 +22,11 @@ package org.apache.james.mailbox.cassandra.mail;
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule;
-import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraDeletedMessageModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraFirstUnseenModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule;

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentMessageIdCreationTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentMessageIdCreationTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentMessageIdCreationTest.java
index da4c0bf..67d5b1e 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentMessageIdCreationTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentMessageIdCreationTest.java
@@ -39,14 +39,14 @@ import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
 import org.apache.james.backends.cassandra.migration.Migration;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
+import org.apache.james.blob.cassandra.CassandraBlobsDAO;
 import org.apache.james.mailbox.MessageUid;
 import org.apache.james.mailbox.cassandra.ids.CassandraId;
 import org.apache.james.mailbox.cassandra.ids.CassandraMessageId;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentMessageIdDAO;
-import org.apache.james.mailbox.cassandra.mail.CassandraBlobsDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAO;
 import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule;
-import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraMessageModule;
 import org.apache.james.mailbox.model.Attachment;
 import org.apache.james.mailbox.model.AttachmentId;

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2MigrationTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2MigrationTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2MigrationTest.java
index b53205e..70792a8 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2MigrationTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2MigrationTest.java
@@ -35,11 +35,11 @@ import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
 import org.apache.james.backends.cassandra.migration.Migration;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
 import org.apache.james.blob.cassandra.CassandraBlobId;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
+import org.apache.james.blob.cassandra.CassandraBlobsDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAOV2;
-import org.apache.james.mailbox.cassandra.mail.CassandraBlobsDAO;
 import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule;
-import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule;
 import org.apache.james.mailbox.model.Attachment;
 import org.apache.james.mailbox.model.AttachmentId;
 import org.junit.Before;

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/utils/DataChunkerTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/utils/DataChunkerTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/utils/DataChunkerTest.java
deleted file mode 100644
index 9f3d369..0000000
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/utils/DataChunkerTest.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.mailbox.cassandra.mail.utils;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.nio.ByteBuffer;
-import java.nio.charset.StandardCharsets;
-import java.util.stream.Stream;
-
-import org.apache.commons.lang3.tuple.Pair;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.primitives.Bytes;
-
-public class DataChunkerTest {
-
-    public static final int CHUNK_SIZE = 10;
-
-    @Rule
-    public ExpectedException expectedException = ExpectedException.none();
-
-    private DataChunker testee;
-
-    @Before
-    public void setUp() {
-        testee = new DataChunker();
-    }
-
-    @Test
-    public void chunkShouldThrowOnNullData() {
-        expectedException.expect(NullPointerException.class);
-
-        testee.chunk(null, CHUNK_SIZE);
-    }
-
-    @Test
-    public void chunkShouldThrowOnNegativeChunkSize() {
-        expectedException.expect(IllegalArgumentException.class);
-
-        int chunkSize = -1;
-        testee.chunk(new byte[0], chunkSize);
-    }
-
-    @Test
-    public void chunkShouldThrowOnZeroChunkSize() {
-        expectedException.expect(IllegalArgumentException.class);
-
-        int chunkSize = 0;
-        testee.chunk(new byte[0], chunkSize);
-    }
-
-    @Test
-    public void chunkShouldReturnOneEmptyArrayWhenInputEmpty() {
-        Stream<Pair<Integer, ByteBuffer>> chunks = testee.chunk(new byte[0], CHUNK_SIZE);
-        ByteBuffer emptyBuffer = ByteBuffer.wrap(new byte[0]);
-        assertThat(chunks)
-            .containsOnlyElementsOf(ImmutableList.of(Pair.of(0, emptyBuffer)));
-    }
-
-    @Test
-    public void chunkShouldReturnOneArrayWhenInputLessThanChunkSize() {
-        byte[] data = "12345".getBytes(StandardCharsets.UTF_8);
-
-        Stream<Pair<Integer, ByteBuffer>> chunks = testee.chunk(data, CHUNK_SIZE);
-
-        assertThat(chunks)
-            .containsOnlyElementsOf(ImmutableList.of(Pair.of(0, ByteBuffer.wrap(data))));
-    }
-
-    @Test
-    public void chunkShouldReturnOneArrayWhenInputEqualsChunkSize() {
-        byte[] data = "1234567890".getBytes(StandardCharsets.UTF_8);
-        assertThat(data.length).isEqualTo(CHUNK_SIZE);
-
-        Stream<Pair<Integer, ByteBuffer>> chunks = testee.chunk(data, CHUNK_SIZE);
-
-        assertThat(chunks)
-            .containsOnlyElementsOf(ImmutableList.of(Pair.of(0, ByteBuffer.wrap(data))));
-    }
-
-    @Test
-    public void chunkShouldReturnSeveralArrayWhenInputBiggerThanChunkSize() {
-        byte[] part1 = "1234567890".getBytes(StandardCharsets.UTF_8);
-        byte[] part2 = "12345".getBytes(StandardCharsets.UTF_8);
-        byte[] data = Bytes.concat(part1, part2);
-
-        Stream<Pair<Integer, ByteBuffer>> chunks = testee.chunk(data, CHUNK_SIZE);
-
-        assertThat(chunks)
-        .containsOnlyElementsOf(ImmutableList.of(
-                Pair.of(0, ByteBuffer.wrap(part1)),
-                Pair.of(1, ByteBuffer.wrap(part2))));
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java
----------------------------------------------------------------------
diff --git a/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java b/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java
index 0f758da..ff42a5a 100644
--- a/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java
+++ b/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java
@@ -21,6 +21,7 @@ package org.apache.james.mpt.imapmailbox.cassandra.host;
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.components.CassandraModule;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
 import org.apache.james.imap.encode.main.DefaultImapEncoderFactory;
 import org.apache.james.imap.main.DefaultImapDecoderFactory;
 import org.apache.james.imap.processor.main.DefaultImapProcessorFactory;
@@ -36,7 +37,6 @@ import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule;
-import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraDeletedMessageModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraFirstUnseenModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule;

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/server/blob/blob-cassandra/pom.xml
----------------------------------------------------------------------
diff --git a/server/blob/blob-cassandra/pom.xml b/server/blob/blob-cassandra/pom.xml
index 387d222..22e6985 100644
--- a/server/blob/blob-cassandra/pom.xml
+++ b/server/blob/blob-cassandra/pom.xml
@@ -35,10 +35,26 @@
     <dependencies>
         <dependency>
             <groupId>${project.groupId}</groupId>
+            <artifactId>apache-james-backends-cassandra</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>apache-james-backends-cassandra</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
             <artifactId>blob-api</artifactId>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
+            <artifactId>blob-api</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
             <artifactId>james-server-util-java8</artifactId>
         </dependency>
         <dependency>
@@ -69,6 +85,10 @@
             <artifactId>junit-platform-launcher</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.testcontainers</groupId>
+            <artifactId>testcontainers</artifactId>
+        </dependency>
     </dependencies>
     
 </project>

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/BlobTable.java
----------------------------------------------------------------------
diff --git a/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/BlobTable.java b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/BlobTable.java
new file mode 100644
index 0000000..bfbe742
--- /dev/null
+++ b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/BlobTable.java
@@ -0,0 +1,32 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.blob.cassandra;
+
+public interface BlobTable {
+    String TABLE_NAME = "blobs";
+    String ID = "id";
+    String NUMBER_OF_CHUNK = "position";
+
+    interface BlobParts {
+        String TABLE_NAME = "blobParts";
+        String CHUNK_NUMBER = "chunkNumber";
+        String DATA = "data";
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[07/13] james-project git commit: JAMES-2287 Cassandra ObjectStore implementation

Posted by bt...@apache.org.
http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobModule.java
----------------------------------------------------------------------
diff --git a/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobModule.java b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobModule.java
new file mode 100644
index 0000000..234988a
--- /dev/null
+++ b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobModule.java
@@ -0,0 +1,68 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.blob.cassandra;
+
+import java.util.List;
+
+import org.apache.james.backends.cassandra.components.CassandraModule;
+import org.apache.james.backends.cassandra.components.CassandraTable;
+import org.apache.james.backends.cassandra.components.CassandraType;
+
+import com.datastax.driver.core.DataType;
+import com.datastax.driver.core.schemabuilder.SchemaBuilder;
+import com.google.common.collect.ImmutableList;
+
+public class CassandraBlobModule implements CassandraModule {
+
+    private final List<CassandraTable> tables;
+    private final List<CassandraType> types;
+
+    public CassandraBlobModule() {
+        tables = ImmutableList.of(
+            new CassandraTable(BlobTable.TABLE_NAME,
+                SchemaBuilder.createTable(BlobTable.TABLE_NAME)
+                    .ifNotExists()
+                    .addPartitionKey(BlobTable.ID, DataType.text())
+                    .addClusteringColumn(BlobTable.NUMBER_OF_CHUNK, DataType.cint())
+                    .withOptions()
+                    .comment("Holds information for retrieving all blob parts composing this blob. " +
+                        "Messages` headers and bodies are stored as blobparts.")),
+            new CassandraTable(BlobTable.BlobParts.TABLE_NAME,
+                SchemaBuilder.createTable(BlobTable.BlobParts.TABLE_NAME)
+                    .ifNotExists()
+                    .addPartitionKey(BlobTable.ID, DataType.text())
+                    .addClusteringColumn(BlobTable.BlobParts.CHUNK_NUMBER, DataType.cint())
+                    .addColumn(BlobTable.BlobParts.DATA, DataType.blob())
+                    .withOptions()
+                    .comment("Holds blob parts composing blobs ." +
+                        "Messages` headers and bodies are stored, chunked in blobparts.")));
+        types = ImmutableList.of();
+    }
+
+    @Override
+    public List<CassandraTable> moduleTables() {
+        return tables;
+    }
+
+    @Override
+    public List<CassandraType> moduleTypes() {
+        return types;
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobsDAO.java
----------------------------------------------------------------------
diff --git a/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobsDAO.java b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobsDAO.java
new file mode 100644
index 0000000..97965ec
--- /dev/null
+++ b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobsDAO.java
@@ -0,0 +1,210 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.blob.cassandra;
+
+import static com.datastax.driver.core.querybuilder.QueryBuilder.bindMarker;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.eq;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.insertInto;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
+
+import java.nio.ByteBuffer;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+import javax.inject.Inject;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.james.backends.cassandra.init.CassandraConfiguration;
+import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor;
+import org.apache.james.blob.api.BlobId;
+import org.apache.james.blob.api.ObjectStore;
+import org.apache.james.blob.cassandra.BlobTable.BlobParts;
+import org.apache.james.blob.cassandra.utils.DataChunker;
+import org.apache.james.util.FluentFutureStream;
+import org.apache.james.util.OptionalUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.datastax.driver.core.PreparedStatement;
+import com.datastax.driver.core.Row;
+import com.datastax.driver.core.Session;
+import com.github.steveash.guavate.Guavate;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.primitives.Bytes;
+
+public class CassandraBlobsDAO implements ObjectStore {
+    private static final Logger LOGGER = LoggerFactory.getLogger(CassandraBlobsDAO.class);
+    private final CassandraAsyncExecutor cassandraAsyncExecutor;
+    private final PreparedStatement insert;
+    private final PreparedStatement insertPart;
+    private final PreparedStatement select;
+    private final PreparedStatement selectPart;
+    private final DataChunker dataChunker;
+    private final CassandraConfiguration configuration;
+
+    @Inject
+    public CassandraBlobsDAO(Session session, CassandraConfiguration cassandraConfiguration) {
+        this.cassandraAsyncExecutor = new CassandraAsyncExecutor(session);
+        this.configuration = cassandraConfiguration;
+        this.dataChunker = new DataChunker();
+        this.insert = prepareInsert(session);
+        this.select = prepareSelect(session);
+
+        this.insertPart = prepareInsertPart(session);
+        this.selectPart = prepareSelectPart(session);
+    }
+
+    @VisibleForTesting
+    public CassandraBlobsDAO(Session session) {
+        this(session, CassandraConfiguration.DEFAULT_CONFIGURATION);
+    }
+
+    private PreparedStatement prepareSelect(Session session) {
+        return session.prepare(select()
+            .from(BlobTable.TABLE_NAME)
+            .where(eq(BlobTable.ID, bindMarker(BlobTable.ID))));
+    }
+
+    private PreparedStatement prepareSelectPart(Session session) {
+        return session.prepare(select()
+            .from(BlobParts.TABLE_NAME)
+            .where(eq(BlobTable.ID, bindMarker(BlobTable.ID)))
+            .and(eq(BlobParts.CHUNK_NUMBER, bindMarker(BlobParts.CHUNK_NUMBER))));
+    }
+
+    private PreparedStatement prepareInsert(Session session) {
+        return session.prepare(insertInto(BlobTable.TABLE_NAME)
+            .value(BlobTable.ID, bindMarker(BlobTable.ID))
+            .value(BlobTable.NUMBER_OF_CHUNK, bindMarker(BlobTable.NUMBER_OF_CHUNK)));
+    }
+
+    private PreparedStatement prepareInsertPart(Session session) {
+        return session.prepare(insertInto(BlobParts.TABLE_NAME)
+            .value(BlobTable.ID, bindMarker(BlobTable.ID))
+            .value(BlobParts.CHUNK_NUMBER, bindMarker(BlobParts.CHUNK_NUMBER))
+            .value(BlobParts.DATA, bindMarker(BlobParts.DATA)));
+    }
+
+    @Override
+    public CompletableFuture<BlobId> save(byte[] data) {
+        Preconditions.checkNotNull(data);
+
+        CassandraBlobId blobId = CassandraBlobId.forPayload(data);
+        return saveBlobParts(data, blobId)
+            .thenCompose(numberOfChunk -> saveBlobPartsReferences(blobId, numberOfChunk))
+            .thenApply(any -> blobId);
+    }
+
+    private CompletableFuture<Integer> saveBlobParts(byte[] data, CassandraBlobId blobId) {
+        return FluentFutureStream.of(
+            dataChunker.chunk(data, configuration.getBlobPartSize())
+                .map(pair -> writePart(pair.getRight(), blobId, pair.getKey())
+                    .thenApply(partId -> Pair.of(pair.getKey(), partId))))
+            .completableFuture()
+            .thenApply(stream ->
+                getLastOfStream(stream)
+                    .map(numOfChunkAndPartId -> numOfChunkAndPartId.getLeft() + 1)
+                    .orElse(0));
+    }
+
+    private static <T> Optional<T> getLastOfStream(Stream<T> stream) {
+        return stream.reduce((first, second) -> second);
+    }
+
+    private CompletableFuture<Void> writePart(ByteBuffer data, CassandraBlobId blobId, int position) {
+        return cassandraAsyncExecutor.executeVoid(
+            insertPart.bind()
+                .setString(BlobTable.ID, blobId.asString())
+                .setInt(BlobParts.CHUNK_NUMBER, position)
+                .setBytes(BlobParts.DATA, data));
+    }
+
+    private CompletableFuture<Void> saveBlobPartsReferences(CassandraBlobId blobId, int numberOfChunk) {
+        return cassandraAsyncExecutor.executeVoid(insert.bind()
+            .setString(BlobTable.ID, blobId.asString())
+            .setInt(BlobTable.NUMBER_OF_CHUNK, numberOfChunk));
+    }
+
+    @Override
+    public CompletableFuture<byte[]> read(BlobId blobId) {
+        return cassandraAsyncExecutor.executeSingleRow(
+            select.bind()
+                .setString(BlobTable.ID, blobId.asString()))
+            .thenCompose(row -> toDataParts(row, blobId))
+            .thenApply(this::concatenateDataParts);
+    }
+
+    private CompletableFuture<Stream<BlobPart>> toDataParts(Optional<Row> blobRowOptional, BlobId blobId) {
+        return blobRowOptional.map(blobRow -> {
+            int numOfChunk = blobRow.getInt(BlobTable.NUMBER_OF_CHUNK);
+            return FluentFutureStream.of(
+                IntStream.range(0, numOfChunk)
+                    .mapToObj(position -> readPart(blobId, position)))
+                .completableFuture();
+        }).orElseGet(() -> {
+            LOGGER.warn("Could not retrieve blob metadata for {}", blobId);
+            return CompletableFuture.completedFuture(Stream.empty());
+        });
+    }
+
+    private byte[] concatenateDataParts(Stream<BlobPart> blobParts) {
+        ImmutableList<byte[]> parts = blobParts
+            .map(blobPart -> OptionalUtils.executeIfEmpty(
+                blobPart.row,
+                () -> LOGGER.warn("Missing blob part for blobId {} and position {}", blobPart.blobId, blobPart.position)))
+            .flatMap(OptionalUtils::toStream)
+            .map(this::rowToData)
+            .collect(Guavate.toImmutableList());
+
+        return Bytes.concat(parts.toArray(new byte[parts.size()][]));
+    }
+
+    private byte[] rowToData(Row row) {
+        byte[] data = new byte[row.getBytes(BlobParts.DATA).remaining()];
+        row.getBytes(BlobParts.DATA).get(data);
+        return data;
+    }
+
+    private CompletableFuture<BlobPart> readPart(BlobId blobId, int position) {
+        return cassandraAsyncExecutor.executeSingleRow(
+            selectPart.bind()
+                .setString(BlobTable.ID, blobId.asString())
+                .setInt(BlobParts.CHUNK_NUMBER, position))
+            .thenApply(row -> new BlobPart(blobId, position, row));
+    }
+
+    private static class BlobPart {
+        private final BlobId blobId;
+        private final int position;
+        private final Optional<Row> row;
+
+        public BlobPart(BlobId blobId, int position, Optional<Row> row) {
+            Preconditions.checkNotNull(blobId);
+            Preconditions.checkArgument(position >= 0, "position need to be positive");
+            this.blobId = blobId;
+            this.position = position;
+            this.row = row;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/utils/DataChunker.java
----------------------------------------------------------------------
diff --git a/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/utils/DataChunker.java b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/utils/DataChunker.java
new file mode 100644
index 0000000..aad71dc
--- /dev/null
+++ b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/utils/DataChunker.java
@@ -0,0 +1,52 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.blob.cassandra.utils;
+
+import java.nio.ByteBuffer;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+import org.apache.commons.lang3.tuple.Pair;
+
+import com.google.common.base.Preconditions;
+
+public class DataChunker {
+
+    public Stream<Pair<Integer, ByteBuffer>> chunk(byte[] data, int chunkSize) {
+        Preconditions.checkNotNull(data);
+        Preconditions.checkArgument(chunkSize > 0, "ChunkSize can not be negative");
+
+        int size = data.length;
+        int fullChunkCount = size / chunkSize;
+
+        return Stream.concat(
+            IntStream.range(0, fullChunkCount)
+                .mapToObj(i -> Pair.of(i, ByteBuffer.wrap(data, i * chunkSize, chunkSize))),
+            lastChunk(data, chunkSize * fullChunkCount, fullChunkCount));
+    }
+
+    private Stream<Pair<Integer, ByteBuffer>> lastChunk(byte[] data, int offset, int index) {
+        if (offset == data.length && index > 0) {
+            return Stream.empty();
+        }
+        return Stream.of(Pair.of(index, ByteBuffer.wrap(data, offset, data.length - offset)));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobsDAOTest.java
----------------------------------------------------------------------
diff --git a/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobsDAOTest.java b/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobsDAOTest.java
new file mode 100644
index 0000000..62e73cd
--- /dev/null
+++ b/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobsDAOTest.java
@@ -0,0 +1,86 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.blob.cassandra;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.james.backends.cassandra.CassandraCluster;
+import org.apache.james.backends.cassandra.DockerCassandraExtension;
+import org.apache.james.backends.cassandra.DockerCassandraExtension.DockerCassandra;
+import org.apache.james.backends.cassandra.init.CassandraConfiguration;
+import org.apache.james.blob.api.BlobId;
+import org.apache.james.blob.api.ObjectStore;
+import org.apache.james.blob.api.ObjectStoreContract;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import com.google.common.base.Strings;
+
+@ExtendWith(DockerCassandraExtension.class)
+public class CassandraBlobsDAOTest implements ObjectStoreContract {
+
+    private static final int CHUNK_SIZE = 10240;
+    private static final int MULTIPLE_CHUNK_SIZE = 3;
+
+    private CassandraCluster cassandra;
+    private CassandraBlobsDAO testee;
+
+    @BeforeEach
+    public void setUp(DockerCassandra dockerCassandra) {
+        cassandra = CassandraCluster.create(
+                new CassandraBlobModule(), dockerCassandra.getIp(), dockerCassandra.getBindingPort());
+        
+        testee = new CassandraBlobsDAO(cassandra.getConf(),
+            CassandraConfiguration.builder()
+                .blobPartSize(CHUNK_SIZE)
+                .build());
+    }
+
+    @AfterEach
+    public void tearDown() {
+        cassandra.close();
+    }
+
+    @Override
+    public ObjectStore testee() {
+        return testee;
+    }
+
+    @Override
+    public BlobId from(String blodIdAsString) {
+        return CassandraBlobId.from(blodIdAsString);
+    }
+
+    @Test
+    public void readShouldReturnSplitSavedDataByChunk() throws IOException {
+        String longString = Strings.repeat("0123456789\n", MULTIPLE_CHUNK_SIZE);
+        BlobId blobId = testee.save(longString.getBytes(StandardCharsets.UTF_8)).join();
+
+        byte[] bytes = testee.read(blobId).join();
+
+        assertThat(new String(bytes, StandardCharsets.UTF_8)).isEqualTo(longString);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/utils/DataChunkerTest.java
----------------------------------------------------------------------
diff --git a/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/utils/DataChunkerTest.java b/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/utils/DataChunkerTest.java
new file mode 100644
index 0000000..0f97a0d
--- /dev/null
+++ b/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/utils/DataChunkerTest.java
@@ -0,0 +1,110 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.blob.cassandra.utils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.stream.Stream;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.primitives.Bytes;
+
+public class DataChunkerTest {
+
+    public static final int CHUNK_SIZE = 10;
+
+    private DataChunker testee;
+
+    @BeforeEach
+    public void setUp() {
+        testee = new DataChunker();
+    }
+
+    @Test
+    public void chunkShouldThrowOnNullData() {
+        assertThatThrownBy(() -> testee.chunk(null, CHUNK_SIZE))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    public void chunkShouldThrowOnNegativeChunkSize() {
+        int chunkSize = -1;
+        assertThatThrownBy(() -> testee.chunk(new byte[0], chunkSize))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void chunkShouldThrowOnZeroChunkSize() {
+        int chunkSize = 0;
+        assertThatThrownBy(() -> testee.chunk(new byte[0], chunkSize))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void chunkShouldReturnOneEmptyArrayWhenInputEmpty() {
+        Stream<Pair<Integer, ByteBuffer>> chunks = testee.chunk(new byte[0], CHUNK_SIZE);
+        ByteBuffer emptyBuffer = ByteBuffer.wrap(new byte[0]);
+        assertThat(chunks)
+            .containsOnlyElementsOf(ImmutableList.of(Pair.of(0, emptyBuffer)));
+    }
+
+    @Test
+    public void chunkShouldReturnOneArrayWhenInputLessThanChunkSize() {
+        byte[] data = "12345".getBytes(StandardCharsets.UTF_8);
+
+        Stream<Pair<Integer, ByteBuffer>> chunks = testee.chunk(data, CHUNK_SIZE);
+
+        assertThat(chunks)
+            .containsOnlyElementsOf(ImmutableList.of(Pair.of(0, ByteBuffer.wrap(data))));
+    }
+
+    @Test
+    public void chunkShouldReturnOneArrayWhenInputEqualsChunkSize() {
+        byte[] data = "1234567890".getBytes(StandardCharsets.UTF_8);
+        assertThat(data.length).isEqualTo(CHUNK_SIZE);
+
+        Stream<Pair<Integer, ByteBuffer>> chunks = testee.chunk(data, CHUNK_SIZE);
+
+        assertThat(chunks)
+            .containsOnlyElementsOf(ImmutableList.of(Pair.of(0, ByteBuffer.wrap(data))));
+    }
+
+    @Test
+    public void chunkShouldReturnSeveralArrayWhenInputBiggerThanChunkSize() {
+        byte[] part1 = "1234567890".getBytes(StandardCharsets.UTF_8);
+        byte[] part2 = "12345".getBytes(StandardCharsets.UTF_8);
+        byte[] data = Bytes.concat(part1, part2);
+
+        Stream<Pair<Integer, ByteBuffer>> chunks = testee.chunk(data, CHUNK_SIZE);
+
+        assertThat(chunks)
+        .containsOnlyElementsOf(ImmutableList.of(
+                Pair.of(0, ByteBuffer.wrap(part1)),
+                Pair.of(1, ByteBuffer.wrap(part2))));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/4e8bcc66/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java
index b233920..3d1c404 100644
--- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java
+++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java
@@ -23,6 +23,7 @@ import javax.inject.Singleton;
 import org.apache.james.adapter.mailbox.store.UserRepositoryAuthenticator;
 import org.apache.james.adapter.mailbox.store.UserRepositoryAuthorizator;
 import org.apache.james.backends.cassandra.components.CassandraModule;
+import org.apache.james.blob.cassandra.CassandraBlobsDAO;
 import org.apache.james.mailbox.AttachmentManager;
 import org.apache.james.mailbox.BlobManager;
 import org.apache.james.mailbox.MailboxListener;
@@ -43,7 +44,6 @@ import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAOV2;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentMessageIdDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentOwnerDAO;
-import org.apache.james.mailbox.cassandra.mail.CassandraBlobsDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraDeletedMessageDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraFirstUnseenDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraMailboxCounterDAO;
@@ -159,7 +159,7 @@ public class CassandraMailboxModule extends AbstractModule {
         cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule.class);
         cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule.class);
         cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule.class);
-        cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraBlobModule.class);
+        cassandraDataDefinitions.addBinding().to(org.apache.james.blob.cassandra.CassandraBlobModule.class);
         cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraDeletedMessageModule.class);
         cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraFirstUnseenModule.class);
         cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule.class);


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[05/13] james-project git commit: JAMES-2287 Introduce ObjectStore API

Posted by bt...@apache.org.
JAMES-2287 Introduce ObjectStore API


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

Branch: refs/heads/master
Commit: 5796a95e297fab53faa8cf5e93203316759cd9d3
Parents: 68e099c
Author: Antoine Duprat <ad...@linagora.com>
Authored: Tue Jan 16 13:09:35 2018 +0100
Committer: benwa <bt...@linagora.com>
Committed: Fri Jan 19 09:07:27 2018 +0700

----------------------------------------------------------------------
 pom.xml                                         |  6 ++
 server/blob/blob-api/pom.xml                    | 32 ++++++++
 .../org/apache/james/blob/api/ObjectStore.java  | 28 +++++++
 .../james/blob/api/ObjectStoreContract.java     | 83 ++++++++++++++++++++
 4 files changed, 149 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/5796a95e/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index edf90d3..ebe228a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -975,6 +975,12 @@
             </dependency>
             <dependency>
                 <groupId>${project.groupId}</groupId>
+                <artifactId>blob-api</artifactId>
+                <version>${project.version}</version>
+                <type>test-jar</type>
+            </dependency>
+            <dependency>
+                <groupId>${project.groupId}</groupId>
                 <artifactId>blob-cassandra</artifactId>
                 <version>${project.version}</version>
             </dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/5796a95e/server/blob/blob-api/pom.xml
----------------------------------------------------------------------
diff --git a/server/blob/blob-api/pom.xml b/server/blob/blob-api/pom.xml
index b0cd9b7..d15765a 100644
--- a/server/blob/blob-api/pom.xml
+++ b/server/blob/blob-api/pom.xml
@@ -33,6 +33,38 @@
     <name>Apache James :: Server :: Blob :: API</name>
 
     <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>james-server-util-java8</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>nl.jqno.equalsverifier</groupId>
+            <artifactId>equalsverifier</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.platform</groupId>
+            <artifactId>junit-platform-launcher</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
     
 </project>

http://git-wip-us.apache.org/repos/asf/james-project/blob/5796a95e/server/blob/blob-api/src/main/java/org/apache/james/blob/api/ObjectStore.java
----------------------------------------------------------------------
diff --git a/server/blob/blob-api/src/main/java/org/apache/james/blob/api/ObjectStore.java b/server/blob/blob-api/src/main/java/org/apache/james/blob/api/ObjectStore.java
new file mode 100644
index 0000000..c2bd88a
--- /dev/null
+++ b/server/blob/blob-api/src/main/java/org/apache/james/blob/api/ObjectStore.java
@@ -0,0 +1,28 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+package org.apache.james.blob.api;
+
+import java.util.concurrent.CompletableFuture;
+
+public interface ObjectStore {
+
+    CompletableFuture<BlobId> save(byte[] data);
+
+    CompletableFuture<byte[]> read(BlobId blobId);
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/5796a95e/server/blob/blob-api/src/test/java/org/apache/james/blob/api/ObjectStoreContract.java
----------------------------------------------------------------------
diff --git a/server/blob/blob-api/src/test/java/org/apache/james/blob/api/ObjectStoreContract.java b/server/blob/blob-api/src/test/java/org/apache/james/blob/api/ObjectStoreContract.java
new file mode 100644
index 0000000..61b5718
--- /dev/null
+++ b/server/blob/blob-api/src/test/java/org/apache/james/blob/api/ObjectStoreContract.java
@@ -0,0 +1,83 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+package org.apache.james.blob.api;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+import org.junit.jupiter.api.Test;
+
+import com.google.common.base.Strings;
+
+public interface ObjectStoreContract {
+
+    ObjectStore testee();
+    BlobId from(String blodIdAsString);
+
+    @Test
+    default void saveShouldReturnEmptyWhenNullData() throws Exception {
+        assertThatThrownBy(() -> testee().save(null))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    default void saveShouldSaveEmptyData() throws Exception {
+        BlobId blobId = testee().save(new byte[]{}).join();
+
+        byte[] bytes = testee().read(blobId).join();
+
+        assertThat(new String(bytes, StandardCharsets.UTF_8)).isEmpty();
+    }
+
+    @Test
+    default void saveShouldReturnBlobId() throws Exception {
+        BlobId blobId = testee().save("toto".getBytes(StandardCharsets.UTF_8)).join();
+
+        assertThat(blobId).isEqualTo(from("31f7a65e315586ac198bd798b6629ce4903d0899476d5741a9f32e2e521b6a66"));
+    }
+
+    @Test
+    default void readShouldBeEmptyWhenNoExisting() throws IOException {
+        byte[] bytes = testee().read(from("unknown")).join();
+
+        assertThat(bytes).isEmpty();
+    }
+
+    @Test
+    default void readShouldReturnSavedData() throws IOException {
+        BlobId blobId = testee().save("toto".getBytes(StandardCharsets.UTF_8)).join();
+
+        byte[] bytes = testee().read(blobId).join();
+
+        assertThat(new String(bytes, StandardCharsets.UTF_8)).isEqualTo("toto");
+    }
+
+    @Test
+    default void readShouldReturnLongSavedData() throws IOException {
+        String longString = Strings.repeat("0123456789\n", 1000);
+        BlobId blobId = testee().save(longString.getBytes(StandardCharsets.UTF_8)).join();
+
+        byte[] bytes = testee().read(blobId).join();
+
+        assertThat(new String(bytes, StandardCharsets.UTF_8)).isEqualTo(longString);
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[12/13] james-project git commit: JAMES-2287 BlobId.Factory for creating BlobIds

Posted by bt...@apache.org.
JAMES-2287 BlobId.Factory for creating BlobIds


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

Branch: refs/heads/master
Commit: c4c370ee946d7589f83acf0e944ca189a1363863
Parents: 4db46a8
Author: benwa <bt...@linagora.com>
Authored: Wed Jan 17 11:51:25 2018 +0700
Committer: benwa <bt...@linagora.com>
Committed: Fri Jan 19 09:07:28 2018 +0700

----------------------------------------------------------------------
 .../java/org/apache/james/blob/api/BlobId.java   |  6 ++++++
 .../james/blob/api/ObjectStoreContract.java      |  7 ++++---
 .../james/blob/cassandra/CassandraBlobId.java    | 18 +++++++++++-------
 .../james/blob/cassandra/CassandraBlobsDAO.java  |  8 +++++---
 .../blob/cassandra/CassandraBlobIdTest.java      | 19 +++++++++++--------
 .../blob/cassandra/CassandraBlobsDAOTest.java    |  7 ++++---
 6 files changed, 41 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/c4c370ee/server/blob/blob-api/src/main/java/org/apache/james/blob/api/BlobId.java
----------------------------------------------------------------------
diff --git a/server/blob/blob-api/src/main/java/org/apache/james/blob/api/BlobId.java b/server/blob/blob-api/src/main/java/org/apache/james/blob/api/BlobId.java
index 647c153..dbfd204 100644
--- a/server/blob/blob-api/src/main/java/org/apache/james/blob/api/BlobId.java
+++ b/server/blob/blob-api/src/main/java/org/apache/james/blob/api/BlobId.java
@@ -21,5 +21,11 @@ package org.apache.james.blob.api;
 
 public interface BlobId {
 
+    interface Factory {
+        BlobId forPayload(byte[] payload);
+
+        BlobId from(String id);
+    }
+
     String asString();
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/c4c370ee/server/blob/blob-api/src/test/java/org/apache/james/blob/api/ObjectStoreContract.java
----------------------------------------------------------------------
diff --git a/server/blob/blob-api/src/test/java/org/apache/james/blob/api/ObjectStoreContract.java b/server/blob/blob-api/src/test/java/org/apache/james/blob/api/ObjectStoreContract.java
index 2cbab37..bd4bd8e 100644
--- a/server/blob/blob-api/src/test/java/org/apache/james/blob/api/ObjectStoreContract.java
+++ b/server/blob/blob-api/src/test/java/org/apache/james/blob/api/ObjectStoreContract.java
@@ -31,7 +31,8 @@ import com.google.common.base.Strings;
 public interface ObjectStoreContract {
 
     ObjectStore testee();
-    BlobId from(String blodIdAsString);
+
+    BlobId.Factory blobIdFactory();
 
     @Test
     default void saveShouldReturnEmptyWhenNullData() throws Exception {
@@ -52,12 +53,12 @@ public interface ObjectStoreContract {
     default void saveShouldReturnBlobId() throws Exception {
         BlobId blobId = testee().save("toto".getBytes(StandardCharsets.UTF_8)).join();
 
-        assertThat(blobId).isEqualTo(from("31f7a65e315586ac198bd798b6629ce4903d0899476d5741a9f32e2e521b6a66"));
+        assertThat(blobId).isEqualTo(blobIdFactory().from("31f7a65e315586ac198bd798b6629ce4903d0899476d5741a9f32e2e521b6a66"));
     }
 
     @Test
     default void readShouldBeEmptyWhenNoExisting() throws IOException {
-        byte[] bytes = testee().read(from("unknown")).join();
+        byte[] bytes = testee().read(blobIdFactory().from("unknown")).join();
 
         assertThat(bytes).isEmpty();
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/c4c370ee/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobId.java
----------------------------------------------------------------------
diff --git a/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobId.java b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobId.java
index 5dba57e..fedd734 100644
--- a/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobId.java
+++ b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobId.java
@@ -30,14 +30,18 @@ import com.google.common.base.Strings;
 
 public class CassandraBlobId implements BlobId {
 
-    public static CassandraBlobId forPayload(byte[] payload) {
-        Preconditions.checkArgument(payload != null);
-        return new CassandraBlobId(DigestUtils.sha256Hex(payload));
-    }
+    public static class Factory implements BlobId.Factory {
+        @Override
+        public CassandraBlobId forPayload(byte[] payload) {
+            Preconditions.checkArgument(payload != null);
+            return new CassandraBlobId(DigestUtils.sha256Hex(payload));
+        }
 
-    public static CassandraBlobId from(String id) {
-        Preconditions.checkArgument(!Strings.isNullOrEmpty(id));
-        return new CassandraBlobId(id);
+        @Override
+        public CassandraBlobId from(String id) {
+            Preconditions.checkArgument(!Strings.isNullOrEmpty(id));
+            return new CassandraBlobId(id);
+        }
     }
 
     private final String id;

http://git-wip-us.apache.org/repos/asf/james-project/blob/c4c370ee/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobsDAO.java
----------------------------------------------------------------------
diff --git a/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobsDAO.java b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobsDAO.java
index 97965ec..0c47757 100644
--- a/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobsDAO.java
+++ b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobsDAO.java
@@ -62,11 +62,13 @@ public class CassandraBlobsDAO implements ObjectStore {
     private final PreparedStatement selectPart;
     private final DataChunker dataChunker;
     private final CassandraConfiguration configuration;
+    private final CassandraBlobId.Factory blobIdFactory;
 
     @Inject
-    public CassandraBlobsDAO(Session session, CassandraConfiguration cassandraConfiguration) {
+    public CassandraBlobsDAO(Session session, CassandraConfiguration cassandraConfiguration, CassandraBlobId.Factory blobIdFactory) {
         this.cassandraAsyncExecutor = new CassandraAsyncExecutor(session);
         this.configuration = cassandraConfiguration;
+        this.blobIdFactory = blobIdFactory;
         this.dataChunker = new DataChunker();
         this.insert = prepareInsert(session);
         this.select = prepareSelect(session);
@@ -77,7 +79,7 @@ public class CassandraBlobsDAO implements ObjectStore {
 
     @VisibleForTesting
     public CassandraBlobsDAO(Session session) {
-        this(session, CassandraConfiguration.DEFAULT_CONFIGURATION);
+        this(session, CassandraConfiguration.DEFAULT_CONFIGURATION, new CassandraBlobId.Factory());
     }
 
     private PreparedStatement prepareSelect(Session session) {
@@ -110,7 +112,7 @@ public class CassandraBlobsDAO implements ObjectStore {
     public CompletableFuture<BlobId> save(byte[] data) {
         Preconditions.checkNotNull(data);
 
-        CassandraBlobId blobId = CassandraBlobId.forPayload(data);
+        CassandraBlobId blobId = blobIdFactory.forPayload(data);
         return saveBlobParts(data, blobId)
             .thenCompose(numberOfChunk -> saveBlobPartsReferences(blobId, numberOfChunk))
             .thenApply(any -> blobId);

http://git-wip-us.apache.org/repos/asf/james-project/blob/c4c370ee/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobIdTest.java
----------------------------------------------------------------------
diff --git a/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobIdTest.java b/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobIdTest.java
index 2fe0db2..70c7e7c 100644
--- a/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobIdTest.java
+++ b/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobIdTest.java
@@ -24,6 +24,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import java.nio.charset.StandardCharsets;
 
+import org.apache.james.blob.api.BlobId;
 import org.apache.james.util.ClassLoaderUtils;
 import org.junit.jupiter.api.Test;
 
@@ -31,6 +32,8 @@ import nl.jqno.equalsverifier.EqualsVerifier;
 
 public class CassandraBlobIdTest {
 
+    private static final CassandraBlobId.Factory BLOB_ID_FACTORY = new CassandraBlobId.Factory();
+
     @Test
     public void shouldRespectBeanContract() {
         EqualsVerifier.forClass(CassandraBlobId.class).verify();
@@ -39,38 +42,38 @@ public class CassandraBlobIdTest {
     @Test
     public void fromShouldConstructBlobId() {
         String id = "111";
-        assertThat(CassandraBlobId.from(id))
+        assertThat(BLOB_ID_FACTORY.from(id))
             .isEqualTo(new CassandraBlobId(id));
     }
 
     @Test
     public void fromShouldThrowOnNull() {
-        assertThatThrownBy(() -> CassandraBlobId.from(null))
+        assertThatThrownBy(() -> BLOB_ID_FACTORY.from(null))
             .isInstanceOf(IllegalArgumentException.class);
     }
 
     @Test
     public void fromShouldThrowOnEmpty() {
-        assertThatThrownBy(() -> CassandraBlobId.from(""))
+        assertThatThrownBy(() -> BLOB_ID_FACTORY.from(""))
             .isInstanceOf(IllegalArgumentException.class);
     }
 
     @Test
     public void forPayloadShouldThrowOnNull() {
-        assertThatThrownBy(() -> CassandraBlobId.forPayload(null))
+        assertThatThrownBy(() -> BLOB_ID_FACTORY.forPayload(null))
             .isInstanceOf(IllegalArgumentException.class);
     }
 
     @Test
     public void forPayloadShouldHashEmptyArray() {
-        CassandraBlobId blobId = CassandraBlobId.forPayload(new byte[0]);
+        BlobId blobId = BLOB_ID_FACTORY.forPayload(new byte[0]);
 
         assertThat(blobId.asString()).isEqualTo("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
     }
 
     @Test
     public void forPayloadShouldHashArray() {
-        CassandraBlobId blobId = CassandraBlobId.forPayload("content".getBytes(StandardCharsets.UTF_8));
+        BlobId blobId = BLOB_ID_FACTORY.forPayload("content".getBytes(StandardCharsets.UTF_8));
 
         assertThat(blobId.asString()).isEqualTo("ed7002b439e9ac845f22357d822bac1444730fbdb6016d3ec9432297b9ec9f73");
     }
@@ -79,8 +82,8 @@ public class CassandraBlobIdTest {
     public void forPayloadShouldCalculateDifferentHashesWhenCraftedSha1Collision() throws Exception {
         byte[] payload1 = ClassLoaderUtils.getSystemResourceAsByteArray("shattered-1.pdf");
         byte[] payload2 = ClassLoaderUtils.getSystemResourceAsByteArray("shattered-2.pdf");
-        CassandraBlobId blobId1 = CassandraBlobId.forPayload(payload1);
-        CassandraBlobId blobId2 = CassandraBlobId.forPayload(payload2);
+        BlobId blobId1 = BLOB_ID_FACTORY.forPayload(payload1);
+        BlobId blobId2 = BLOB_ID_FACTORY.forPayload(payload2);
         assertThat(blobId1).isNotEqualTo(blobId2);
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/c4c370ee/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobsDAOTest.java
----------------------------------------------------------------------
diff --git a/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobsDAOTest.java b/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobsDAOTest.java
index 62e73cd..918730a 100644
--- a/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobsDAOTest.java
+++ b/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobsDAOTest.java
@@ -55,7 +55,8 @@ public class CassandraBlobsDAOTest implements ObjectStoreContract {
         testee = new CassandraBlobsDAO(cassandra.getConf(),
             CassandraConfiguration.builder()
                 .blobPartSize(CHUNK_SIZE)
-                .build());
+                .build(),
+            new CassandraBlobId.Factory());
     }
 
     @AfterEach
@@ -69,8 +70,8 @@ public class CassandraBlobsDAOTest implements ObjectStoreContract {
     }
 
     @Override
-    public BlobId from(String blodIdAsString) {
-        return CassandraBlobId.from(blodIdAsString);
+    public BlobId.Factory blobIdFactory() {
+        return new CassandraBlobId.Factory();
     }
 
     @Test


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[13/13] james-project git commit: JAMES-2287 Makes DockerCassandraExtension significantly faster

Posted by bt...@apache.org.
JAMES-2287 Makes DockerCassandraExtension significantly faster


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

Branch: refs/heads/master
Commit: 63a6a1471470e2231971321b0b5a2ebd15010da1
Parents: 4e8bcc6
Author: benwa <bt...@linagora.com>
Authored: Wed Jan 17 11:37:47 2018 +0700
Committer: benwa <bt...@linagora.com>
Committed: Fri Jan 19 09:07:28 2018 +0700

----------------------------------------------------------------------
 .../backends/cassandra/DockerCassandraExtension.java     | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/63a6a147/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandraExtension.java
----------------------------------------------------------------------
diff --git a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandraExtension.java b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandraExtension.java
index 98b16fc..43a3cb5 100644
--- a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandraExtension.java
+++ b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandraExtension.java
@@ -19,16 +19,15 @@
 
 package org.apache.james.backends.cassandra;
 
-import org.junit.jupiter.api.extension.AfterEachCallback;
-import org.junit.jupiter.api.extension.BeforeEachCallback;
+import org.junit.jupiter.api.extension.AfterAllCallback;
+import org.junit.jupiter.api.extension.BeforeAllCallback;
 import org.junit.jupiter.api.extension.ExtensionContext;
 import org.junit.jupiter.api.extension.ParameterContext;
 import org.junit.jupiter.api.extension.ParameterResolutionException;
 import org.junit.jupiter.api.extension.ParameterResolver;
 import org.testcontainers.containers.GenericContainer;
 
-
-public class DockerCassandraExtension implements BeforeEachCallback, AfterEachCallback, ParameterResolver {
+public class DockerCassandraExtension implements BeforeAllCallback, AfterAllCallback, ParameterResolver {
 
     private final DockerCassandraRule cassandraContainer;
     private DockerCassandra dockerCassandra;
@@ -38,13 +37,13 @@ public class DockerCassandraExtension implements BeforeEachCallback, AfterEachCa
     }
 
     @Override
-    public void beforeEach(ExtensionContext context) throws Exception {
+    public void beforeAll(ExtensionContext context) throws Exception {
         cassandraContainer.start();
         dockerCassandra = DockerCassandra.from(cassandraContainer.getRawContainer());
     }
 
     @Override
-    public void afterEach(ExtensionContext context) throws Exception {
+    public void afterAll(ExtensionContext context) throws Exception {
         cassandraContainer.stop();
     }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[11/13] james-project git commit: JAMES-2287 Cassandra mailbox should depend on ObjectStore API

Posted by bt...@apache.org.
JAMES-2287 Cassandra mailbox should depend on ObjectStore API

And not on its implementations


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

Branch: refs/heads/master
Commit: ea12b94b50b49b3dfc8739825a60c87321fd0329
Parents: c4c370e
Author: benwa <bt...@linagora.com>
Authored: Thu Jan 18 11:22:15 2018 +0700
Committer: benwa <bt...@linagora.com>
Committed: Fri Jan 19 09:07:28 2018 +0700

----------------------------------------------------------------------
 mailbox/cassandra/pom.xml                       |  5 ++++
 .../CassandraMailboxSessionMapperFactory.java   | 15 ++++++----
 .../mail/CassandraAttachmentDAOV2.java          | 11 +++----
 .../mail/CassandraAttachmentMapper.java         | 14 ++++-----
 .../cassandra/mail/CassandraMessageDAO.java     | 30 ++++++++++----------
 .../mail/migration/AttachmentV2Migration.java   | 10 +++----
 .../CassandraSubscriptionManagerTest.java       |  7 ++++-
 ...estCassandraMailboxSessionMapperFactory.java | 11 +++----
 .../mail/CassandraAttachmentDAOV2Test.java      |  6 ++--
 .../mail/CassandraAttachmentFallbackTest.java   |  4 ++-
 .../cassandra/mail/CassandraMessageDAOTest.java |  5 +++-
 .../AttachmentMessageIdCreationTest.java        |  3 +-
 .../migration/AttachmentV2MigrationTest.java    | 22 +++++++-------
 mpt/impl/imap-mailbox/cassandra/pom.xml         |  4 +++
 14 files changed, 87 insertions(+), 60 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/ea12b94b/mailbox/cassandra/pom.xml
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/pom.xml b/mailbox/cassandra/pom.xml
index 0826db3..2be705b 100644
--- a/mailbox/cassandra/pom.xml
+++ b/mailbox/cassandra/pom.xml
@@ -64,7 +64,12 @@
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
+            <artifactId>blob-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
             <artifactId>blob-cassandra</artifactId>
+            <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>

http://git-wip-us.apache.org/repos/asf/james-project/blob/ea12b94b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
index 3969700..d95d1a0 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
@@ -23,7 +23,8 @@ import javax.inject.Inject;
 
 import org.apache.james.backends.cassandra.init.CassandraConfiguration;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
-import org.apache.james.blob.cassandra.CassandraBlobsDAO;
+import org.apache.james.blob.api.BlobId;
+import org.apache.james.blob.api.ObjectStore;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.cassandra.mail.CassandraACLMapper;
 import org.apache.james.mailbox.cassandra.mail.CassandraAnnotationMapper;
@@ -85,11 +86,12 @@ public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFa
     private final CassandraAttachmentDAO attachmentDAO;
     private final CassandraAttachmentDAOV2 attachmentDAOV2;
     private final CassandraDeletedMessageDAO deletedMessageDAO;
-    private final CassandraBlobsDAO blobsDAO;
+    private final ObjectStore objectStore;
     private final CassandraAttachmentMessageIdDAO attachmentMessageIdDAO;
     private final CassandraAttachmentOwnerDAO ownerDAO;
     private final CassandraACLMapper aclMapper;
     private final CassandraUserMailboxRightsDAO userMailboxRightsDAO;
+    private final BlobId.Factory blobIdFactory;
     private final CassandraUtils cassandraUtils;
     private final CassandraConfiguration cassandraConfiguration;
 
@@ -100,10 +102,10 @@ public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFa
                                                 CassandraMailboxCounterDAO mailboxCounterDAO, CassandraMailboxRecentsDAO mailboxRecentsDAO, CassandraMailboxDAO mailboxDAO,
                                                 CassandraMailboxPathDAO mailboxPathDAO, CassandraFirstUnseenDAO firstUnseenDAO, CassandraApplicableFlagDAO applicableFlagDAO,
                                                 CassandraAttachmentDAO attachmentDAO, CassandraAttachmentDAOV2 attachmentDAOV2, CassandraDeletedMessageDAO deletedMessageDAO,
-                                                CassandraBlobsDAO blobsDAO, CassandraAttachmentMessageIdDAO attachmentMessageIdDAO,
+                                                ObjectStore objectStore, CassandraAttachmentMessageIdDAO attachmentMessageIdDAO,
                                                 CassandraAttachmentOwnerDAO ownerDAO, CassandraACLMapper aclMapper,
                                                 CassandraUserMailboxRightsDAO userMailboxRightsDAO,
-                                                CassandraUtils cassandraUtils, CassandraConfiguration cassandraConfiguration) {
+                                                BlobId.Factory blobIdFactory, CassandraUtils cassandraUtils, CassandraConfiguration cassandraConfiguration) {
         this.uidProvider = uidProvider;
         this.modSeqProvider = modSeqProvider;
         this.session = session;
@@ -119,10 +121,11 @@ public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFa
         this.attachmentDAOV2 = attachmentDAOV2;
         this.deletedMessageDAO = deletedMessageDAO;
         this.applicableFlagDAO = applicableFlagDAO;
-        this.blobsDAO = blobsDAO;
+        this.objectStore = objectStore;
         this.attachmentMessageIdDAO = attachmentMessageIdDAO;
         this.aclMapper = aclMapper;
         this.userMailboxRightsDAO = userMailboxRightsDAO;
+        this.blobIdFactory = blobIdFactory;
         this.cassandraUtils = cassandraUtils;
         this.ownerDAO = ownerDAO;
         this.cassandraConfiguration = cassandraConfiguration;
@@ -168,7 +171,7 @@ public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFa
 
     @Override
     public CassandraAttachmentMapper createAttachmentMapper(MailboxSession mailboxSession) {
-        return new CassandraAttachmentMapper(attachmentDAO, attachmentDAOV2, blobsDAO, attachmentMessageIdDAO, ownerDAO);
+        return new CassandraAttachmentMapper(attachmentDAO, attachmentDAOV2, objectStore, attachmentMessageIdDAO, ownerDAO);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/james-project/blob/ea12b94b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2.java
index 8a40ef8..f88723f 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2.java
@@ -39,7 +39,6 @@ import javax.inject.Inject;
 
 import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor;
 import org.apache.james.blob.api.BlobId;
-import org.apache.james.blob.cassandra.CassandraBlobId;
 import org.apache.james.mailbox.model.Attachment;
 import org.apache.james.mailbox.model.AttachmentId;
 
@@ -113,20 +112,22 @@ public class CassandraAttachmentDAOV2 {
             attachment.getSize());
     }
 
-    private static DAOAttachment fromRow(Row row) {
+    private static DAOAttachment fromRow(Row row, BlobId.Factory blobIfFactory) {
         return new DAOAttachment(
             AttachmentId.from(row.getString(ID)),
-            CassandraBlobId.from(row.getString(BLOB_ID)),
+            blobIfFactory.from(row.getString(BLOB_ID)),
             row.getString(TYPE),
             row.getLong(SIZE));
     }
 
+    private final BlobId.Factory blobIdFactory;
     private final CassandraAsyncExecutor cassandraAsyncExecutor;
     private final PreparedStatement insertStatement;
     private final PreparedStatement selectStatement;
 
     @Inject
-    public CassandraAttachmentDAOV2(Session session) {
+    public CassandraAttachmentDAOV2(BlobId.Factory blobIdFactory, Session session) {
+        this.blobIdFactory = blobIdFactory;
         this.cassandraAsyncExecutor = new CassandraAsyncExecutor(session);
 
         this.selectStatement = prepareSelect(session);
@@ -154,7 +155,7 @@ public class CassandraAttachmentDAOV2 {
         return cassandraAsyncExecutor.executeSingleRow(
             selectStatement.bind()
                 .setUUID(ID_AS_UUID, attachmentId.asUUID()))
-            .thenApply(row -> row.map(CassandraAttachmentDAOV2::fromRow));
+            .thenApply(rowOptional -> rowOptional.map(row -> CassandraAttachmentDAOV2.fromRow(row, blobIdFactory)));
     }
 
     public CompletableFuture<Void> storeAttachment(DAOAttachment attachment) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/ea12b94b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java
index d9a282f..ef0294b 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java
@@ -28,7 +28,7 @@ import java.util.stream.Stream;
 
 import javax.inject.Inject;
 
-import org.apache.james.blob.cassandra.CassandraBlobsDAO;
+import org.apache.james.blob.api.ObjectStore;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAOV2.DAOAttachment;
 import org.apache.james.mailbox.exception.AttachmentNotFoundException;
 import org.apache.james.mailbox.exception.MailboxException;
@@ -51,15 +51,15 @@ public class CassandraAttachmentMapper implements AttachmentMapper {
 
     private final CassandraAttachmentDAO attachmentDAO;
     private final CassandraAttachmentDAOV2 attachmentDAOV2;
-    private final CassandraBlobsDAO blobsDAO;
+    private final ObjectStore objectStore;
     private final CassandraAttachmentMessageIdDAO attachmentMessageIdDAO;
     private final CassandraAttachmentOwnerDAO ownerDAO;
 
     @Inject
-    public CassandraAttachmentMapper(CassandraAttachmentDAO attachmentDAO, CassandraAttachmentDAOV2 attachmentDAOV2, CassandraBlobsDAO blobsDAO, CassandraAttachmentMessageIdDAO attachmentMessageIdDAO, final CassandraAttachmentOwnerDAO ownerDAO) {
+    public CassandraAttachmentMapper(CassandraAttachmentDAO attachmentDAO, CassandraAttachmentDAOV2 attachmentDAOV2, ObjectStore objectStore, CassandraAttachmentMessageIdDAO attachmentMessageIdDAO, CassandraAttachmentOwnerDAO ownerDAO) {
         this.attachmentDAO = attachmentDAO;
         this.attachmentDAOV2 = attachmentDAOV2;
-        this.blobsDAO = blobsDAO;
+        this.objectStore = objectStore;
         this.attachmentMessageIdDAO = attachmentMessageIdDAO;
         this.ownerDAO = ownerDAO;
     }
@@ -87,7 +87,7 @@ public class CassandraAttachmentMapper implements AttachmentMapper {
             return CompletableFuture.completedFuture(Optional.empty());
         }
         DAOAttachment daoAttachment = daoAttachmentOptional.get();
-        return blobsDAO.read(daoAttachment.getBlobId())
+        return objectStore.read(daoAttachment.getBlobId())
             .thenApply(bytes -> Optional.of(daoAttachment.toAttachment(bytes)));
     }
 
@@ -126,7 +126,7 @@ public class CassandraAttachmentMapper implements AttachmentMapper {
     @Override
     public void storeAttachmentForOwner(Attachment attachment, Username owner) throws MailboxException {
         ownerDAO.addOwner(attachment.getAttachmentId(), owner)
-            .thenCompose(any -> blobsDAO.save(attachment.getBytes()))
+            .thenCompose(any -> objectStore.save(attachment.getBytes()))
             .thenApply(blobId -> CassandraAttachmentDAOV2.from(attachment, blobId))
             .thenCompose(attachmentDAOV2::storeAttachment)
             .join();
@@ -152,7 +152,7 @@ public class CassandraAttachmentMapper implements AttachmentMapper {
     }
 
     public CompletableFuture<Void> storeAttachmentAsync(Attachment attachment, MessageId ownerMessageId) {
-        return blobsDAO.save(attachment.getBytes())
+        return objectStore.save(attachment.getBytes())
             .thenApply(blobId -> CassandraAttachmentDAOV2.from(attachment, blobId))
             .thenCompose(daoAttachment -> storeAttachmentWithIndex(daoAttachment, ownerMessageId));
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/ea12b94b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java
index 72fe82e..e00ca41 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java
@@ -60,8 +60,7 @@ import org.apache.james.backends.cassandra.init.CassandraTypesProvider;
 import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
 import org.apache.james.blob.api.BlobId;
-import org.apache.james.blob.cassandra.CassandraBlobId;
-import org.apache.james.blob.cassandra.CassandraBlobsDAO;
+import org.apache.james.blob.api.ObjectStore;
 import org.apache.james.mailbox.cassandra.ids.CassandraMessageId;
 import org.apache.james.mailbox.cassandra.mail.utils.Limit;
 import org.apache.james.mailbox.cassandra.table.CassandraMessageV2Table;
@@ -103,7 +102,8 @@ public class CassandraMessageDAO {
 
     private final CassandraAsyncExecutor cassandraAsyncExecutor;
     private final CassandraTypesProvider typesProvider;
-    private final CassandraBlobsDAO blobsDAO;
+    private final ObjectStore objectStore;
+    private final BlobId.Factory blobIdFactory;
     private final CassandraConfiguration configuration;
     private final CassandraUtils cassandraUtils;
     private final CassandraMessageId.Factory messageIdFactory;
@@ -117,11 +117,13 @@ public class CassandraMessageDAO {
     private final Cid.CidParser cidParser;
 
     @Inject
-    public CassandraMessageDAO(Session session, CassandraTypesProvider typesProvider, CassandraBlobsDAO blobsDAO, CassandraConfiguration cassandraConfiguration,
+    public CassandraMessageDAO(Session session, CassandraTypesProvider typesProvider, ObjectStore objectStore,
+                               BlobId.Factory blobIdFactory, CassandraConfiguration cassandraConfiguration,
             CassandraUtils cassandraUtils, CassandraMessageId.Factory messageIdFactory) {
         this.cassandraAsyncExecutor = new CassandraAsyncExecutor(session);
         this.typesProvider = typesProvider;
-        this.blobsDAO = blobsDAO;
+        this.objectStore = objectStore;
+        this.blobIdFactory = blobIdFactory;
         this.configuration = cassandraConfiguration;
         this.cassandraUtils = cassandraUtils;
         this.messageIdFactory = messageIdFactory;
@@ -137,9 +139,9 @@ public class CassandraMessageDAO {
     }
 
     @VisibleForTesting
-    public CassandraMessageDAO(Session session, CassandraTypesProvider typesProvider, CassandraBlobsDAO blobsDAO,
-            CassandraUtils cassandraUtils, CassandraMessageId.Factory messageIdFactory) {
-        this(session, typesProvider, blobsDAO, CassandraConfiguration.DEFAULT_CONFIGURATION, cassandraUtils, messageIdFactory);
+    public CassandraMessageDAO(Session session, CassandraTypesProvider typesProvider, ObjectStore objectStore,
+                               BlobId.Factory blobIdFactory, CassandraUtils cassandraUtils, CassandraMessageId.Factory messageIdFactory) {
+        this(session, typesProvider, objectStore,  blobIdFactory, CassandraConfiguration.DEFAULT_CONFIGURATION, cassandraUtils, messageIdFactory);
     }
 
     private PreparedStatement prepareSelect(Session session, String[] fields) {
@@ -180,13 +182,11 @@ public class CassandraMessageDAO {
 
     private CompletableFuture<Pair<BlobId, BlobId>> saveContent(MailboxMessage message) throws MailboxException {
         try {
+            byte[] headerContent = IOUtils.toByteArray(message.getHeaderContent());
+            byte[] bodyContent = IOUtils.toByteArray(message.getBodyContent());
             return CompletableFutureUtil.combine(
-                blobsDAO.save(
-                    IOUtils.toByteArray(
-                        message.getHeaderContent())),
-                blobsDAO.save(
-                    IOUtils.toByteArray(
-                        message.getBodyContent())),
+                objectStore.save(headerContent),
+                objectStore.save(bodyContent),
                 Pair::of);
         } catch (IOException e) {
             throw new MailboxException("Error saving mail content", e);
@@ -372,7 +372,7 @@ public class CassandraMessageDAO {
     }
 
     private CompletableFuture<byte[]> getFieldContent(String field, Row row) {
-        return blobsDAO.read(CassandraBlobId.from(row.getString(field)));
+        return objectStore.read(blobIdFactory.from(row.getString(field)));
     }
 
     public static MessageResult notFound(ComposedMessageIdWithMetaData id) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/ea12b94b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2Migration.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2Migration.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2Migration.java
index 651b381..0e074f4 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2Migration.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2Migration.java
@@ -22,7 +22,7 @@ package org.apache.james.mailbox.cassandra.mail.migration;
 import javax.inject.Inject;
 
 import org.apache.james.backends.cassandra.migration.Migration;
-import org.apache.james.blob.cassandra.CassandraBlobsDAO;
+import org.apache.james.blob.api.ObjectStore;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAOV2;
 import org.apache.james.mailbox.model.Attachment;
@@ -34,15 +34,15 @@ public class AttachmentV2Migration implements Migration {
     private static final Logger LOGGER = LoggerFactory.getLogger(AttachmentV2Migration.class);
     private final CassandraAttachmentDAO attachmentDAOV1;
     private final CassandraAttachmentDAOV2 attachmentDAOV2;
-    private final CassandraBlobsDAO blobsDAO;
+    private final ObjectStore objectStore;
 
     @Inject
     public AttachmentV2Migration(CassandraAttachmentDAO attachmentDAOV1,
                                  CassandraAttachmentDAOV2 attachmentDAOV2,
-                                 CassandraBlobsDAO blobsDAO) {
+                                 ObjectStore objectStore) {
         this.attachmentDAOV1 = attachmentDAOV1;
         this.attachmentDAOV2 = attachmentDAOV2;
-        this.blobsDAO = blobsDAO;
+        this.objectStore = objectStore;
     }
 
     @Override
@@ -59,7 +59,7 @@ public class AttachmentV2Migration implements Migration {
 
     private Result migrateAttachment(Attachment attachment) {
         try {
-            blobsDAO.save(attachment.getBytes())
+            objectStore.save(attachment.getBytes())
                 .thenApply(blobId -> CassandraAttachmentDAOV2.from(attachment, blobId))
                 .thenCompose(attachmentDAOV2::storeAttachment)
                 .thenCompose(any -> attachmentDAOV1.deleteAttachment(attachment.getAttachmentId()))

http://git-wip-us.apache.org/repos/asf/james-project/blob/ea12b94b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManagerTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManagerTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManagerTest.java
index c55cc11..153a859 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManagerTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManagerTest.java
@@ -24,6 +24,8 @@ import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.init.CassandraConfiguration;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
+import org.apache.james.blob.api.BlobId;
+import org.apache.james.blob.api.ObjectStore;
 import org.apache.james.blob.cassandra.CassandraBlobsDAO;
 import org.apache.james.mailbox.AbstractSubscriptionManagerTest;
 import org.apache.james.mailbox.SubscriptionManager;
@@ -99,6 +101,8 @@ public class CassandraSubscriptionManagerTest extends AbstractSubscriptionManage
         CassandraAttachmentOwnerDAO ownerDAO = null;
         CassandraACLMapper aclMapper = null;
         CassandraUserMailboxRightsDAO userMailboxRightsDAO = null;
+        BlobId.Factory blobIdFactory = null;
+        ObjectStore objectStore = null;
         return new CassandraSubscriptionManager(
             new CassandraMailboxSessionMapperFactory(
                 new CassandraUidProvider(cassandra.getConf()),
@@ -116,11 +120,12 @@ public class CassandraSubscriptionManagerTest extends AbstractSubscriptionManage
                 attachmentDAO,
                 attachmentDAOV2,
                 deletedMessageDAO,
-                cassandraBlobsDAO,
+                objectStore,
                 attachmentMessageIdDAO,
                 ownerDAO,
                 aclMapper,
                 userMailboxRightsDAO,
+                blobIdFactory,
                 CassandraUtils.WITH_DEFAULT_CONFIGURATION,
                 CassandraConfiguration.DEFAULT_CONFIGURATION));
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/ea12b94b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/TestCassandraMailboxSessionMapperFactory.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/TestCassandraMailboxSessionMapperFactory.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/TestCassandraMailboxSessionMapperFactory.java
index a6d854c..c4503b1 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/TestCassandraMailboxSessionMapperFactory.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/TestCassandraMailboxSessionMapperFactory.java
@@ -22,6 +22,7 @@ package org.apache.james.mailbox.cassandra;
 import org.apache.james.backends.cassandra.init.CassandraConfiguration;
 import org.apache.james.backends.cassandra.init.CassandraTypesProvider;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
+import org.apache.james.blob.cassandra.CassandraBlobId;
 import org.apache.james.blob.cassandra.CassandraBlobsDAO;
 import org.apache.james.mailbox.cassandra.ids.CassandraMessageId;
 import org.apache.james.mailbox.cassandra.mail.CassandraACLMapper;
@@ -49,11 +50,12 @@ public class TestCassandraMailboxSessionMapperFactory {
     public static CassandraMailboxSessionMapperFactory forTests(Session session, CassandraTypesProvider typesProvider,
                                                                 CassandraMessageId.Factory factory) {
         CassandraBlobsDAO cassandraBlobsDAO = new CassandraBlobsDAO(session);
+        CassandraBlobId.Factory blobIdFactory = new CassandraBlobId.Factory();
         return new CassandraMailboxSessionMapperFactory(
             new CassandraUidProvider(session),
             new CassandraModSeqProvider(session),
             session,
-            new CassandraMessageDAO(session, typesProvider, cassandraBlobsDAO, CassandraUtils.WITH_DEFAULT_CONFIGURATION, factory),
+            new CassandraMessageDAO(session, typesProvider, cassandraBlobsDAO, blobIdFactory, CassandraUtils.WITH_DEFAULT_CONFIGURATION, factory),
             new CassandraMessageIdDAO(session, factory),
             new CassandraMessageIdToImapUidDAO(session, factory),
             new CassandraMailboxCounterDAO(session),
@@ -63,16 +65,15 @@ public class TestCassandraMailboxSessionMapperFactory {
             new CassandraFirstUnseenDAO(session),
             new CassandraApplicableFlagDAO(session),
             new CassandraAttachmentDAO(session, CassandraUtils.WITH_DEFAULT_CONFIGURATION, CassandraConfiguration.DEFAULT_CONFIGURATION),
-            new CassandraAttachmentDAOV2(session),
+            new CassandraAttachmentDAOV2(blobIdFactory, session),
             new CassandraDeletedMessageDAO(session),
-            cassandraBlobsDAO,
-            new CassandraAttachmentMessageIdDAO(session, factory, CassandraUtils.WITH_DEFAULT_CONFIGURATION),
+            cassandraBlobsDAO, new CassandraAttachmentMessageIdDAO(session, factory, CassandraUtils.WITH_DEFAULT_CONFIGURATION),
             new CassandraAttachmentOwnerDAO(session, CassandraUtils.WITH_DEFAULT_CONFIGURATION),
             new CassandraACLMapper(session,
                 new CassandraUserMailboxRightsDAO(session, CassandraUtils.WITH_DEFAULT_CONFIGURATION),
                 CassandraConfiguration.DEFAULT_CONFIGURATION),
             new CassandraUserMailboxRightsDAO(session, CassandraUtils.WITH_DEFAULT_CONFIGURATION),
-            CassandraUtils.WITH_DEFAULT_CONFIGURATION,
+            blobIdFactory, CassandraUtils.WITH_DEFAULT_CONFIGURATION,
             CassandraConfiguration.DEFAULT_CONFIGURATION);
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/ea12b94b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2Test.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2Test.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2Test.java
index f5a8285..d5f7ca4 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2Test.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2Test.java
@@ -26,6 +26,7 @@ import java.util.Optional;
 
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.DockerCassandraRule;
+import org.apache.james.blob.api.BlobId;
 import org.apache.james.blob.cassandra.CassandraBlobId;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAOV2.DAOAttachment;
 import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule;
@@ -38,6 +39,7 @@ import org.junit.Test;
 
 public class CassandraAttachmentDAOV2Test {
     public static final AttachmentId ATTACHMENT_ID = AttachmentId.from("id1");
+    private static final CassandraBlobId.Factory BLOB_ID_FACTORY = new CassandraBlobId.Factory();
 
     @ClassRule
     public static DockerCassandraRule cassandraServer = new DockerCassandraRule();
@@ -53,7 +55,7 @@ public class CassandraAttachmentDAOV2Test {
             cassandraServer.getIp(),
             cassandraServer.getBindingPort());
 
-        testee = new CassandraAttachmentDAOV2(cassandra.getConf());
+        testee = new CassandraAttachmentDAOV2(BLOB_ID_FACTORY, cassandra.getConf());
     }
 
     @After
@@ -75,7 +77,7 @@ public class CassandraAttachmentDAOV2Test {
             .type("application/json")
             .bytes("{\"property\":`\"value\"}".getBytes(StandardCharsets.UTF_8))
             .build();
-        CassandraBlobId blobId = CassandraBlobId.from("blobId");
+        BlobId blobId = BLOB_ID_FACTORY.from("blobId");
         DAOAttachment daoAttachment = CassandraAttachmentDAOV2.from(attachment, blobId);
         testee.storeAttachment(daoAttachment).join();
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/ea12b94b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentFallbackTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentFallbackTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentFallbackTest.java
index 0658b1a..175c479 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentFallbackTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentFallbackTest.java
@@ -30,6 +30,7 @@ import org.apache.james.backends.cassandra.init.CassandraConfiguration;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
 import org.apache.james.blob.api.BlobId;
+import org.apache.james.blob.cassandra.CassandraBlobId;
 import org.apache.james.blob.cassandra.CassandraBlobModule;
 import org.apache.james.blob.cassandra.CassandraBlobsDAO;
 import org.apache.james.mailbox.cassandra.ids.CassandraMessageId;
@@ -46,6 +47,7 @@ import org.testcontainers.shaded.com.google.common.collect.ImmutableList;
 public class CassandraAttachmentFallbackTest {
     public static final AttachmentId ATTACHMENT_ID_1 = AttachmentId.from("id1");
     public static final AttachmentId ATTACHMENT_ID_2 = AttachmentId.from("id2");
+    private static final CassandraBlobId.Factory BLOB_ID_FACTORY = new CassandraBlobId.Factory();
 
     @ClassRule
     public static DockerCassandraRule cassandraServer = new DockerCassandraRule();
@@ -69,7 +71,7 @@ public class CassandraAttachmentFallbackTest {
             cassandraServer.getIp(),
             cassandraServer.getBindingPort());
 
-        attachmentDAOV2 = new CassandraAttachmentDAOV2(cassandra.getConf());
+        attachmentDAOV2 = new CassandraAttachmentDAOV2(BLOB_ID_FACTORY, cassandra.getConf());
         attachmentDAO = new CassandraAttachmentDAO(cassandra.getConf(),
             CassandraUtils.WITH_DEFAULT_CONFIGURATION,
             CassandraConfiguration.DEFAULT_CONFIGURATION);

http://git-wip-us.apache.org/repos/asf/james-project/blob/ea12b94b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAOTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAOTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAOTest.java
index eee499f..f9d3f45 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAOTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAOTest.java
@@ -38,6 +38,7 @@ import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
+import org.apache.james.blob.cassandra.CassandraBlobId;
 import org.apache.james.blob.cassandra.CassandraBlobModule;
 import org.apache.james.blob.cassandra.CassandraBlobsDAO;
 import org.apache.james.mailbox.MessageUid;
@@ -89,7 +90,9 @@ public class CassandraMessageDAOTest {
         messageIdFactory = new CassandraMessageId.Factory();
         messageId = messageIdFactory.generate();
         CassandraBlobsDAO blobsDAO = new CassandraBlobsDAO(cassandra.getConf());
-        testee = new CassandraMessageDAO(cassandra.getConf(), cassandra.getTypesProvider(), blobsDAO, CassandraUtils.WITH_DEFAULT_CONFIGURATION, new CassandraMessageId.Factory());
+        CassandraBlobId.Factory blobIdFactory = new CassandraBlobId.Factory();
+        testee = new CassandraMessageDAO(cassandra.getConf(), cassandra.getTypesProvider(), blobsDAO, blobIdFactory,
+            CassandraUtils.WITH_DEFAULT_CONFIGURATION, new CassandraMessageId.Factory());
 
         messageIds = ImmutableList.of(ComposedMessageIdWithMetaData.builder()
                 .composedMessageId(new ComposedMessageId(MAILBOX_ID, messageId, messageUid))

http://git-wip-us.apache.org/repos/asf/james-project/blob/ea12b94b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentMessageIdCreationTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentMessageIdCreationTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentMessageIdCreationTest.java
index 67d5b1e..1a491fd 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentMessageIdCreationTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentMessageIdCreationTest.java
@@ -39,6 +39,7 @@ import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
 import org.apache.james.backends.cassandra.migration.Migration;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
+import org.apache.james.blob.cassandra.CassandraBlobId;
 import org.apache.james.blob.cassandra.CassandraBlobModule;
 import org.apache.james.blob.cassandra.CassandraBlobsDAO;
 import org.apache.james.mailbox.MessageUid;
@@ -87,7 +88,7 @@ public class AttachmentMessageIdCreationTest {
 
         blobsDAO = new CassandraBlobsDAO(cassandra.getConf());
         cassandraMessageDAO = new CassandraMessageDAO(cassandra.getConf(), cassandra.getTypesProvider(),
-            blobsDAO, CassandraUtils.WITH_DEFAULT_CONFIGURATION, messageIdFactory);
+            blobsDAO, new CassandraBlobId.Factory(), CassandraUtils.WITH_DEFAULT_CONFIGURATION, messageIdFactory);
 
         attachmentMessageIdDAO = new CassandraAttachmentMessageIdDAO(cassandra.getConf(),
             new CassandraMessageId.Factory(), CassandraUtils.WITH_DEFAULT_CONFIGURATION);

http://git-wip-us.apache.org/repos/asf/james-project/blob/ea12b94b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2MigrationTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2MigrationTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2MigrationTest.java
index 70792a8..68d53a6 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2MigrationTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2MigrationTest.java
@@ -49,6 +49,7 @@ import org.junit.Test;
 public class AttachmentV2MigrationTest {
     public static final AttachmentId ATTACHMENT_ID = AttachmentId.from("id1");
     public static final AttachmentId ATTACHMENT_ID_2 = AttachmentId.from("id2");
+    private static final CassandraBlobId.Factory BLOB_ID_FACTORY = new CassandraBlobId.Factory();
 
     @ClassRule
     public static DockerCassandraRule cassandraServer = new DockerCassandraRule();
@@ -72,9 +73,8 @@ public class AttachmentV2MigrationTest {
         attachmentDAO = new CassandraAttachmentDAO(cassandra.getConf(),
             CassandraUtils.WITH_DEFAULT_CONFIGURATION,
             CassandraConfiguration.DEFAULT_CONFIGURATION);
-        attachmentDAOV2 = new CassandraAttachmentDAOV2(cassandra.getConf());
+        attachmentDAOV2 = new CassandraAttachmentDAOV2(BLOB_ID_FACTORY, cassandra.getConf());
         blobsDAO = new CassandraBlobsDAO(cassandra.getConf());
-
         migration = new AttachmentV2Migration(attachmentDAO, attachmentDAOV2, blobsDAO);
 
         attachment1 = Attachment.builder()
@@ -112,12 +112,12 @@ public class AttachmentV2MigrationTest {
         migration.run();
 
         assertThat(attachmentDAOV2.getAttachment(ATTACHMENT_ID).join())
-            .contains(CassandraAttachmentDAOV2.from(attachment1, CassandraBlobId.forPayload(attachment1.getBytes())));
+            .contains(CassandraAttachmentDAOV2.from(attachment1, BLOB_ID_FACTORY.forPayload(attachment1.getBytes())));
         assertThat(attachmentDAOV2.getAttachment(ATTACHMENT_ID_2).join())
-            .contains(CassandraAttachmentDAOV2.from(attachment2, CassandraBlobId.forPayload(attachment2.getBytes())));
-        assertThat(blobsDAO.read(CassandraBlobId.forPayload(attachment1.getBytes())).join())
+            .contains(CassandraAttachmentDAOV2.from(attachment2, BLOB_ID_FACTORY.forPayload(attachment2.getBytes())));
+        assertThat(blobsDAO.read(BLOB_ID_FACTORY.forPayload(attachment1.getBytes())).join())
             .isEqualTo(attachment1.getBytes());
-        assertThat(blobsDAO.read(CassandraBlobId.forPayload(attachment2.getBytes())).join())
+        assertThat(blobsDAO.read(BLOB_ID_FACTORY.forPayload(attachment2.getBytes())).join())
             .isEqualTo(attachment2.getBytes());
     }
 
@@ -172,9 +172,9 @@ public class AttachmentV2MigrationTest {
             attachment1,
             attachment2));
         when(blobsDAO.save(attachment1.getBytes()))
-            .thenReturn(CompletableFuture.completedFuture(CassandraBlobId.forPayload(attachment1.getBytes())));
+            .thenReturn(CompletableFuture.completedFuture(BLOB_ID_FACTORY.forPayload(attachment1.getBytes())));
         when(blobsDAO.save(attachment2.getBytes()))
-            .thenReturn(CompletableFuture.completedFuture(CassandraBlobId.forPayload(attachment2.getBytes())));
+            .thenReturn(CompletableFuture.completedFuture(BLOB_ID_FACTORY.forPayload(attachment2.getBytes())));
         when(attachmentDAOV2.storeAttachment(any())).thenThrow(new RuntimeException());
 
         assertThat(migration.run()).isEqualTo(Migration.Result.PARTIAL);
@@ -191,9 +191,9 @@ public class AttachmentV2MigrationTest {
             attachment1,
             attachment2));
         when(blobsDAO.save(attachment1.getBytes()))
-            .thenReturn(CompletableFuture.completedFuture(CassandraBlobId.forPayload(attachment1.getBytes())));
+            .thenReturn(CompletableFuture.completedFuture(BLOB_ID_FACTORY.forPayload(attachment1.getBytes())));
         when(blobsDAO.save(attachment2.getBytes()))
-            .thenReturn(CompletableFuture.completedFuture(CassandraBlobId.forPayload(attachment2.getBytes())));
+            .thenReturn(CompletableFuture.completedFuture(BLOB_ID_FACTORY.forPayload(attachment2.getBytes())));
         when(attachmentDAOV2.storeAttachment(any())).thenReturn(CompletableFuture.completedFuture(null));
         when(attachmentDAO.deleteAttachment(any())).thenThrow(new RuntimeException());
 
@@ -211,7 +211,7 @@ public class AttachmentV2MigrationTest {
             attachment1,
             attachment2));
         when(blobsDAO.save(attachment1.getBytes()))
-            .thenReturn(CompletableFuture.completedFuture(CassandraBlobId.forPayload(attachment1.getBytes())));
+            .thenReturn(CompletableFuture.completedFuture(BLOB_ID_FACTORY.forPayload(attachment1.getBytes())));
         when(blobsDAO.save(attachment2.getBytes()))
             .thenThrow(new RuntimeException());
         when(attachmentDAOV2.storeAttachment(any())).thenReturn(CompletableFuture.completedFuture(null));

http://git-wip-us.apache.org/repos/asf/james-project/blob/ea12b94b/mpt/impl/imap-mailbox/cassandra/pom.xml
----------------------------------------------------------------------
diff --git a/mpt/impl/imap-mailbox/cassandra/pom.xml b/mpt/impl/imap-mailbox/cassandra/pom.xml
index bec05c3..2c325cd 100644
--- a/mpt/impl/imap-mailbox/cassandra/pom.xml
+++ b/mpt/impl/imap-mailbox/cassandra/pom.xml
@@ -55,5 +55,9 @@
             <groupId>${project.groupId}</groupId>
             <artifactId>apache-james-mpt-imapmailbox-core</artifactId>
         </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>blob-cassandra</artifactId>
+        </dependency>
     </dependencies>
 </project>


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[03/13] james-project git commit: JAMES-2287 Introduce BlobId API

Posted by bt...@apache.org.
JAMES-2287 Introduce BlobId API


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

Branch: refs/heads/master
Commit: 1815212517925812a3e24b5f6ad905c1e4b77d66
Parents: 894647e
Author: Antoine Duprat <ad...@linagora.com>
Authored: Tue Jan 16 12:47:11 2018 +0100
Committer: benwa <bt...@linagora.com>
Committed: Fri Jan 19 09:06:42 2018 +0700

----------------------------------------------------------------------
 .../java/org/apache/james/blob/api/BlobId.java  | 25 ++++++++++++++++++++
 1 file changed, 25 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/18152125/server/blob/blob-api/src/main/java/org/apache/james/blob/api/BlobId.java
----------------------------------------------------------------------
diff --git a/server/blob/blob-api/src/main/java/org/apache/james/blob/api/BlobId.java b/server/blob/blob-api/src/main/java/org/apache/james/blob/api/BlobId.java
new file mode 100644
index 0000000..647c153
--- /dev/null
+++ b/server/blob/blob-api/src/main/java/org/apache/james/blob/api/BlobId.java
@@ -0,0 +1,25 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.blob.api;
+
+public interface BlobId {
+
+    String asString();
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[09/13] james-project git commit: JAMES-2287 Cassandra blobId should implement the blobId interface & move in the blob-cassandra project

Posted by bt...@apache.org.
JAMES-2287 Cassandra blobId should implement the blobId interface & move in the blob-cassandra project


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

Branch: refs/heads/master
Commit: 68e099ce99243c8b58f82267910eb7a856d9014a
Parents: 1815212
Author: Antoine Duprat <ad...@linagora.com>
Authored: Tue Jan 16 13:59:35 2018 +0100
Committer: benwa <bt...@linagora.com>
Committed: Fri Jan 19 09:07:27 2018 +0700

----------------------------------------------------------------------
 mailbox/cassandra/pom.xml                       |   4 +
 .../james/mailbox/cassandra/ids/BlobId.java     |  73 ---------------
 .../mail/CassandraAttachmentDAOV2.java          |  14 +--
 .../cassandra/mail/CassandraBlobsDAO.java       |  30 +++---
 .../cassandra/mail/CassandraMessageDAO.java     |  12 +--
 .../james/mailbox/cassandra/ids/BlobIdTest.java |  93 -------------------
 .../mail/CassandraAttachmentDAOV2Test.java      |   4 +-
 .../mail/CassandraAttachmentFallbackTest.java   |   8 +-
 .../cassandra/mail/CassandraBlobsDAOTest.java   |  18 ++--
 .../migration/AttachmentV2MigrationTest.java    |  20 ++--
 pom.xml                                         |   5 +
 server/blob/blob-cassandra/pom.xml              |  74 +++++++++++++++
 .../james/blob/cassandra/CassandraBlobId.java   |  76 +++++++++++++++
 .../blob/cassandra/CassandraBlobIdTest.java     |  86 +++++++++++++++++
 .../src/test/resources/shattered-1.pdf          | Bin 0 -> 422435 bytes
 .../src/test/resources/shattered-2.pdf          | Bin 0 -> 422435 bytes
 server/blob/pom.xml                             |   1 +
 17 files changed, 299 insertions(+), 219 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/68e099ce/mailbox/cassandra/pom.xml
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/pom.xml b/mailbox/cassandra/pom.xml
index 5bffe2b..4377f83 100644
--- a/mailbox/cassandra/pom.xml
+++ b/mailbox/cassandra/pom.xml
@@ -64,6 +64,10 @@
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
+            <artifactId>blob-cassandra</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
             <artifactId>james-server-task</artifactId>
         </dependency>
         <dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/68e099ce/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ids/BlobId.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ids/BlobId.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ids/BlobId.java
deleted file mode 100644
index 3824003..0000000
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ids/BlobId.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.mailbox.cassandra.ids;
-
-import org.apache.commons.codec.digest.DigestUtils;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.MoreObjects;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
-
-public class BlobId {
-    public static BlobId forPayload(byte[] payload) {
-        Preconditions.checkArgument(payload != null);
-        return new BlobId(DigestUtils.sha256Hex(payload));
-    }
-
-    public static BlobId from(String id) {
-        Preconditions.checkArgument(!Strings.isNullOrEmpty(id));
-        return new BlobId(id);
-    }
-
-    private final String id;
-
-    @VisibleForTesting
-    BlobId(String id) {
-        this.id = id;
-    }
-
-    public String getId() {
-        return id;
-    }
-
-    @Override
-    public final boolean equals(Object obj) {
-        if (obj instanceof BlobId) {
-            BlobId other = (BlobId) obj;
-            return Objects.equal(id, other.id);
-        }
-        return false;
-    }
-
-    @Override
-    public final int hashCode() {
-        return Objects.hashCode(id);
-    }
-
-    @Override
-    public String toString() {
-        return MoreObjects
-            .toStringHelper(this)
-            .add("id", id)
-            .toString();
-    }
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/68e099ce/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2.java
index 34a654c..5a9727a 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2.java
@@ -38,7 +38,7 @@ import java.util.concurrent.CompletableFuture;
 import javax.inject.Inject;
 
 import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor;
-import org.apache.james.mailbox.cassandra.ids.BlobId;
+import org.apache.james.blob.cassandra.CassandraBlobId;
 import org.apache.james.mailbox.model.Attachment;
 import org.apache.james.mailbox.model.AttachmentId;
 
@@ -50,11 +50,11 @@ import com.google.common.base.Preconditions;
 public class CassandraAttachmentDAOV2 {
     public static class DAOAttachment {
         private final AttachmentId attachmentId;
-        private final BlobId blobId;
+        private final CassandraBlobId blobId;
         private final String type;
         private final long size;
 
-        private DAOAttachment(AttachmentId attachmentId, BlobId blobId, String type, long size) {
+        private DAOAttachment(AttachmentId attachmentId, CassandraBlobId blobId, String type, long size) {
             this.attachmentId = attachmentId;
             this.blobId = blobId;
             this.type = type;
@@ -65,7 +65,7 @@ public class CassandraAttachmentDAOV2 {
             return attachmentId;
         }
 
-        public BlobId getBlobId() {
+        public CassandraBlobId getBlobId() {
             return blobId;
         }
 
@@ -104,7 +104,7 @@ public class CassandraAttachmentDAOV2 {
         }
     }
 
-    public static DAOAttachment from(Attachment attachment, BlobId blobId) {
+    public static DAOAttachment from(Attachment attachment, CassandraBlobId blobId) {
         return new DAOAttachment(
             attachment.getAttachmentId(),
             blobId,
@@ -115,7 +115,7 @@ public class CassandraAttachmentDAOV2 {
     private static DAOAttachment fromRow(Row row) {
         return new DAOAttachment(
             AttachmentId.from(row.getString(ID)),
-            BlobId.from(row.getString(BLOB_ID)),
+            CassandraBlobId.from(row.getString(BLOB_ID)),
             row.getString(TYPE),
             row.getLong(SIZE));
     }
@@ -163,7 +163,7 @@ public class CassandraAttachmentDAOV2 {
                 .setString(ID, attachment.getAttachmentId().getId())
                 .setLong(SIZE, attachment.getSize())
                 .setString(TYPE, attachment.getType())
-                .setString(BLOB_ID, attachment.getBlobId().getId()));
+                .setString(BLOB_ID, attachment.getBlobId().asString()));
     }
 
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/68e099ce/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraBlobsDAO.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraBlobsDAO.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraBlobsDAO.java
index c7eabf7..5fc09aa 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraBlobsDAO.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraBlobsDAO.java
@@ -35,7 +35,7 @@ import javax.inject.Inject;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.james.backends.cassandra.init.CassandraConfiguration;
 import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor;
-import org.apache.james.mailbox.cassandra.ids.BlobId;
+import org.apache.james.blob.cassandra.CassandraBlobId;
 import org.apache.james.mailbox.cassandra.mail.utils.DataChunker;
 import org.apache.james.mailbox.cassandra.table.BlobTable;
 import org.apache.james.mailbox.cassandra.table.BlobTable.BlobParts;
@@ -106,16 +106,16 @@ public class CassandraBlobsDAO {
             .value(BlobParts.DATA, bindMarker(BlobParts.DATA)));
     }
 
-    public CompletableFuture<BlobId> save(byte[] data) {
+    public CompletableFuture<CassandraBlobId> save(byte[] data) {
         Preconditions.checkNotNull(data);
 
-        BlobId blobId = BlobId.forPayload(data);
+        CassandraBlobId blobId = CassandraBlobId.forPayload(data);
         return saveBlobParts(data, blobId)
             .thenCompose(numberOfChunk -> saveBlobPartsReferences(blobId, numberOfChunk))
             .thenApply(any -> blobId);
     }
 
-    private CompletableFuture<Integer> saveBlobParts(byte[] data, BlobId blobId) {
+    private CompletableFuture<Integer> saveBlobParts(byte[] data, CassandraBlobId blobId) {
         return FluentFutureStream.of(
             dataChunker.chunk(data, configuration.getBlobPartSize())
                 .map(pair -> writePart(pair.getRight(), blobId, pair.getKey())
@@ -131,29 +131,29 @@ public class CassandraBlobsDAO {
         return stream.reduce((first, second) -> second);
     }
 
-    private CompletableFuture<Void> writePart(ByteBuffer data, BlobId blobId, int position) {
+    private CompletableFuture<Void> writePart(ByteBuffer data, CassandraBlobId blobId, int position) {
         return cassandraAsyncExecutor.executeVoid(
             insertPart.bind()
-                .setString(BlobTable.ID, blobId.getId())
+                .setString(BlobTable.ID, blobId.asString())
                 .setInt(BlobParts.CHUNK_NUMBER, position)
                 .setBytes(BlobParts.DATA, data));
     }
 
-    private CompletableFuture<Void> saveBlobPartsReferences(BlobId blobId, int numberOfChunk) {
+    private CompletableFuture<Void> saveBlobPartsReferences(CassandraBlobId blobId, int numberOfChunk) {
         return cassandraAsyncExecutor.executeVoid(insert.bind()
-            .setString(BlobTable.ID, blobId.getId())
+            .setString(BlobTable.ID, blobId.asString())
             .setInt(BlobTable.NUMBER_OF_CHUNK, numberOfChunk));
     }
 
-    public CompletableFuture<byte[]> read(BlobId blobId) {
+    public CompletableFuture<byte[]> read(CassandraBlobId blobId) {
         return cassandraAsyncExecutor.executeSingleRow(
             select.bind()
-                .setString(BlobTable.ID, blobId.getId()))
+                .setString(BlobTable.ID, blobId.asString()))
             .thenCompose(row -> toDataParts(row, blobId))
             .thenApply(this::concatenateDataParts);
     }
 
-    private CompletableFuture<Stream<BlobPart>> toDataParts(Optional<Row> blobRowOptional, BlobId blobId) {
+    private CompletableFuture<Stream<BlobPart>> toDataParts(Optional<Row> blobRowOptional, CassandraBlobId blobId) {
         return blobRowOptional.map(blobRow -> {
             int numOfChunk = blobRow.getInt(BlobTable.NUMBER_OF_CHUNK);
             return FluentFutureStream.of(
@@ -184,20 +184,20 @@ public class CassandraBlobsDAO {
         return data;
     }
 
-    private CompletableFuture<BlobPart> readPart(BlobId blobId, int position) {
+    private CompletableFuture<BlobPart> readPart(CassandraBlobId blobId, int position) {
         return cassandraAsyncExecutor.executeSingleRow(
             selectPart.bind()
-                .setString(BlobTable.ID, blobId.getId())
+                .setString(BlobTable.ID, blobId.asString())
                 .setInt(BlobParts.CHUNK_NUMBER, position))
             .thenApply(row -> new BlobPart(blobId, position, row));
     }
 
     private static class BlobPart {
-        private final BlobId blobId;
+        private final CassandraBlobId blobId;
         private final int position;
         private final Optional<Row> row;
 
-        public BlobPart(BlobId blobId, int position, Optional<Row> row) {
+        public BlobPart(CassandraBlobId blobId, int position, Optional<Row> row) {
             Preconditions.checkNotNull(blobId);
             Preconditions.checkArgument(position >= 0, "position need to be positive");
             this.blobId = blobId;

http://git-wip-us.apache.org/repos/asf/james-project/blob/68e099ce/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java
index 83477fb..c80f982 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java
@@ -59,7 +59,7 @@ import org.apache.james.backends.cassandra.init.CassandraConfiguration;
 import org.apache.james.backends.cassandra.init.CassandraTypesProvider;
 import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
-import org.apache.james.mailbox.cassandra.ids.BlobId;
+import org.apache.james.blob.cassandra.CassandraBlobId;
 import org.apache.james.mailbox.cassandra.ids.CassandraMessageId;
 import org.apache.james.mailbox.cassandra.mail.utils.Limit;
 import org.apache.james.mailbox.cassandra.table.CassandraMessageV2Table;
@@ -176,7 +176,7 @@ public class CassandraMessageDAO {
             cassandraAsyncExecutor.executeVoid(boundWriteStatement(message, pair)));
     }
 
-    private CompletableFuture<Pair<BlobId, BlobId>> saveContent(MailboxMessage message) throws MailboxException {
+    private CompletableFuture<Pair<CassandraBlobId, CassandraBlobId>> saveContent(MailboxMessage message) throws MailboxException {
         try {
             return CompletableFutureUtil.combine(
                 blobsDAO.save(
@@ -191,7 +191,7 @@ public class CassandraMessageDAO {
         }
     }
 
-    private BoundStatement boundWriteStatement(MailboxMessage message, Pair<BlobId, BlobId> pair) {
+    private BoundStatement boundWriteStatement(MailboxMessage message, Pair<CassandraBlobId, CassandraBlobId> pair) {
         CassandraMessageId messageId = (CassandraMessageId) message.getMessageId();
         return insert.bind()
             .setUUID(MESSAGE_ID, messageId.get())
@@ -199,8 +199,8 @@ public class CassandraMessageDAO {
             .setInt(BODY_START_OCTET, (int) (message.getHeaderOctets()))
             .setLong(FULL_CONTENT_OCTETS, message.getFullContentOctets())
             .setLong(BODY_OCTECTS, message.getBodyOctets())
-            .setString(BODY_CONTENT, pair.getRight().getId())
-            .setString(HEADER_CONTENT, pair.getLeft().getId())
+            .setString(BODY_CONTENT, pair.getRight().asString())
+            .setString(HEADER_CONTENT, pair.getLeft().asString())
             .setLong(TEXTUAL_LINE_COUNT, Optional.ofNullable(message.getTextualLineCount()).orElse(DEFAULT_LONG_VALUE))
             .setList(PROPERTIES, buildPropertiesUdt(message))
             .setList(ATTACHMENTS, buildAttachmentUdt(message));
@@ -370,7 +370,7 @@ public class CassandraMessageDAO {
     }
 
     private CompletableFuture<byte[]> getFieldContent(String field, Row row) {
-        return blobsDAO.read(BlobId.from(row.getString(field)));
+        return blobsDAO.read(CassandraBlobId.from(row.getString(field)));
     }
 
     public static MessageResult notFound(ComposedMessageIdWithMetaData id) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/68e099ce/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/ids/BlobIdTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/ids/BlobIdTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/ids/BlobIdTest.java
deleted file mode 100644
index e8e3f13..0000000
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/ids/BlobIdTest.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.mailbox.cassandra.ids;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.nio.charset.StandardCharsets;
-
-import org.apache.james.util.ClassLoaderUtils;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-import nl.jqno.equalsverifier.EqualsVerifier;
-
-public class BlobIdTest {
-
-    @Rule
-    public ExpectedException expectedException = ExpectedException.none();
-
-    @Test
-    public void shouldRespectBeanContract() {
-        EqualsVerifier.forClass(BlobId.class).verify();
-    }
-
-    @Test
-    public void fromShouldConstructBlobId() {
-        String id = "111";
-        assertThat(BlobId.from(id))
-            .isEqualTo(new BlobId(id));
-    }
-
-    @Test
-    public void fromShouldThrowOnNull() {
-        expectedException.expect(IllegalArgumentException.class);
-
-        BlobId.from(null);
-    }
-
-    @Test
-    public void fromShouldThrowOnEmpty() {
-        expectedException.expect(IllegalArgumentException.class);
-
-        BlobId.from("");
-    }
-
-    @Test
-    public void forPayloadShouldThrowOnNull() {
-        expectedException.expect(IllegalArgumentException.class);
-
-        BlobId.forPayload(null);
-    }
-
-    @Test
-    public void forPayloadShouldHashEmptyArray() {
-        BlobId blobId = BlobId.forPayload(new byte[0]);
-
-        assertThat(blobId.getId()).isEqualTo("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
-    }
-
-    @Test
-    public void forPayloadShouldHashArray() {
-        BlobId blobId = BlobId.forPayload("content".getBytes(StandardCharsets.UTF_8));
-
-        assertThat(blobId.getId()).isEqualTo("ed7002b439e9ac845f22357d822bac1444730fbdb6016d3ec9432297b9ec9f73");
-    }
-
-    @Test
-    public void forPayloadShouldCalculateDifferentHashesWhenCraftedSha1Collision() throws Exception {
-        byte[] payload1 = ClassLoaderUtils.getSystemResourceAsByteArray("shattered-1.pdf");
-        byte[] payload2 = ClassLoaderUtils.getSystemResourceAsByteArray("shattered-2.pdf");
-        BlobId blobId1 = BlobId.forPayload(payload1);
-        BlobId blobId2 = BlobId.forPayload(payload2);
-        assertThat(blobId1).isNotEqualTo(blobId2);
-    }
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/68e099ce/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2Test.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2Test.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2Test.java
index 84e19bc..f5a8285 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2Test.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOV2Test.java
@@ -26,7 +26,7 @@ import java.util.Optional;
 
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.DockerCassandraRule;
-import org.apache.james.mailbox.cassandra.ids.BlobId;
+import org.apache.james.blob.cassandra.CassandraBlobId;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAOV2.DAOAttachment;
 import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule;
 import org.apache.james.mailbox.model.Attachment;
@@ -75,7 +75,7 @@ public class CassandraAttachmentDAOV2Test {
             .type("application/json")
             .bytes("{\"property\":`\"value\"}".getBytes(StandardCharsets.UTF_8))
             .build();
-        BlobId blobId = BlobId.from("blobId");
+        CassandraBlobId blobId = CassandraBlobId.from("blobId");
         DAOAttachment daoAttachment = CassandraAttachmentDAOV2.from(attachment, blobId);
         testee.storeAttachment(daoAttachment).join();
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/68e099ce/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentFallbackTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentFallbackTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentFallbackTest.java
index 6ac6409..4c42a2d 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentFallbackTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentFallbackTest.java
@@ -29,7 +29,7 @@ import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.init.CassandraConfiguration;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
-import org.apache.james.mailbox.cassandra.ids.BlobId;
+import org.apache.james.blob.cassandra.CassandraBlobId;
 import org.apache.james.mailbox.cassandra.ids.CassandraMessageId;
 import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule;
@@ -108,7 +108,7 @@ public class CassandraAttachmentFallbackTest {
             .bytes("{\"property\":`\"different\"}".getBytes(StandardCharsets.UTF_8))
             .build();
 
-        BlobId blobId = blobsDAO.save(attachment.getBytes()).join();
+        CassandraBlobId blobId = blobsDAO.save(attachment.getBytes()).join();
         attachmentDAOV2.storeAttachment(CassandraAttachmentDAOV2.from(attachment, blobId)).join();
         attachmentDAO.storeAttachment(otherAttachment).join();
 
@@ -143,7 +143,7 @@ public class CassandraAttachmentFallbackTest {
             .bytes("{\"property\":`\"different\"}".getBytes(StandardCharsets.UTF_8))
             .build();
 
-        BlobId blobId = blobsDAO.save(attachment.getBytes()).join();
+        CassandraBlobId blobId = blobsDAO.save(attachment.getBytes()).join();
         attachmentDAOV2.storeAttachment(CassandraAttachmentDAOV2.from(attachment, blobId)).join();
         attachmentDAO.storeAttachment(otherAttachment).join();
 
@@ -178,7 +178,7 @@ public class CassandraAttachmentFallbackTest {
             .bytes("{\"property\":`\"different\"}".getBytes(StandardCharsets.UTF_8))
             .build();
 
-        BlobId blobId = blobsDAO.save(attachment.getBytes()).join();
+        CassandraBlobId blobId = blobsDAO.save(attachment.getBytes()).join();
         attachmentDAOV2.storeAttachment(CassandraAttachmentDAOV2.from(attachment, blobId)).join();
         attachmentDAO.storeAttachment(otherAttachment).join();
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/68e099ce/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraBlobsDAOTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraBlobsDAOTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraBlobsDAOTest.java
index 9709bb4..e92316a 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraBlobsDAOTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraBlobsDAOTest.java
@@ -28,7 +28,7 @@ import java.nio.charset.StandardCharsets;
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.init.CassandraConfiguration;
-import org.apache.james.mailbox.cassandra.ids.BlobId;
+import org.apache.james.blob.cassandra.CassandraBlobId;
 import org.apache.james.mailbox.cassandra.modules.CassandraBlobModule;
 import org.junit.After;
 import org.junit.Before;
@@ -70,7 +70,7 @@ public class CassandraBlobsDAOTest {
 
     @Test
     public void saveShouldSaveEmptyData() throws Exception {
-        BlobId blobId = testee.save(new byte[]{}).join();
+        CassandraBlobId blobId = testee.save(new byte[]{}).join();
 
         byte[] bytes = testee.read(blobId).join();
 
@@ -79,7 +79,7 @@ public class CassandraBlobsDAOTest {
 
     @Test
     public void saveShouldSaveBlankData() throws Exception {
-        BlobId blobId = testee.save("".getBytes(StandardCharsets.UTF_8)).join();
+        CassandraBlobId blobId = testee.save("".getBytes(StandardCharsets.UTF_8)).join();
 
         byte[] bytes = testee.read(blobId).join();
 
@@ -88,21 +88,21 @@ public class CassandraBlobsDAOTest {
 
     @Test
     public void saveShouldReturnBlobId() throws Exception {
-        BlobId blobId = testee.save("toto".getBytes(StandardCharsets.UTF_8)).join();
+        CassandraBlobId blobId = testee.save("toto".getBytes(StandardCharsets.UTF_8)).join();
 
-        assertThat(blobId).isEqualTo(BlobId.from("31f7a65e315586ac198bd798b6629ce4903d0899476d5741a9f32e2e521b6a66"));
+        assertThat(blobId).isEqualTo(CassandraBlobId.from("31f7a65e315586ac198bd798b6629ce4903d0899476d5741a9f32e2e521b6a66"));
     }
 
     @Test
     public void readShouldBeEmptyWhenNoExisting() throws IOException {
-        byte[] bytes = testee.read(BlobId.from("unknown")).join();
+        byte[] bytes = testee.read(CassandraBlobId.from("unknown")).join();
 
         assertThat(bytes).isEmpty();
     }
 
     @Test
     public void readShouldReturnSavedData() throws IOException {
-        BlobId blobId = testee.save("toto".getBytes(StandardCharsets.UTF_8)).join();
+        CassandraBlobId blobId = testee.save("toto".getBytes(StandardCharsets.UTF_8)).join();
 
         byte[] bytes = testee.read(blobId).join();
 
@@ -112,7 +112,7 @@ public class CassandraBlobsDAOTest {
     @Test
     public void readShouldReturnLongSavedData() throws IOException {
         String longString = Strings.repeat("0123456789\n", 1000);
-        BlobId blobId = testee.save(longString.getBytes(StandardCharsets.UTF_8)).join();
+        CassandraBlobId blobId = testee.save(longString.getBytes(StandardCharsets.UTF_8)).join();
 
         byte[] bytes = testee.read(blobId).join();
 
@@ -122,7 +122,7 @@ public class CassandraBlobsDAOTest {
     @Test
     public void readShouldReturnSplitSavedDataByChunk() throws IOException {
         String longString = Strings.repeat("0123456789\n", MULTIPLE_CHUNK_SIZE);
-        BlobId blobId = testee.save(longString.getBytes(StandardCharsets.UTF_8)).join();
+        CassandraBlobId blobId = testee.save(longString.getBytes(StandardCharsets.UTF_8)).join();
 
         byte[] bytes = testee.read(blobId).join();
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/68e099ce/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2MigrationTest.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2MigrationTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2MigrationTest.java
index 0f456ac..b53205e 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2MigrationTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2MigrationTest.java
@@ -34,7 +34,7 @@ import org.apache.james.backends.cassandra.init.CassandraConfiguration;
 import org.apache.james.backends.cassandra.init.CassandraModuleComposite;
 import org.apache.james.backends.cassandra.migration.Migration;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
-import org.apache.james.mailbox.cassandra.ids.BlobId;
+import org.apache.james.blob.cassandra.CassandraBlobId;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAOV2;
 import org.apache.james.mailbox.cassandra.mail.CassandraBlobsDAO;
@@ -112,12 +112,12 @@ public class AttachmentV2MigrationTest {
         migration.run();
 
         assertThat(attachmentDAOV2.getAttachment(ATTACHMENT_ID).join())
-            .contains(CassandraAttachmentDAOV2.from(attachment1, BlobId.forPayload(attachment1.getBytes())));
+            .contains(CassandraAttachmentDAOV2.from(attachment1, CassandraBlobId.forPayload(attachment1.getBytes())));
         assertThat(attachmentDAOV2.getAttachment(ATTACHMENT_ID_2).join())
-            .contains(CassandraAttachmentDAOV2.from(attachment2, BlobId.forPayload(attachment2.getBytes())));
-        assertThat(blobsDAO.read(BlobId.forPayload(attachment1.getBytes())).join())
+            .contains(CassandraAttachmentDAOV2.from(attachment2, CassandraBlobId.forPayload(attachment2.getBytes())));
+        assertThat(blobsDAO.read(CassandraBlobId.forPayload(attachment1.getBytes())).join())
             .isEqualTo(attachment1.getBytes());
-        assertThat(blobsDAO.read(BlobId.forPayload(attachment2.getBytes())).join())
+        assertThat(blobsDAO.read(CassandraBlobId.forPayload(attachment2.getBytes())).join())
             .isEqualTo(attachment2.getBytes());
     }
 
@@ -172,9 +172,9 @@ public class AttachmentV2MigrationTest {
             attachment1,
             attachment2));
         when(blobsDAO.save(attachment1.getBytes()))
-            .thenReturn(CompletableFuture.completedFuture(BlobId.forPayload(attachment1.getBytes())));
+            .thenReturn(CompletableFuture.completedFuture(CassandraBlobId.forPayload(attachment1.getBytes())));
         when(blobsDAO.save(attachment2.getBytes()))
-            .thenReturn(CompletableFuture.completedFuture(BlobId.forPayload(attachment2.getBytes())));
+            .thenReturn(CompletableFuture.completedFuture(CassandraBlobId.forPayload(attachment2.getBytes())));
         when(attachmentDAOV2.storeAttachment(any())).thenThrow(new RuntimeException());
 
         assertThat(migration.run()).isEqualTo(Migration.Result.PARTIAL);
@@ -191,9 +191,9 @@ public class AttachmentV2MigrationTest {
             attachment1,
             attachment2));
         when(blobsDAO.save(attachment1.getBytes()))
-            .thenReturn(CompletableFuture.completedFuture(BlobId.forPayload(attachment1.getBytes())));
+            .thenReturn(CompletableFuture.completedFuture(CassandraBlobId.forPayload(attachment1.getBytes())));
         when(blobsDAO.save(attachment2.getBytes()))
-            .thenReturn(CompletableFuture.completedFuture(BlobId.forPayload(attachment2.getBytes())));
+            .thenReturn(CompletableFuture.completedFuture(CassandraBlobId.forPayload(attachment2.getBytes())));
         when(attachmentDAOV2.storeAttachment(any())).thenReturn(CompletableFuture.completedFuture(null));
         when(attachmentDAO.deleteAttachment(any())).thenThrow(new RuntimeException());
 
@@ -211,7 +211,7 @@ public class AttachmentV2MigrationTest {
             attachment1,
             attachment2));
         when(blobsDAO.save(attachment1.getBytes()))
-            .thenReturn(CompletableFuture.completedFuture(BlobId.forPayload(attachment1.getBytes())));
+            .thenReturn(CompletableFuture.completedFuture(CassandraBlobId.forPayload(attachment1.getBytes())));
         when(blobsDAO.save(attachment2.getBytes()))
             .thenThrow(new RuntimeException());
         when(attachmentDAOV2.storeAttachment(any())).thenReturn(CompletableFuture.completedFuture(null));

http://git-wip-us.apache.org/repos/asf/james-project/blob/68e099ce/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 420ffaa..edf90d3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -975,6 +975,11 @@
             </dependency>
             <dependency>
                 <groupId>${project.groupId}</groupId>
+                <artifactId>blob-cassandra</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>${project.groupId}</groupId>
                 <artifactId>james-server-cassandra-guice</artifactId>
                 <version>${project.version}</version>
             </dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/68e099ce/server/blob/blob-cassandra/pom.xml
----------------------------------------------------------------------
diff --git a/server/blob/blob-cassandra/pom.xml b/server/blob/blob-cassandra/pom.xml
new file mode 100644
index 0000000..387d222
--- /dev/null
+++ b/server/blob/blob-cassandra/pom.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <artifactId>james-server-blob</artifactId>
+        <groupId>org.apache.james</groupId>
+        <version>3.1.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>blob-cassandra</artifactId>
+    <packaging>jar</packaging>
+
+    <name>Apache James :: Server :: Blob :: Cassandra</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>blob-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>james-server-util-java8</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>nl.jqno.equalsverifier</groupId>
+            <artifactId>equalsverifier</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.platform</groupId>
+            <artifactId>junit-platform-launcher</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    
+</project>

http://git-wip-us.apache.org/repos/asf/james-project/blob/68e099ce/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobId.java
----------------------------------------------------------------------
diff --git a/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobId.java b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobId.java
new file mode 100644
index 0000000..5dba57e
--- /dev/null
+++ b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobId.java
@@ -0,0 +1,76 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.blob.cassandra;
+
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.james.blob.api.BlobId;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+
+public class CassandraBlobId implements BlobId {
+
+    public static CassandraBlobId forPayload(byte[] payload) {
+        Preconditions.checkArgument(payload != null);
+        return new CassandraBlobId(DigestUtils.sha256Hex(payload));
+    }
+
+    public static CassandraBlobId from(String id) {
+        Preconditions.checkArgument(!Strings.isNullOrEmpty(id));
+        return new CassandraBlobId(id);
+    }
+
+    private final String id;
+
+    @VisibleForTesting
+    CassandraBlobId(String id) {
+        this.id = id;
+    }
+
+    @Override
+    public String asString() {
+        return id;
+    }
+
+    @Override
+    public final boolean equals(Object obj) {
+        if (obj instanceof CassandraBlobId) {
+            CassandraBlobId other = (CassandraBlobId) obj;
+            return Objects.equal(id, other.id);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hashCode(id);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects
+            .toStringHelper(this)
+            .add("id", id)
+            .toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/68e099ce/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobIdTest.java
----------------------------------------------------------------------
diff --git a/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobIdTest.java b/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobIdTest.java
new file mode 100644
index 0000000..2fe0db2
--- /dev/null
+++ b/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobIdTest.java
@@ -0,0 +1,86 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.blob.cassandra;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.nio.charset.StandardCharsets;
+
+import org.apache.james.util.ClassLoaderUtils;
+import org.junit.jupiter.api.Test;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+
+public class CassandraBlobIdTest {
+
+    @Test
+    public void shouldRespectBeanContract() {
+        EqualsVerifier.forClass(CassandraBlobId.class).verify();
+    }
+
+    @Test
+    public void fromShouldConstructBlobId() {
+        String id = "111";
+        assertThat(CassandraBlobId.from(id))
+            .isEqualTo(new CassandraBlobId(id));
+    }
+
+    @Test
+    public void fromShouldThrowOnNull() {
+        assertThatThrownBy(() -> CassandraBlobId.from(null))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void fromShouldThrowOnEmpty() {
+        assertThatThrownBy(() -> CassandraBlobId.from(""))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void forPayloadShouldThrowOnNull() {
+        assertThatThrownBy(() -> CassandraBlobId.forPayload(null))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void forPayloadShouldHashEmptyArray() {
+        CassandraBlobId blobId = CassandraBlobId.forPayload(new byte[0]);
+
+        assertThat(blobId.asString()).isEqualTo("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
+    }
+
+    @Test
+    public void forPayloadShouldHashArray() {
+        CassandraBlobId blobId = CassandraBlobId.forPayload("content".getBytes(StandardCharsets.UTF_8));
+
+        assertThat(blobId.asString()).isEqualTo("ed7002b439e9ac845f22357d822bac1444730fbdb6016d3ec9432297b9ec9f73");
+    }
+
+    @Test
+    public void forPayloadShouldCalculateDifferentHashesWhenCraftedSha1Collision() throws Exception {
+        byte[] payload1 = ClassLoaderUtils.getSystemResourceAsByteArray("shattered-1.pdf");
+        byte[] payload2 = ClassLoaderUtils.getSystemResourceAsByteArray("shattered-2.pdf");
+        CassandraBlobId blobId1 = CassandraBlobId.forPayload(payload1);
+        CassandraBlobId blobId2 = CassandraBlobId.forPayload(payload2);
+        assertThat(blobId1).isNotEqualTo(blobId2);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/68e099ce/server/blob/blob-cassandra/src/test/resources/shattered-1.pdf
----------------------------------------------------------------------
diff --git a/server/blob/blob-cassandra/src/test/resources/shattered-1.pdf b/server/blob/blob-cassandra/src/test/resources/shattered-1.pdf
new file mode 100644
index 0000000..ba9aaa1
Binary files /dev/null and b/server/blob/blob-cassandra/src/test/resources/shattered-1.pdf differ

http://git-wip-us.apache.org/repos/asf/james-project/blob/68e099ce/server/blob/blob-cassandra/src/test/resources/shattered-2.pdf
----------------------------------------------------------------------
diff --git a/server/blob/blob-cassandra/src/test/resources/shattered-2.pdf b/server/blob/blob-cassandra/src/test/resources/shattered-2.pdf
new file mode 100644
index 0000000..b621eec
Binary files /dev/null and b/server/blob/blob-cassandra/src/test/resources/shattered-2.pdf differ

http://git-wip-us.apache.org/repos/asf/james-project/blob/68e099ce/server/blob/pom.xml
----------------------------------------------------------------------
diff --git a/server/blob/pom.xml b/server/blob/pom.xml
index d86a2bd..21cfffb 100644
--- a/server/blob/pom.xml
+++ b/server/blob/pom.xml
@@ -34,6 +34,7 @@
 
     <modules>
         <module>blob-api</module>
+        <module>blob-cassandra</module>
     </modules>
 
 </project>


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[06/13] james-project git commit: JAMES-2287 Introduce a JUnit 5 extension for Cassandra in Docker

Posted by bt...@apache.org.
JAMES-2287 Introduce a JUnit 5 extension for Cassandra in Docker


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

Branch: refs/heads/master
Commit: 12074ca0a8da1408a3ddde233cda6e094fa806ae
Parents: 5796a95
Author: Antoine Duprat <ad...@linagora.com>
Authored: Mon Jan 15 16:11:04 2018 +0100
Committer: benwa <bt...@linagora.com>
Committed: Fri Jan 19 09:07:27 2018 +0700

----------------------------------------------------------------------
 backends-common/cassandra/pom.xml               | 20 +++--
 .../cassandra/DockerCassandraExtension.java     | 86 ++++++++++++++++++++
 server/blob/blob-api/pom.xml                    |  8 +-
 .../james/blob/api/ObjectStoreContract.java     | 11 +++
 4 files changed, 116 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/12074ca0/backends-common/cassandra/pom.xml
----------------------------------------------------------------------
diff --git a/backends-common/cassandra/pom.xml b/backends-common/cassandra/pom.xml
index 36aa204..9b74931 100644
--- a/backends-common/cassandra/pom.xml
+++ b/backends-common/cassandra/pom.xml
@@ -76,11 +76,6 @@
             <artifactId>javax.inject</artifactId>
         </dependency>
         <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
             <groupId>net.javacrumbs.future-converter</groupId>
             <artifactId>future-converter-java8-guava</artifactId>
             <version>0.3.0</version>
@@ -104,6 +99,21 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.platform</groupId>
+            <artifactId>junit-platform-launcher</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.vintage</groupId>
+            <artifactId>junit-vintage-engine</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>org.mockito</groupId>
             <artifactId>mockito-core</artifactId>
             <scope>test</scope>

http://git-wip-us.apache.org/repos/asf/james-project/blob/12074ca0/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandraExtension.java
----------------------------------------------------------------------
diff --git a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandraExtension.java b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandraExtension.java
new file mode 100644
index 0000000..98b16fc
--- /dev/null
+++ b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandraExtension.java
@@ -0,0 +1,86 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.backends.cassandra;
+
+import org.junit.jupiter.api.extension.AfterEachCallback;
+import org.junit.jupiter.api.extension.BeforeEachCallback;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.api.extension.ParameterContext;
+import org.junit.jupiter.api.extension.ParameterResolutionException;
+import org.junit.jupiter.api.extension.ParameterResolver;
+import org.testcontainers.containers.GenericContainer;
+
+
+public class DockerCassandraExtension implements BeforeEachCallback, AfterEachCallback, ParameterResolver {
+
+    private final DockerCassandraRule cassandraContainer;
+    private DockerCassandra dockerCassandra;
+
+    public DockerCassandraExtension() {
+        cassandraContainer = new DockerCassandraRule();
+    }
+
+    @Override
+    public void beforeEach(ExtensionContext context) throws Exception {
+        cassandraContainer.start();
+        dockerCassandra = DockerCassandra.from(cassandraContainer.getRawContainer());
+    }
+
+    @Override
+    public void afterEach(ExtensionContext context) throws Exception {
+        cassandraContainer.stop();
+    }
+
+    @Override
+    public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
+        return (parameterContext.getParameter().getType() == DockerCassandra.class);
+    }
+
+    @Override
+    public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
+        return dockerCassandra;
+    }
+    
+    public static class DockerCassandra {
+        
+        private static final int CASSANDRA_PORT = 9042;
+
+        public static DockerCassandra from(GenericContainer<?> cassandraContainer) {
+            return new DockerCassandra(cassandraContainer.getContainerIpAddress(), cassandraContainer.getMappedPort(CASSANDRA_PORT));
+        }
+
+        private final String ip;
+        private final int bindingPort;
+
+        private DockerCassandra(String ip, int bindingPort) {
+            this.ip = ip;
+            this.bindingPort = bindingPort;
+        }
+
+        public String getIp() {
+            return ip;
+        }
+    
+        public int getBindingPort() {
+            return bindingPort;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/12074ca0/server/blob/blob-api/pom.xml
----------------------------------------------------------------------
diff --git a/server/blob/blob-api/pom.xml b/server/blob/blob-api/pom.xml
index d15765a..9cc1d92 100644
--- a/server/blob/blob-api/pom.xml
+++ b/server/blob/blob-api/pom.xml
@@ -51,8 +51,8 @@
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.junit.platform</groupId>
-            <artifactId>junit-platform-launcher</artifactId>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
@@ -61,8 +61,8 @@
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.assertj</groupId>
-            <artifactId>assertj-core</artifactId>
+            <groupId>org.junit.platform</groupId>
+            <artifactId>junit-platform-launcher</artifactId>
             <scope>test</scope>
         </dependency>
     </dependencies>

http://git-wip-us.apache.org/repos/asf/james-project/blob/12074ca0/server/blob/blob-api/src/test/java/org/apache/james/blob/api/ObjectStoreContract.java
----------------------------------------------------------------------
diff --git a/server/blob/blob-api/src/test/java/org/apache/james/blob/api/ObjectStoreContract.java b/server/blob/blob-api/src/test/java/org/apache/james/blob/api/ObjectStoreContract.java
index 61b5718..2cbab37 100644
--- a/server/blob/blob-api/src/test/java/org/apache/james/blob/api/ObjectStoreContract.java
+++ b/server/blob/blob-api/src/test/java/org/apache/james/blob/api/ObjectStoreContract.java
@@ -80,4 +80,15 @@ public interface ObjectStoreContract {
 
         assertThat(new String(bytes, StandardCharsets.UTF_8)).isEqualTo(longString);
     }
+
+    @Test
+    default void readShouldReturnBigSavedData() throws IOException {
+        // 12 MB of text
+        String bigString = Strings.repeat("0123456789\r\n", 1024 * 1024);
+        BlobId blobId = testee().save(bigString.getBytes(StandardCharsets.UTF_8)).join();
+
+        byte[] bytes = testee().read(blobId).join();
+
+        assertThat(new String(bytes, StandardCharsets.UTF_8)).isEqualTo(bigString);
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[04/13] james-project git commit: JAMES-2287 Introduce the james-server-blob-api module

Posted by bt...@apache.org.
JAMES-2287 Introduce the james-server-blob-api module


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

Branch: refs/heads/master
Commit: 894647e1248d2629d251166f55d2aac8772aa092
Parents: c668025
Author: Antoine Duprat <ad...@linagora.com>
Authored: Tue Jan 16 10:48:27 2018 +0100
Committer: benwa <bt...@linagora.com>
Committed: Fri Jan 19 09:06:42 2018 +0700

----------------------------------------------------------------------
 pom.xml                      |  5 +++++
 server/blob/blob-api/pom.xml | 38 ++++++++++++++++++++++++++++++++++++++
 server/blob/pom.xml          | 39 +++++++++++++++++++++++++++++++++++++++
 server/pom.xml               |  2 ++
 4 files changed, 84 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/894647e1/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index d4988bd..420ffaa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -970,6 +970,11 @@
             </dependency>
             <dependency>
                 <groupId>${project.groupId}</groupId>
+                <artifactId>blob-api</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>${project.groupId}</groupId>
                 <artifactId>james-server-cassandra-guice</artifactId>
                 <version>${project.version}</version>
             </dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/894647e1/server/blob/blob-api/pom.xml
----------------------------------------------------------------------
diff --git a/server/blob/blob-api/pom.xml b/server/blob/blob-api/pom.xml
new file mode 100644
index 0000000..b0cd9b7
--- /dev/null
+++ b/server/blob/blob-api/pom.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <artifactId>james-server-blob</artifactId>
+        <groupId>org.apache.james</groupId>
+        <version>3.1.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>blob-api</artifactId>
+    <packaging>jar</packaging>
+
+    <name>Apache James :: Server :: Blob :: API</name>
+
+    <dependencies>
+    </dependencies>
+    
+</project>

http://git-wip-us.apache.org/repos/asf/james-project/blob/894647e1/server/blob/pom.xml
----------------------------------------------------------------------
diff --git a/server/blob/pom.xml b/server/blob/pom.xml
new file mode 100644
index 0000000..d86a2bd
--- /dev/null
+++ b/server/blob/pom.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.james</groupId>
+        <artifactId>james-server</artifactId>
+        <version>3.1.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>james-server-blob</artifactId>
+    <packaging>pom</packaging>
+    <name>Apache James :: Server :: Blob</name>
+
+    <modules>
+        <module>blob-api</module>
+    </modules>
+
+</project>

http://git-wip-us.apache.org/repos/asf/james-project/blob/894647e1/server/pom.xml
----------------------------------------------------------------------
diff --git a/server/pom.xml b/server/pom.xml
index f586a1a..5615df5 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -40,6 +40,8 @@
     <modules>
         <module>app</module>
 
+        <module>blob</module>
+
         <module>container/cli</module>
         <module>container/cli-integration</module>
         <module>container/core</module>


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[10/13] james-project git commit: JAMES-2287 Guice injections for object store

Posted by bt...@apache.org.
JAMES-2287 Guice injections for object store


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

Branch: refs/heads/master
Commit: 4db46a880c2a0de25ef6c957b5b5756528a78403
Parents: 63a6a14
Author: benwa <bt...@linagora.com>
Authored: Wed Jan 17 11:57:04 2018 +0700
Committer: benwa <bt...@linagora.com>
Committed: Fri Jan 19 09:07:28 2018 +0700

----------------------------------------------------------------------
 server/container/guice/cassandra-guice/pom.xml  |  5 +++
 .../modules/mailbox/CassandraMailboxModule.java |  3 +-
 .../mailbox/CassandraObjectStoreModule.java     | 39 ++++++++++++++++++++
 3 files changed, 45 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/4db46a88/server/container/guice/cassandra-guice/pom.xml
----------------------------------------------------------------------
diff --git a/server/container/guice/cassandra-guice/pom.xml b/server/container/guice/cassandra-guice/pom.xml
index aba7dd0..db90008 100644
--- a/server/container/guice/cassandra-guice/pom.xml
+++ b/server/container/guice/cassandra-guice/pom.xml
@@ -93,6 +93,11 @@
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
+            <artifactId>blob-cassandra</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
             <artifactId>james-server-data-cassandra</artifactId>
         </dependency>
         <dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/4db46a88/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java
index 3d1c404..0bd19a1 100644
--- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java
+++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java
@@ -23,7 +23,6 @@ import javax.inject.Singleton;
 import org.apache.james.adapter.mailbox.store.UserRepositoryAuthenticator;
 import org.apache.james.adapter.mailbox.store.UserRepositoryAuthorizator;
 import org.apache.james.backends.cassandra.components.CassandraModule;
-import org.apache.james.blob.cassandra.CassandraBlobsDAO;
 import org.apache.james.mailbox.AttachmentManager;
 import org.apache.james.mailbox.BlobManager;
 import org.apache.james.mailbox.MailboxListener;
@@ -94,13 +93,13 @@ public class CassandraMailboxModule extends AbstractModule {
     protected void configure() {
         install(new DefaultEventModule());
         install(new CassandraQuotaModule());
+        install(new CassandraObjectStoreModule());
 
         bind(CassandraApplicableFlagDAO.class).in(Scopes.SINGLETON);
         bind(CassandraAttachmentDAO.class).in(Scopes.SINGLETON);
         bind(CassandraAttachmentDAOV2.class).in(Scopes.SINGLETON);
         bind(CassandraAttachmentMessageIdDAO.class).in(Scopes.SINGLETON);
         bind(CassandraAttachmentOwnerDAO.class).in(Scopes.SINGLETON);
-        bind(CassandraBlobsDAO.class).in(Scopes.SINGLETON);
         bind(CassandraDeletedMessageDAO.class).in(Scopes.SINGLETON);
         bind(CassandraFirstUnseenDAO.class).in(Scopes.SINGLETON);
         bind(CassandraMailboxCounterDAO.class).in(Scopes.SINGLETON);

http://git-wip-us.apache.org/repos/asf/james-project/blob/4db46a88/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraObjectStoreModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraObjectStoreModule.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraObjectStoreModule.java
new file mode 100644
index 0000000..4fad8e3
--- /dev/null
+++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraObjectStoreModule.java
@@ -0,0 +1,39 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.modules.mailbox;
+
+import org.apache.james.blob.api.BlobId;
+import org.apache.james.blob.api.ObjectStore;
+import org.apache.james.blob.cassandra.CassandraBlobId;
+import org.apache.james.blob.cassandra.CassandraBlobsDAO;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Scopes;
+
+public class CassandraObjectStoreModule extends AbstractModule {
+    @Override
+    protected void configure() {
+        bind(CassandraBlobsDAO.class).in(Scopes.SINGLETON);
+        bind(CassandraBlobId.Factory.class).in(Scopes.SINGLETON);
+
+        bind(ObjectStore.class).to(CassandraBlobsDAO.class);
+        bind(BlobId.Factory.class).to(CassandraBlobId.Factory.class);
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[02/13] james-project git commit: JAMES-2310 Use LineBasedFrameDecoder instead of DelimiterBasedFrameDecoder

Posted by bt...@apache.org.
JAMES-2310 Use LineBasedFrameDecoder instead of DelimiterBasedFrameDecoder

The resulting decoder should be the same as before commit b4f1ed6 except
starttls handling. This is because delimiter decoder will try to use
line decoder *if* the delimiter is CRLF and LF AND the decoder is
not subclass of delimiter decoder. Therefore, before b4f1ed6 the
underlying decoder is actually line decoder, after that commit the
decoder became generic delimiter decoder which cause huge performance
drop (in my simple benchmark, using line decoder only take 60% time of
delimiter decoder to complete the same SMTP transcations).

The same applies to IMAP server's frame decoder.


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

Branch: refs/heads/master
Commit: a2b0345d3cc93201ecf142b4951fa69cb89cdb9b
Parents: 4247d88
Author: TzeKei Lee <ch...@gmail.com>
Authored: Tue Jan 16 23:59:44 2018 +0800
Committer: benwa <bt...@linagora.com>
Committed: Fri Jan 19 09:04:31 2018 +0700

----------------------------------------------------------------------
 .../AllButStartTlsDelimiterChannelHandler.java  | 79 -------------------
 .../AllButStartTlsLineBasedChannelHandler.java  | 80 ++++++++++++++++++++
 ...AllButStartTlsLineChannelHandlerFactory.java | 37 +++++++++
 ...rtTlsLineDelimiterChannelHandlerFactory.java | 38 ----------
 .../smtp/netty/NettyStartTlsSMTPServerTest.java |  4 +-
 .../james/imapserver/netty/IMAPServer.java      |  2 +-
 .../netty/ImapRequestFrameDecoder.java          |  4 +-
 .../SwitchableDelimiterBasedFrameDecoder.java   | 58 --------------
 .../netty/SwitchableLineBasedFrameDecoder.java  | 59 +++++++++++++++
 .../SwitchableLineBasedFrameDecoderFactory.java | 37 +++++++++
 ...leLineDelimiterBasedFrameDecoderFactory.java | 38 ----------
 .../james/smtpserver/netty/SMTPServer.java      |  4 +-
 12 files changed, 220 insertions(+), 220 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/a2b0345d/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/AllButStartTlsDelimiterChannelHandler.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/AllButStartTlsDelimiterChannelHandler.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/AllButStartTlsDelimiterChannelHandler.java
deleted file mode 100644
index b42f1d3..0000000
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/AllButStartTlsDelimiterChannelHandler.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-package org.apache.james.protocols.smtp;
-
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-import java.util.Locale;
-
-import org.apache.james.protocols.netty.HandlerConstants;
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.channel.Channel;
-import org.jboss.netty.channel.ChannelHandlerContext;
-import org.jboss.netty.channel.ChannelPipeline;
-import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
-
-import com.google.common.base.CharMatcher;
-import com.google.common.base.Splitter;
-
-
-public class AllButStartTlsDelimiterChannelHandler extends DelimiterBasedFrameDecoder {
-
-    private static final String STARTTLS = "starttls";
-    private final ChannelPipeline pipeline;
-
-    public AllButStartTlsDelimiterChannelHandler(ChannelPipeline pipeline, int maxFrameLength, boolean stripDelimiter, ChannelBuffer[] delimiters) {
-        super(maxFrameLength, stripDelimiter, delimiters);
-        this.pipeline = pipeline;
-    }
-
-    @Override
-    protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
-        SMTPSession session = (SMTPSession) pipeline.getContext(HandlerConstants.CORE_HANDLER).getAttachment();
-
-        if (session == null || session.needsCommandInjectionDetection()) {
-            String trimedLowerCasedInput = readAll(buffer).trim().toLowerCase(Locale.US);
-            if (hasCommandInjection(trimedLowerCasedInput)) {
-                throw new CommandInjectionDetectedException();
-            }
-        }
-        return super.decode(ctx, channel, buffer);
-    }
-
-    private String readAll(ChannelBuffer buffer) {
-        return buffer.toString(StandardCharsets.US_ASCII);
-    }
-
-    private boolean hasCommandInjection(String trimedLowerCasedInput) {
-        List<String> parts = Splitter.on(CharMatcher.anyOf("\r\n")).omitEmptyStrings()
-            .splitToList(trimedLowerCasedInput);
-
-        return hasInvalidStartTlsPart(parts) || multiPartsAndOneStartTls(parts);
-    }
-
-    private boolean multiPartsAndOneStartTls(List<String> parts) {
-        return parts.stream()
-            .anyMatch(line -> line.startsWith(STARTTLS)) && parts.size() > 1;
-    }
-
-    private boolean hasInvalidStartTlsPart(List<String> parts) {
-        return parts.stream()
-            .anyMatch(line -> line.startsWith(STARTTLS) && !line.endsWith(STARTTLS));
-    }
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/a2b0345d/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/AllButStartTlsLineBasedChannelHandler.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/AllButStartTlsLineBasedChannelHandler.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/AllButStartTlsLineBasedChannelHandler.java
new file mode 100644
index 0000000..eba24c6
--- /dev/null
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/AllButStartTlsLineBasedChannelHandler.java
@@ -0,0 +1,80 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+package org.apache.james.protocols.smtp;
+
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.james.protocols.netty.HandlerConstants;
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ChannelPipeline;
+import org.jboss.netty.handler.codec.frame.LineBasedFrameDecoder;
+
+import com.google.common.base.CharMatcher;
+import com.google.common.base.Splitter;
+
+
+public class AllButStartTlsLineBasedChannelHandler extends LineBasedFrameDecoder {
+
+    private static final String STARTTLS = "starttls";
+    private static final Boolean FAIL_FAST = true;
+    private final ChannelPipeline pipeline;
+
+    public AllButStartTlsLineBasedChannelHandler(ChannelPipeline pipeline, int maxFrameLength, boolean stripDelimiter) {
+        super(maxFrameLength, stripDelimiter, !FAIL_FAST);
+        this.pipeline = pipeline;
+    }
+
+    @Override
+    protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
+        SMTPSession session = (SMTPSession) pipeline.getContext(HandlerConstants.CORE_HANDLER).getAttachment();
+
+        if (session == null || session.needsCommandInjectionDetection()) {
+            String trimedLowerCasedInput = readAll(buffer).trim().toLowerCase(Locale.US);
+            if (hasCommandInjection(trimedLowerCasedInput)) {
+                throw new CommandInjectionDetectedException();
+            }
+        }
+        return super.decode(ctx, channel, buffer);
+    }
+
+    private String readAll(ChannelBuffer buffer) {
+        return buffer.toString(StandardCharsets.US_ASCII);
+    }
+
+    private boolean hasCommandInjection(String trimedLowerCasedInput) {
+        List<String> parts = Splitter.on(CharMatcher.anyOf("\r\n")).omitEmptyStrings()
+            .splitToList(trimedLowerCasedInput);
+
+        return hasInvalidStartTlsPart(parts) || multiPartsAndOneStartTls(parts);
+    }
+
+    private boolean multiPartsAndOneStartTls(List<String> parts) {
+        return parts.stream()
+            .anyMatch(line -> line.startsWith(STARTTLS)) && parts.size() > 1;
+    }
+
+    private boolean hasInvalidStartTlsPart(List<String> parts) {
+        return parts.stream()
+            .anyMatch(line -> line.startsWith(STARTTLS) && !line.endsWith(STARTTLS));
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/a2b0345d/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/AllButStartTlsLineChannelHandlerFactory.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/AllButStartTlsLineChannelHandlerFactory.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/AllButStartTlsLineChannelHandlerFactory.java
new file mode 100644
index 0000000..94d9b2f
--- /dev/null
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/AllButStartTlsLineChannelHandlerFactory.java
@@ -0,0 +1,37 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+package org.apache.james.protocols.smtp;
+
+import org.apache.james.protocols.netty.ChannelHandlerFactory;
+import org.jboss.netty.channel.ChannelHandler;
+import org.jboss.netty.channel.ChannelPipeline;
+
+public class AllButStartTlsLineChannelHandlerFactory implements ChannelHandlerFactory {
+
+    private int maxFrameLength;
+
+    public AllButStartTlsLineChannelHandlerFactory(int maxFrameLength) {
+        this.maxFrameLength = maxFrameLength;
+    }
+
+    @Override
+    public ChannelHandler create(ChannelPipeline pipeline) {
+        return new AllButStartTlsLineBasedChannelHandler(pipeline, maxFrameLength, false);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/a2b0345d/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/AllButStartTlsLineDelimiterChannelHandlerFactory.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/AllButStartTlsLineDelimiterChannelHandlerFactory.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/AllButStartTlsLineDelimiterChannelHandlerFactory.java
deleted file mode 100644
index 22939ff..0000000
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/AllButStartTlsLineDelimiterChannelHandlerFactory.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-package org.apache.james.protocols.smtp;
-
-import org.apache.james.protocols.netty.ChannelHandlerFactory;
-import org.jboss.netty.channel.ChannelHandler;
-import org.jboss.netty.channel.ChannelPipeline;
-import org.jboss.netty.handler.codec.frame.Delimiters;
-
-public class AllButStartTlsLineDelimiterChannelHandlerFactory implements ChannelHandlerFactory {
-
-    private int maxFrameLength;
-
-    public AllButStartTlsLineDelimiterChannelHandlerFactory(int maxFrameLength) {
-        this.maxFrameLength = maxFrameLength;
-    }
-
-    @Override
-    public ChannelHandler create(ChannelPipeline pipeline) {
-        return new AllButStartTlsDelimiterChannelHandler(pipeline, maxFrameLength, false, Delimiters.lineDelimiter());
-    }
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/a2b0345d/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/netty/NettyStartTlsSMTPServerTest.java
----------------------------------------------------------------------
diff --git a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/netty/NettyStartTlsSMTPServerTest.java b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/netty/NettyStartTlsSMTPServerTest.java
index 5e33b6d..996f69b 100644
--- a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/netty/NettyStartTlsSMTPServerTest.java
+++ b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/netty/NettyStartTlsSMTPServerTest.java
@@ -46,7 +46,7 @@ import org.apache.james.protocols.api.utils.BogusTrustManagerFactory;
 import org.apache.james.protocols.api.utils.ProtocolServerUtils;
 import org.apache.james.protocols.netty.AbstractChannelPipelineFactory;
 import org.apache.james.protocols.netty.NettyServer;
-import org.apache.james.protocols.smtp.AllButStartTlsLineDelimiterChannelHandlerFactory;
+import org.apache.james.protocols.smtp.AllButStartTlsLineChannelHandlerFactory;
 import org.apache.james.protocols.smtp.SMTPConfigurationImpl;
 import org.apache.james.protocols.smtp.SMTPProtocol;
 import org.apache.james.protocols.smtp.SMTPProtocolHandlerChain;
@@ -80,7 +80,7 @@ public class NettyStartTlsSMTPServerTest {
         NettyServer server = NettyServer.builder()
                 .protocol(protocol)
                 .secure(enc)
-                .frameHandlerFactory(new AllButStartTlsLineDelimiterChannelHandlerFactory(AbstractChannelPipelineFactory.MAX_LINE_LENGTH))
+                .frameHandlerFactory(new AllButStartTlsLineChannelHandlerFactory(AbstractChannelPipelineFactory.MAX_LINE_LENGTH))
                 .build();
         server.setListenAddresses(new InetSocketAddress(LOCALHOST_IP, RANDOM_PORT));
         return server;

http://git-wip-us.apache.org/repos/asf/james-project/blob/a2b0345d/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
----------------------------------------------------------------------
diff --git a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
index bccdd57..d834e0b 100644
--- a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
+++ b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
@@ -225,7 +225,7 @@ public class IMAPServer extends AbstractConfigurableAsyncServer implements ImapC
 
     @Override
     protected ChannelHandlerFactory createFrameHandlerFactory() {
-        return new SwitchableLineDelimiterBasedFrameDecoderFactory(maxLineLength);
+        return new SwitchableLineBasedFrameDecoderFactory(maxLineLength);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/a2b0345d/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapRequestFrameDecoder.java
----------------------------------------------------------------------
diff --git a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapRequestFrameDecoder.java b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapRequestFrameDecoder.java
index 2d7f44e..6e99515 100644
--- a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapRequestFrameDecoder.java
+++ b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapRequestFrameDecoder.java
@@ -180,7 +180,7 @@ public class ImapRequestFrameDecoder extends FrameDecoder implements NettyConsta
                 //    channel.getPipeline().addFirst(FRAMER, handler);
                 //}
                 
-                ((SwitchableDelimiterBasedFrameDecoder) channel.getPipeline().get(FRAMER)).enableFraming();
+                ((SwitchableLineBasedFrameDecoder) channel.getPipeline().get(FRAMER)).enableFraming();
                 
                 attachment.clear();
                 return message;
@@ -200,7 +200,7 @@ public class ImapRequestFrameDecoder extends FrameDecoder implements NettyConsta
                 //attachment.put(FRAMER, handler);
 
                 // SwitchableDelimiterBasedFrameDecoder added further to JAMES-1436.
-                final SwitchableDelimiterBasedFrameDecoder framer = (SwitchableDelimiterBasedFrameDecoder) pipeline.get(FRAMER);
+                final SwitchableLineBasedFrameDecoder framer = (SwitchableLineBasedFrameDecoder) pipeline.get(FRAMER);
                 framer.disableFraming(framerContext);
                 
                 buffer.resetReaderIndex();

http://git-wip-us.apache.org/repos/asf/james-project/blob/a2b0345d/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/SwitchableDelimiterBasedFrameDecoder.java
----------------------------------------------------------------------
diff --git a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/SwitchableDelimiterBasedFrameDecoder.java b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/SwitchableDelimiterBasedFrameDecoder.java
deleted file mode 100644
index 0b3e127..0000000
--- a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/SwitchableDelimiterBasedFrameDecoder.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.imapserver.netty;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.channel.ChannelHandlerContext;
-import org.jboss.netty.channel.Channels;
-import org.jboss.netty.channel.MessageEvent;
-import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
-
-public class SwitchableDelimiterBasedFrameDecoder extends DelimiterBasedFrameDecoder {
-
-    private volatile boolean framingEnabled = true;
-
-    public SwitchableDelimiterBasedFrameDecoder(int maxFrameLength, boolean stripDelimiter, ChannelBuffer... delimiters) {
-        super(maxFrameLength, stripDelimiter, delimiters);
-    }
-
-    @Override
-    public synchronized void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
-        if (this.framingEnabled) {
-            super.messageReceived(ctx, e);
-        } else {
-            ctx.sendUpstream(e);
-        }
-    }
-
-    public synchronized void enableFraming() {
-        this.framingEnabled = true;
-
-    }
-
-    public synchronized void disableFraming(ChannelHandlerContext ctx) {
-        this.framingEnabled = false;
-        if (this.cumulation != null && this.cumulation.readable()) {
-            final ChannelBuffer spareBytes = this.cumulation.readBytes(this.cumulation.readableBytes());
-            Channels.fireMessageReceived(ctx, spareBytes);
-        }
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/a2b0345d/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/SwitchableLineBasedFrameDecoder.java
----------------------------------------------------------------------
diff --git a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/SwitchableLineBasedFrameDecoder.java b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/SwitchableLineBasedFrameDecoder.java
new file mode 100644
index 0000000..b05cdc6
--- /dev/null
+++ b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/SwitchableLineBasedFrameDecoder.java
@@ -0,0 +1,59 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.imapserver.netty;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.Channels;
+import org.jboss.netty.channel.MessageEvent;
+import org.jboss.netty.handler.codec.frame.LineBasedFrameDecoder;
+
+public class SwitchableLineBasedFrameDecoder extends LineBasedFrameDecoder {
+
+    private static final Boolean FAIL_FAST = true;
+    private volatile boolean framingEnabled = true;
+
+    public SwitchableLineBasedFrameDecoder(int maxFrameLength, boolean stripDelimiter) {
+        super(maxFrameLength, stripDelimiter, !FAIL_FAST);
+    }
+
+    @Override
+    public synchronized void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
+        if (this.framingEnabled) {
+            super.messageReceived(ctx, e);
+        } else {
+            ctx.sendUpstream(e);
+        }
+    }
+
+    public synchronized void enableFraming() {
+        this.framingEnabled = true;
+
+    }
+
+    public synchronized void disableFraming(ChannelHandlerContext ctx) {
+        this.framingEnabled = false;
+        if (this.cumulation != null && this.cumulation.readable()) {
+            final ChannelBuffer spareBytes = this.cumulation.readBytes(this.cumulation.readableBytes());
+            Channels.fireMessageReceived(ctx, spareBytes);
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/a2b0345d/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/SwitchableLineBasedFrameDecoderFactory.java
----------------------------------------------------------------------
diff --git a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/SwitchableLineBasedFrameDecoderFactory.java b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/SwitchableLineBasedFrameDecoderFactory.java
new file mode 100644
index 0000000..9c5f5d4
--- /dev/null
+++ b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/SwitchableLineBasedFrameDecoderFactory.java
@@ -0,0 +1,37 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+package org.apache.james.imapserver.netty;
+
+import org.apache.james.protocols.netty.ChannelHandlerFactory;
+import org.jboss.netty.channel.ChannelHandler;
+import org.jboss.netty.channel.ChannelPipeline;
+
+public class SwitchableLineBasedFrameDecoderFactory implements ChannelHandlerFactory {
+
+    private int maxLineLength;
+
+    public SwitchableLineBasedFrameDecoderFactory(int maxLineLength) {
+        this.maxLineLength = maxLineLength;
+    }
+
+    @Override
+    public ChannelHandler create(ChannelPipeline pipeline) {
+        return new SwitchableLineBasedFrameDecoder(maxLineLength, false);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/a2b0345d/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/SwitchableLineDelimiterBasedFrameDecoderFactory.java
----------------------------------------------------------------------
diff --git a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/SwitchableLineDelimiterBasedFrameDecoderFactory.java b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/SwitchableLineDelimiterBasedFrameDecoderFactory.java
deleted file mode 100644
index 0350f09..0000000
--- a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/SwitchableLineDelimiterBasedFrameDecoderFactory.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-package org.apache.james.imapserver.netty;
-
-import org.apache.james.protocols.netty.ChannelHandlerFactory;
-import org.jboss.netty.channel.ChannelHandler;
-import org.jboss.netty.channel.ChannelPipeline;
-import org.jboss.netty.handler.codec.frame.Delimiters;
-
-public class SwitchableLineDelimiterBasedFrameDecoderFactory implements ChannelHandlerFactory {
-
-    private int maxLineLength;
-
-    public SwitchableLineDelimiterBasedFrameDecoderFactory(int maxLineLength) {
-        this.maxLineLength = maxLineLength;
-    }
-
-    @Override
-    public ChannelHandler create(ChannelPipeline pipeline) {
-        return new SwitchableDelimiterBasedFrameDecoder(maxLineLength, false, Delimiters.lineDelimiter());
-    }
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/a2b0345d/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/netty/SMTPServer.java
----------------------------------------------------------------------
diff --git a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/netty/SMTPServer.java b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/netty/SMTPServer.java
index a7c8233..78e1fe2 100644
--- a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/netty/SMTPServer.java
+++ b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/netty/SMTPServer.java
@@ -32,7 +32,7 @@ import org.apache.james.protocols.lib.handler.HandlersPackage;
 import org.apache.james.protocols.lib.netty.AbstractProtocolAsyncServer;
 import org.apache.james.protocols.netty.AbstractChannelPipelineFactory;
 import org.apache.james.protocols.netty.ChannelHandlerFactory;
-import org.apache.james.protocols.smtp.AllButStartTlsLineDelimiterChannelHandlerFactory;
+import org.apache.james.protocols.smtp.AllButStartTlsLineChannelHandlerFactory;
 import org.apache.james.protocols.smtp.SMTPConfiguration;
 import org.apache.james.protocols.smtp.SMTPProtocol;
 import org.apache.james.smtpserver.CoreCmdHandlerLoader;
@@ -371,7 +371,7 @@ public class SMTPServer extends AbstractProtocolAsyncServer implements SMTPServe
 
     @Override
     protected ChannelHandlerFactory createFrameHandlerFactory() {
-        return new AllButStartTlsLineDelimiterChannelHandlerFactory(AbstractChannelPipelineFactory.MAX_LINE_LENGTH);
+        return new AllButStartTlsLineChannelHandlerFactory(AbstractChannelPipelineFactory.MAX_LINE_LENGTH);
     }
 
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org