From ba3da755ed7460be28160dc66d989eed0e6e690f Mon Sep 17 00:00:00 2001
From: Matthieu Baechler <matthieu.baechler@linagora.com>
Date: Wed, 23 Oct 2013 15:47:33 +0200
Subject: [PATCH 01/35] Prototype mailbox-cassandra implementation

---
 .gitignore                                         |   3 +
 cassandra/pom.xml                                  |  95 ++++++
 .../CassandraMailboxSessionMapperFactory.java      |  67 ++++
 .../cassandra/mail/CassandraMailboxMapper.java     | 153 +++++++++
 .../cassandra/mail/CassandraMessageMapper.java     | 371 +++++++++++++++++++++
 .../cassandra/mail/CassandraModSeqProvider.java    |  71 ++++
 .../cassandra/mail/CassandraUidProvider.java       |  70 ++++
 .../cassandra/mail/MailboxCountersTable.java       |  42 +++
 .../james/mailbox/cassandra/mail/MailboxTable.java |  43 +++
 .../james/mailbox/cassandra/mail/MessageTable.java |  63 ++++
 .../user/CassandraSubscriptionMapper.java          |  98 ++++++
 .../cassandra/CassandraMailboxManagerTest.java     |  82 +++++
 cassandra/src/test/resources/logback.xml           |  15 +
 cassandra/src/test/resources/mailbox.cql           |  40 +++
 pom.xml                                            |   1 +
 15 files changed, 1214 insertions(+)
 create mode 100644 cassandra/pom.xml
 create mode 100644 cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
 create mode 100644 cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
 create mode 100644 cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
 create mode 100644 cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProvider.java
 create mode 100644 cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProvider.java
 create mode 100644 cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MailboxCountersTable.java
 create mode 100644 cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MailboxTable.java
 create mode 100644 cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MessageTable.java
 create mode 100644 cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java
 create mode 100644 cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java
 create mode 100644 cassandra/src/test/resources/logback.xml
 create mode 100644 cassandra/src/test/resources/mailbox.cql

diff --git a/.gitignore b/.gitignore
index e2fbf32..303b9f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,6 @@ target
 derby.log
 var
 log
+.classpath
+.project
+.settings
\ No newline at end of file
diff --git a/cassandra/pom.xml b/cassandra/pom.xml
new file mode 100644
index 0000000..f4e6428
--- /dev/null
+++ b/cassandra/pom.xml
@@ -0,0 +1,95 @@
+<?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>apache-james-mailbox</artifactId>
+        <groupId>org.apache.james</groupId>
+        <version>0.6-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>apache-james-mailbox-cassandra</artifactId>
+    <name>Apache James :: Mailbox :: Cassandra</name>
+    <packaging>bundle</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>${javax.mail.groupId}</groupId>
+            <artifactId>${javax.mail.artifactId}</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.james</groupId>
+            <artifactId>apache-james-mailbox-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.james</groupId>
+            <artifactId>apache-james-mailbox-store</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.james</groupId>
+            <artifactId>apache-james-mailbox-api</artifactId>
+            <scope>test</scope>
+            <type>test-jar</type>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.james</groupId>
+            <artifactId>apache-james-mailbox-store</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+                <dependency>
+			<groupId>org.cassandraunit</groupId>
+			<artifactId>cassandra-unit</artifactId>
+			<version>1.2.0.1</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>com.datastax.cassandra</groupId>
+			<artifactId>cassandra-driver-core</artifactId>
+			<version>1.0.0</version>
+		</dependency>
+		<dependency>
+			<groupId>javax.inject</groupId>
+			<artifactId>javax.inject</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>ch.qos.logback</groupId>
+			<artifactId>logback-classic</artifactId>
+			<version>1.0.13</version>
+			<scope>test</scope>
+		</dependency>
+    </dependencies>
+</project>
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
new file mode 100644
index 0000000..6b7515d
--- /dev/null
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
@@ -0,0 +1,67 @@
+/****************************************************************
+ * 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;
+
+import java.util.UUID;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.cassandra.mail.CassandraMailboxMapper;
+import org.apache.james.mailbox.cassandra.mail.CassandraMessageMapper;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.exception.SubscriptionException;
+import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
+import org.apache.james.mailbox.store.mail.MailboxMapper;
+import org.apache.james.mailbox.store.mail.MessageMapper;
+import org.apache.james.mailbox.store.user.SubscriptionMapper;
+
+import com.google.common.annotations.VisibleForTesting;
+
+@Singleton
+public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFactory<UUID> {
+
+    private MailboxMapper<UUID> mailboxMapper;
+    private MessageMapper<UUID> messageMapper;
+    private SubscriptionMapper subscriptionMapper;
+    
+    @Inject
+    @VisibleForTesting CassandraMailboxSessionMapperFactory(CassandraMailboxMapper mailboxMapper, CassandraMessageMapper messageMapper, SubscriptionMapper subscriptionMapper) {
+        this.mailboxMapper = mailboxMapper;
+        this.messageMapper = messageMapper;
+		this.subscriptionMapper = subscriptionMapper;
+    }
+    
+    @Override
+    public MailboxMapper<UUID> createMailboxMapper(MailboxSession session) throws MailboxException {
+        return mailboxMapper;
+    }
+
+    @Override
+    public MessageMapper<UUID> createMessageMapper(MailboxSession session) throws MailboxException {
+        return messageMapper;
+    }
+
+    @Override
+    public SubscriptionMapper createSubscriptionMapper(MailboxSession session) throws SubscriptionException {
+        return subscriptionMapper;
+    }
+
+}
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
new file mode 100644
index 0000000..f0fe060
--- /dev/null
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
@@ -0,0 +1,153 @@
+/****************************************************************
+ * 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.eq;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.insertInto;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
+import static org.apache.james.mailbox.cassandra.mail.MailboxTable.ID;
+import static org.apache.james.mailbox.cassandra.mail.MailboxTable.TABLE_NAME;
+import static org.apache.james.mailbox.cassandra.mail.MailboxTable.NAME;
+import static org.apache.james.mailbox.cassandra.mail.MailboxTable.NAMESPACE;
+import static org.apache.james.mailbox.cassandra.mail.MailboxTable.PATH;
+import static org.apache.james.mailbox.cassandra.mail.MailboxTable.UIDVALIDITY;
+import static org.apache.james.mailbox.cassandra.mail.MailboxTable.USER;
+
+import java.util.List;
+import java.util.UUID;
+
+import javax.inject.Inject;
+
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.exception.MailboxNotFoundException;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.store.mail.MailboxMapper;
+import org.apache.james.mailbox.store.mail.model.Mailbox;
+import org.apache.james.mailbox.store.mail.model.impl.SimpleMailbox;
+
+import com.datastax.driver.core.ResultSet;
+import com.datastax.driver.core.Row;
+import com.datastax.driver.core.Session;
+import com.datastax.driver.core.querybuilder.QueryBuilder;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableList.Builder;
+
+public class CassandraMailboxMapper implements MailboxMapper<UUID> {
+    
+	private static final String[] FIELDS = {ID, USER, NAMESPACE, UIDVALIDITY, NAME, PATH};
+	private Session session;
+
+    @Inject
+    public CassandraMailboxMapper(Session session) {
+        this.session = session;
+    }
+
+    @Override
+    public void delete(Mailbox<UUID> mailbox) throws MailboxException {
+        session.execute(QueryBuilder.delete().from(TABLE_NAME).where(eq(ID, mailbox.getMailboxId())));
+    }
+
+    @Override
+    public Mailbox<UUID> findMailboxByPath(MailboxPath path) throws MailboxException, MailboxNotFoundException {
+        ResultSet resultSet = session.execute(select(FIELDS).from(TABLE_NAME).where(eq(PATH, path.toString())));
+        if (resultSet.isExhausted()) {
+            throw new MailboxNotFoundException(path);
+        } else {
+            return mailbox(resultSet.one());
+        }
+    }
+
+	private SimpleMailbox<UUID> mailbox(Row row) {
+		SimpleMailbox<UUID> mailbox = new SimpleMailbox<UUID>(
+				new MailboxPath(
+						row.getString(NAMESPACE),
+						row.getString(USER),
+						row.getString(NAME)),
+				row.getLong(UIDVALIDITY));
+		mailbox.setMailboxId(row.getUUID(ID));
+		return mailbox;
+	}
+
+	@Override
+    public List<Mailbox<UUID>> findMailboxWithPathLike(MailboxPath path) throws MailboxException {
+        final String regex = path.getName().replace("%", ".*");
+        Builder<Mailbox<UUID>> result = ImmutableList.<Mailbox<UUID>>builder();
+        for (Row row: session.execute(select(FIELDS).from(TABLE_NAME))) {
+            if (row.getString(PATH).matches(regex)) {
+                result.add(mailbox(row));
+            }
+        }
+        return result.build();
+    }
+
+    @Override
+    public void save(Mailbox<UUID> mailbox) throws MailboxException {
+    	Preconditions.checkArgument(mailbox instanceof SimpleMailbox<?>);
+    	SimpleMailbox<UUID> simpleMailbox = (SimpleMailbox<UUID>) mailbox;
+    	UUID id = simpleMailbox.getMailboxId();
+        if (id == null) {
+            id = UUID.randomUUID();
+            simpleMailbox.setMailboxId(id);
+        }
+        upsertMailbox(simpleMailbox);
+    }
+
+    private void upsertMailbox(SimpleMailbox<UUID> mailbox) {
+    	session.execute(insertInto(TABLE_NAME)
+    			.value(ID, mailbox.getMailboxId())
+    			.value(NAME, mailbox.getName())
+    			.value(NAMESPACE, mailbox.getNamespace())
+    			.value(UIDVALIDITY, mailbox.getUidValidity())
+    			.value(USER, mailbox.getUser())
+    			.value(PATH, path(mailbox).toString())
+    			);
+    }
+    
+    private MailboxPath path(Mailbox<?> mailbox) {
+    	return new MailboxPath(mailbox.getNamespace(), mailbox.getUser(), mailbox.getName());
+    }
+    
+    @Override
+    public void endRequest() {
+        // Do nothing
+    }
+
+    @Override
+    public boolean hasChildren(Mailbox<UUID> mailbox, char delimiter) throws MailboxException, MailboxNotFoundException {
+        return !findMailboxWithPathLike(
+        			new MailboxPath(mailbox.getNamespace(), mailbox.getUser(), mailbox.getName() + delimiter + "%"))
+        		.isEmpty();
+    }
+
+    @Override
+    public List<Mailbox<UUID>> list() throws MailboxException {
+        Builder<Mailbox<UUID>> result = ImmutableList.<Mailbox<UUID>>builder();
+    	for (Row row: session.execute(select(FIELDS).from(TABLE_NAME))) {
+    		result.add(mailbox(row));
+    	}
+    	return result.build();
+    }
+
+    @Override
+    public <T> T execute(Transaction<T> transaction) throws MailboxException {
+        return transaction.run();
+    }
+    
+}
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
new file mode 100644
index 0000000..c12c8bf
--- /dev/null
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
@@ -0,0 +1,371 @@
+/****************************************************************
+ * 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.asc;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.bindMarker;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.decr;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.eq;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.gt;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.incr;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.insertInto;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.lt;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.update;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.inject.Inject;
+import javax.mail.Flags;
+import javax.mail.Flags.Flag;
+import javax.mail.util.SharedByteArrayInputStream;
+
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.MessageMetaData;
+import org.apache.james.mailbox.model.MessageRange;
+import org.apache.james.mailbox.model.UpdatedFlags;
+import org.apache.james.mailbox.store.SimpleMessageMetaData;
+import org.apache.james.mailbox.store.mail.MessageMapper;
+import org.apache.james.mailbox.store.mail.ModSeqProvider;
+import org.apache.james.mailbox.store.mail.UidProvider;
+import org.apache.james.mailbox.store.mail.model.Mailbox;
+import org.apache.james.mailbox.store.mail.model.Message;
+import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder;
+import org.apache.james.mailbox.store.mail.model.impl.SimpleMessage;
+
+import com.datastax.driver.core.BoundStatement;
+import com.datastax.driver.core.PreparedStatement;
+import com.datastax.driver.core.ResultSet;
+import com.datastax.driver.core.Row;
+import com.datastax.driver.core.Session;
+import com.datastax.driver.core.querybuilder.Assignment;
+import com.datastax.driver.core.querybuilder.Insert;
+import com.datastax.driver.core.querybuilder.QueryBuilder;
+import com.datastax.driver.core.querybuilder.Select.Where;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.collect.ImmutableSortedSet.Builder;
+import com.google.common.io.ByteStreams;
+
+public class CassandraMessageMapper implements MessageMapper<UUID> {
+
+	private static final String[] FIELDS = {
+		MessageTable.MAILBOX_ID, MessageTable.IMAP_UID, MessageTable.INTERNAL_DATE, MessageTable.MOD_SEQ,
+		MessageTable.BODY_START_OCTET,
+		MessageTable.MEDIA_TYPE, MessageTable.SUB_TYPE, MessageTable.FULL_CONTENT_OCTETS,
+		MessageTable.BODY_OCTECTS, MessageTable.Flag.ANSWERED, MessageTable.Flag.DELETED,
+		MessageTable.Flag.DRAFT, MessageTable.Flag.FLAGGED, MessageTable.Flag.RECENT,
+		MessageTable.Flag.SEEN,	MessageTable.Flag.USER, MessageTable.BODY_CONTENT, MessageTable.HEADER_CONTENT};
+	private Session session;
+	private ModSeqProvider<UUID> modSeqProvider;
+	private MailboxSession mailboxSession;
+	private UidProvider<UUID> uidProvider;
+
+    @Inject
+    public CassandraMessageMapper(Session session, UidProvider<UUID> uidProvider,
+            ModSeqProvider<UUID> modSeqProvider) {
+		this.session = session;
+		this.uidProvider = uidProvider;
+		this.modSeqProvider = modSeqProvider;
+    }
+
+    @Override
+    public long countMessagesInMailbox(Mailbox<UUID> mailbox) throws MailboxException {
+        ResultSet results = session.execute(
+        		select(MailboxCountersTable.COUNT).from(MailboxCountersTable.TABLE_NAME).where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
+        if (results.isExhausted()) {
+        	return 0;
+        } else {
+        	return results.one().getLong(MailboxCountersTable.COUNT);
+        }
+    }
+
+    @Override
+    public long countUnseenMessagesInMailbox(Mailbox<UUID> mailbox) throws MailboxException {
+    	ResultSet results = session.execute(
+        		select(MailboxCountersTable.COUNT).from(MailboxCountersTable.TABLE_NAME).where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
+        if (!results.isExhausted()) {
+        	Row row = results.one();
+        	if (row.getColumnDefinitions().contains(MailboxCountersTable.UNSEEN)) {
+        		return row.getLong(MailboxCountersTable.UNSEEN);
+        	}
+        }
+        return 0;
+    }
+
+    @Override
+    public void delete(Mailbox<UUID> mailbox, Message<UUID> message) throws MailboxException {
+    	session.execute(QueryBuilder.delete()
+    			.from(MessageTable.TABLE_NAME)
+    			.where(eq(MessageTable.MAILBOX_ID, mailbox.getMailboxId()))
+    			.and(eq(MessageTable.IMAP_UID, message.getUid())));
+    	decrementCount(mailbox);
+    	if (!message.isSeen()) {
+    		decrementUnseen(mailbox);
+    	}
+    }
+
+	private void decrementCount(Mailbox<UUID> mailbox) {
+		updateMailbox(mailbox, decr(MailboxCountersTable.COUNT));
+	}
+
+	private void incrementCount(Mailbox<UUID> mailbox) {
+		updateMailbox(mailbox, incr(MailboxCountersTable.COUNT));
+	}
+	
+	private void decrementUnseen(Mailbox<UUID> mailbox) {
+		updateMailbox(mailbox, decr(MailboxCountersTable.UNSEEN));
+	}
+
+	private void incrementUnseen(Mailbox<UUID> mailbox) {
+		updateMailbox(mailbox, incr(MailboxCountersTable.UNSEEN));
+	}
+
+	
+	private void updateMailbox(Mailbox<UUID> mailbox, Assignment operation) {
+		session.execute(update(MailboxCountersTable.TABLE_NAME)
+				.with(operation)
+				.where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
+	}
+
+    @Override
+    public Iterator<Message<UUID>> findInMailbox(Mailbox<UUID> mailbox, MessageRange set, FetchType ftype, int max)
+            throws MailboxException {
+    	Builder<Message<UUID>> result = ImmutableSortedSet.<Message<UUID>>naturalOrder();
+    	ResultSet rows = session.execute(buildQuery(mailbox, set));
+        for (Row row: rows) {
+        	result.add(message(row));
+        }
+        return result.build().iterator();
+    }
+
+	private Message<UUID> message(Row row) {
+		SimpleMessage<UUID> message = new SimpleMessage<UUID>(
+				row.getDate(MessageTable.INTERNAL_DATE),
+				row.getInt(MessageTable.FULL_CONTENT_OCTETS),
+				row.getInt(MessageTable.BODY_START_OCTET),
+				new SharedByteArrayInputStream(row.getBytes(MessageTable.BODY_CONTENT).array()),
+				new Flags(),
+				new PropertyBuilder(), 
+				row.getUUID(MessageTable.MAILBOX_ID));
+		message.setUid(row.getLong(MessageTable.IMAP_UID));
+		return message;
+	}
+	
+	private Where buildQuery(Mailbox<UUID> mailbox, MessageRange set) {
+		final MessageRange.Type type = set.getType();
+        switch (type) {
+        case ALL:
+            return selectAll(mailbox);
+        case FROM:
+        	return selectFrom(mailbox, set.getUidFrom());
+        case RANGE:
+        	return selectRange(mailbox, set.getUidFrom(), set.getUidTo());
+        case ONE:
+        	return selectMessage(mailbox, set.getUidFrom());
+        }
+        throw new UnsupportedOperationException();
+	}
+
+	private Where selectAll(Mailbox<UUID> mailbox) {
+		return select(FIELDS).from(MessageTable.TABLE_NAME).where(eq(MessageTable.MAILBOX_ID, mailbox.getMailboxId()));
+	}
+	
+	private Where selectFrom(Mailbox<UUID> mailbox, long uid) {
+		return select(FIELDS).from(MessageTable.TABLE_NAME).where(eq(MessageTable.MAILBOX_ID, mailbox.getMailboxId())).and(gt(MessageTable.IMAP_UID, uid));
+	}
+
+
+	private Where selectRange(Mailbox<UUID> mailbox, long from, long to) {
+		return select(FIELDS).from(MessageTable.TABLE_NAME)
+					.where(eq(MessageTable.MAILBOX_ID, mailbox.getMailboxId()))
+					.and(gt(MessageTable.IMAP_UID, from))
+					.and(lt(MessageTable.IMAP_UID, to));
+	}
+
+	private Where selectMessage(Mailbox<UUID> mailbox, long uid) {
+		return select(FIELDS).from(MessageTable.TABLE_NAME)
+				.where(eq(MessageTable.MAILBOX_ID, mailbox.getMailboxId()))
+				.and(eq(MessageTable.IMAP_UID, uid));
+	}
+	
+	@Override
+	public List<Long> findRecentMessageUidsInMailbox(Mailbox<UUID> mailbox) throws MailboxException {
+		ImmutableList.Builder<Long> result = ImmutableList.<Long>builder();
+    	ResultSet rows = session.execute(selectAll(mailbox).orderBy(asc(MessageTable.IMAP_UID)));
+        for (Row row: rows) {
+        	Message<UUID> message = message(row);
+        	if (message.isRecent()) {
+        		result.add(message.getUid());
+        	}
+        }
+        return result.build();
+    }
+
+
+	@Override
+    public Long findFirstUnseenMessageUid(Mailbox<UUID> mailbox) throws MailboxException {
+		ResultSet rows = session.execute(selectAll(mailbox).orderBy(asc(MessageTable.IMAP_UID)));
+        for (Row row: rows) {
+        	Message<UUID> message = message(row);
+        	if (!message.isSeen()) {
+        		return message.getUid();
+        	}
+        }
+        return null;
+    }
+
+    @Override
+    public Map<Long, MessageMetaData> expungeMarkedForDeletionInMailbox(final Mailbox<UUID> mailbox, MessageRange set) throws MailboxException {
+    	ImmutableMap.Builder<Long, MessageMetaData> deletedMessages = ImmutableMap.builder();
+    	ResultSet messages = session.execute(buildQuery(mailbox, set));
+    	for (Row row: messages) {
+    		Message<UUID> message = message(row);
+    		if (message.isDeleted()) {
+    			delete(mailbox, message);
+    			deletedMessages.put(message.getUid(), new SimpleMessageMetaData(message));
+    		}
+    	}
+    	return deletedMessages.build();
+    }
+
+    @Override
+    public MessageMetaData move(Mailbox<UUID> mailbox, Message<UUID> original) throws MailboxException {
+        throw new UnsupportedOperationException("Not implemented - see https://issues.apache.org/jira/browse/IMAP-370");
+    }
+
+    @Override
+    public void endRequest() {
+        // Do nothing
+    }
+
+    @Override
+    public long getHighestModSeq(Mailbox<UUID> mailbox) throws MailboxException {
+    	return modSeqProvider.highestModSeq(mailboxSession, mailbox);
+    }
+
+	@Override
+	public <T> T execute(Transaction<T> transaction) throws MailboxException {
+		return transaction.run();
+	}
+
+	@Override
+	public MessageMetaData add(Mailbox<UUID> mailbox, Message<UUID> message)
+			throws MailboxException {
+		message.setUid(uidProvider.nextUid(mailboxSession, mailbox));
+		message.setModSeq(modSeqProvider.nextModSeq(mailboxSession, mailbox));
+		MessageMetaData messageMetaData = save(mailbox, message);
+		incrementUnseen(mailbox);
+		incrementCount(mailbox);
+		return messageMetaData;
+	}
+
+	private MessageMetaData save(Mailbox<UUID> mailbox, Message<UUID> message) throws MailboxException {
+		try {
+			Insert query = insertInto(MessageTable.TABLE_NAME)
+				.value(MessageTable.MAILBOX_ID, mailbox.getMailboxId())
+				.value(MessageTable.IMAP_UID, message.getUid())
+				.value(MessageTable.MOD_SEQ, message.getModSeq())
+				.value(MessageTable.INTERNAL_DATE, message.getInternalDate())
+				.value(MessageTable.MEDIA_TYPE, message.getMediaType())
+				.value(MessageTable.SUB_TYPE, message.getSubType())
+				.value(MessageTable.FULL_CONTENT_OCTETS, message.getFullContentOctets())
+				.value(MessageTable.BODY_OCTECTS, message.getBodyOctets())
+				.value(MessageTable.Flag.ANSWERED, message.isAnswered())
+				.value(MessageTable.Flag.DELETED, message.isDeleted())
+				.value(MessageTable.Flag.DRAFT, message.isDraft())
+				.value(MessageTable.Flag.FLAGGED, message.isFlagged())
+				.value(MessageTable.Flag.RECENT, message.isRecent())
+				.value(MessageTable.Flag.SEEN, message.isSeen())
+				.value(MessageTable.Flag.USER, message.createFlags().contains(Flag.USER))
+				.value(MessageTable.BODY_CONTENT, bindMarker())
+				.value(MessageTable.HEADER_CONTENT, bindMarker());
+			if (message.getTextualLineCount() != null) {
+				query.value(MessageTable.TEXTUAL_LINE_COUNT, message.getTextualLineCount());
+			}
+			PreparedStatement preparedStatement = session.prepare(query.toString());
+			BoundStatement boundStatement = preparedStatement.bind(
+					toByteBuffer(message.getBodyContent()),
+					toByteBuffer(message.getHeaderContent()));
+			session.execute(boundStatement);
+			return new SimpleMessageMetaData(message);
+		} catch (IOException e) {
+			throw new MailboxException("Error saving mail", e);
+		}
+	}
+
+	private ByteBuffer toByteBuffer(InputStream stream) throws IOException {
+		return ByteBuffer.wrap(ByteStreams.toByteArray(stream));
+	}
+
+	@Override
+	public Iterator<UpdatedFlags> updateFlags(Mailbox<UUID> mailbox,
+			Flags flags, boolean value, boolean replace, MessageRange set)
+			throws MailboxException {
+		ImmutableList.Builder<UpdatedFlags> result = ImmutableList.builder();
+		ResultSet messages = session.execute(buildQuery(mailbox, set));
+    	for (Row row: messages) {
+    		Message<UUID> message = message(row);
+    		Flags originFlags = message.createFlags();
+    		Flags updatedFlags = buildFlags(message, flags, value, replace);
+    		message.setFlags(updatedFlags);
+    		message.setModSeq(modSeqProvider.nextModSeq(mailboxSession, mailbox));
+    		save(mailbox, message);
+    		result.add(new UpdatedFlags(message.getUid(), message.getModSeq(), originFlags, updatedFlags));
+    	}
+    	return result.build().iterator();
+	}
+
+	private Flags buildFlags(Message<UUID> message, Flags flags, boolean value, boolean replace) {
+		if (replace) {
+			return message.createFlags();
+		} else {
+			Flags updatedFlags = message.createFlags();
+			if (value) {
+				updatedFlags.add(flags);
+			} else {
+				updatedFlags.remove(flags);
+			}
+			return updatedFlags;
+		}
+	}
+
+	@Override
+	public MessageMetaData copy(Mailbox<UUID> mailbox, Message<UUID> original) throws MailboxException {
+        original.setUid(uidProvider.nextUid(mailboxSession, mailbox));
+        original.setModSeq(modSeqProvider.nextModSeq(mailboxSession, mailbox));
+        return save(mailbox, original);
+	}
+
+	@Override
+	public long getLastUid(Mailbox<UUID> mailbox) throws MailboxException {
+		return uidProvider.lastUid(mailboxSession, mailbox);
+	}
+    
+    
+}
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProvider.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProvider.java
new file mode 100644
index 0000000..5d1ef12
--- /dev/null
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProvider.java
@@ -0,0 +1,71 @@
+/****************************************************************
+ * 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.eq;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.incr;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.update;
+
+import java.util.UUID;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.store.mail.ModSeqProvider;
+import org.apache.james.mailbox.store.mail.model.Mailbox;
+
+import com.datastax.driver.core.ResultSet;
+import com.datastax.driver.core.Session;
+
+@Singleton
+public class CassandraModSeqProvider implements ModSeqProvider<UUID> {
+
+	private Session session;
+	
+	@Inject
+	public CassandraModSeqProvider(Session session) {
+		this.session = session;
+	}
+	
+    @Override
+    public long nextModSeq(MailboxSession mailboxSession, Mailbox<UUID> mailbox) throws MailboxException {
+    	session.execute(
+    			update(MailboxCountersTable.TABLE_NAME)
+    				.with(incr(MailboxCountersTable.NEXT_MOD_SEQ))
+    				.where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
+    	return highestModSeq(mailboxSession, mailbox);
+    }
+
+    @Override
+    public long highestModSeq(MailboxSession mailboxSession, Mailbox<UUID> mailbox) throws MailboxException {
+    	ResultSet result = session.execute(
+    			select(MailboxCountersTable.NEXT_MOD_SEQ)
+    				.from(MailboxCountersTable.TABLE_NAME)
+    				.where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
+    	if (result.isExhausted()) {
+    		return 0;
+    	} else {
+    		return result.one().getLong(MailboxCountersTable.NEXT_MOD_SEQ);
+    	}        
+    }
+}
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProvider.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProvider.java
new file mode 100644
index 0000000..16fc681
--- /dev/null
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProvider.java
@@ -0,0 +1,70 @@
+/****************************************************************
+ * 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.eq;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.incr;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.update;
+
+import java.util.UUID;
+
+import javax.inject.Inject;
+
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.store.mail.UidProvider;
+import org.apache.james.mailbox.store.mail.model.Mailbox;
+
+import com.datastax.driver.core.ResultSet;
+import com.datastax.driver.core.Session;
+
+public class CassandraUidProvider implements UidProvider<UUID> {
+    
+	private Session session;
+	
+	@Inject
+	public CassandraUidProvider(Session session) {
+		this.session = session;
+	}
+
+	@Override
+    public long nextUid(MailboxSession mailboxSession, Mailbox<UUID> mailbox) throws MailboxException {
+    	session.execute(
+    			update(MailboxCountersTable.TABLE_NAME)
+    				.with(incr(MailboxCountersTable.NEXT_UID))
+    				.where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
+    	return lastUid(mailboxSession, mailbox);
+    }
+
+    @Override
+    public long lastUid(MailboxSession mailboxSession, Mailbox<UUID> mailbox) throws MailboxException {
+    	ResultSet result = session.execute(
+    			select(MailboxCountersTable.NEXT_UID)
+    				.from(MailboxCountersTable.TABLE_NAME)
+    				.where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
+    	if (result.isExhausted()) {
+    		return 0;
+    	} else {
+    		return result.one().getLong(MailboxCountersTable.NEXT_UID);
+    	}        
+    }
+
+}
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MailboxCountersTable.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MailboxCountersTable.java
new file mode 100644
index 0000000..7b76f14
--- /dev/null
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MailboxCountersTable.java
@@ -0,0 +1,42 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * 
+ * Copyright (C) 2013 Linagora
+ *
+ * This program is free software: you can redistribute it and/or 
+ * modify it under the terms of the GNU Affero General Public License as 
+ * published by the Free Software Foundation, either version 3 of the 
+ * License, or (at your option) any later version, provided you comply 
+ * with the Additional Terms applicable for OBM connector by Linagora 
+ * pursuant to Section 7 of the GNU Affero General Public License, 
+ * subsections (b), (c), and (e), pursuant to which you must notably (i) retain 
+ * the “Message sent thanks to OBM, Free Communication by Linagora” 
+ * signature notice appended to any and all outbound messages 
+ * (notably e-mail and meeting requests), (ii) retain all hypertext links between 
+ * OBM and obm.org, as well as between Linagora and linagora.com, and (iii) refrain 
+ * from infringing Linagora intellectual property rights over its trademarks 
+ * and commercial brands. Other Additional Terms apply, 
+ * see <http://www.linagora.com/licenses/> for more details. 
+ *
+ * This program is distributed in the hope that it will be useful, 
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
+ * for more details. 
+ *
+ * You should have received a copy of the GNU Affero General Public License 
+ * and its applicable Additional Terms for OBM along with this program. If not, 
+ * see <http://www.gnu.org/licenses/> for the GNU Affero General Public License version 3 
+ * and <http://www.linagora.com/licenses/> for the Additional Terms applicable to 
+ * OBM connectors. 
+ * 
+ * ***** END LICENSE BLOCK ***** */
+package org.apache.james.mailbox.cassandra.mail;
+
+public interface MailboxCountersTable {
+	String TABLE_NAME = "mailboxCounters";
+	String MAILBOX_ID = "mailboxId";
+	String COUNT = "count";
+	String UNSEEN = "unseen";
+	String NEXT_UID = "nextUid";
+	String NEXT_MOD_SEQ = "nextModSeq";
+
+}
\ No newline at end of file
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MailboxTable.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MailboxTable.java
new file mode 100644
index 0000000..337d2ae
--- /dev/null
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MailboxTable.java
@@ -0,0 +1,43 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * 
+ * Copyright (C) 2013 Linagora
+ *
+ * This program is free software: you can redistribute it and/or 
+ * modify it under the terms of the GNU Affero General Public License as 
+ * published by the Free Software Foundation, either version 3 of the 
+ * License, or (at your option) any later version, provided you comply 
+ * with the Additional Terms applicable for OBM connector by Linagora 
+ * pursuant to Section 7 of the GNU Affero General Public License, 
+ * subsections (b), (c), and (e), pursuant to which you must notably (i) retain 
+ * the “Message sent thanks to OBM, Free Communication by Linagora” 
+ * signature notice appended to any and all outbound messages 
+ * (notably e-mail and meeting requests), (ii) retain all hypertext links between 
+ * OBM and obm.org, as well as between Linagora and linagora.com, and (iii) refrain 
+ * from infringing Linagora intellectual property rights over its trademarks 
+ * and commercial brands. Other Additional Terms apply, 
+ * see <http://www.linagora.com/licenses/> for more details. 
+ *
+ * This program is distributed in the hope that it will be useful, 
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
+ * for more details. 
+ *
+ * You should have received a copy of the GNU Affero General Public License 
+ * and its applicable Additional Terms for OBM along with this program. If not, 
+ * see <http://www.gnu.org/licenses/> for the GNU Affero General Public License version 3 
+ * and <http://www.linagora.com/licenses/> for the Additional Terms applicable to 
+ * OBM connectors. 
+ * 
+ * ***** END LICENSE BLOCK ***** */
+package org.apache.james.mailbox.cassandra.mail;
+
+public interface MailboxTable {
+
+	String TABLE_NAME = "mailbox";
+	String ID = "id";
+    String USER = "user";
+    String PATH = "path";
+    String NAMESPACE = "namespace";
+	String UIDVALIDITY = "uidvalidity";
+	String NAME = "name";
+}
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MessageTable.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MessageTable.java
new file mode 100644
index 0000000..f58f5cb
--- /dev/null
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MessageTable.java
@@ -0,0 +1,63 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * 
+ * Copyright (C) 2013 Linagora
+ *
+ * This program is free software: you can redistribute it and/or 
+ * modify it under the terms of the GNU Affero General Public License as 
+ * published by the Free Software Foundation, either version 3 of the 
+ * License, or (at your option) any later version, provided you comply 
+ * with the Additional Terms applicable for OBM connector by Linagora 
+ * pursuant to Section 7 of the GNU Affero General Public License, 
+ * subsections (b), (c), and (e), pursuant to which you must notably (i) retain 
+ * the “Message sent thanks to OBM, Free Communication by Linagora” 
+ * signature notice appended to any and all outbound messages 
+ * (notably e-mail and meeting requests), (ii) retain all hypertext links between 
+ * OBM and obm.org, as well as between Linagora and linagora.com, and (iii) refrain 
+ * from infringing Linagora intellectual property rights over its trademarks 
+ * and commercial brands. Other Additional Terms apply, 
+ * see <http://www.linagora.com/licenses/> for more details. 
+ *
+ * This program is distributed in the hope that it will be useful, 
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
+ * for more details. 
+ *
+ * You should have received a copy of the GNU Affero General Public License 
+ * and its applicable Additional Terms for OBM along with this program. If not, 
+ * see <http://www.gnu.org/licenses/> for the GNU Affero General Public License version 3 
+ * and <http://www.linagora.com/licenses/> for the Additional Terms applicable to 
+ * OBM connectors. 
+ * 
+ * ***** END LICENSE BLOCK ***** */
+package org.apache.james.mailbox.cassandra.mail;
+
+public interface MessageTable {
+
+	String TABLE_NAME = "message";
+	String MAILBOX_ID = "mailboxId";
+	String IMAP_UID = "uid";
+	String INTERNAL_DATE = "internalDate";
+	String BODY_START_OCTET = "bodyStartOctet";
+	String CONTENT = "content";
+	String MOD_SEQ = "modSeq";
+	String MEDIA_TYPE = "mediaType";
+	String SUB_TYPE = "subType";
+	String FULL_CONTENT_OCTETS = "fullContentOctets";
+	String BODY_OCTECTS = "bodyOctets";
+	String TEXTUAL_LINE_COUNT = "textualLineCount";
+	String BODY_CONTENT = "bodyContent";
+	String HEADER_CONTENT = "headerContent";
+	
+	interface Flag {
+		String ANSWERED = "flagAnswered";
+		String DELETED = "flagDeleted";
+		String DRAFT = "flagDraft";
+		String RECENT = "flagRecent";
+		String SEEN = "flagSeen";
+		String FLAGGED = "flagFlagged";
+		String USER = "flagUser";
+		String[] ALL = {ANSWERED, DELETED, DRAFT, RECENT, SEEN, FLAGGED, USER};
+	}
+	
+	
+}
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java
new file mode 100644
index 0000000..1bc52ee
--- /dev/null
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java
@@ -0,0 +1,98 @@
+/****************************************************************
+ * 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.user;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.inject.Singleton;
+
+import org.apache.james.mailbox.store.transaction.NonTransactionalMapper;
+import org.apache.james.mailbox.store.user.SubscriptionMapper;
+import org.apache.james.mailbox.store.user.model.Subscription;
+
+@Singleton
+public class CassandraSubscriptionMapper extends NonTransactionalMapper implements SubscriptionMapper {
+    
+    private static final int INITIAL_SIZE = 64;
+    private final Map<String, List<Subscription>> subscriptionsByUser;
+    
+    public CassandraSubscriptionMapper() {
+        subscriptionsByUser = new ConcurrentHashMap<String, List<Subscription>>(INITIAL_SIZE);
+    }
+
+    @Override
+    public synchronized void delete(Subscription subscription) {
+        final String user = subscription.getUser();
+        final List<Subscription> subscriptions = subscriptionsByUser.get(user);
+        if (subscriptions != null) {
+            subscriptions.remove(subscription);
+        }
+    }
+
+    @Override
+    public Subscription findMailboxSubscriptionForUser(String user, String mailbox) {
+        final List<Subscription> subscriptions = subscriptionsByUser.get(user);
+        Subscription result = null;
+        if (subscriptions != null) {
+            for(Subscription subscription:subscriptions) {
+                if (subscription.getMailbox().equals(mailbox)) {
+                    result = subscription;
+                    break;
+                }
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public List<Subscription> findSubscriptionsForUser(String user) {
+        final List<Subscription> subcriptions = subscriptionsByUser.get(user);
+        final List<Subscription> results;
+        if (subcriptions == null) {
+            results = Collections.EMPTY_LIST;
+        } else {
+            // Make a copy to prevent concurrent modifications
+            results = new ArrayList<Subscription>(subcriptions);
+        }
+        return results;
+    }
+
+    @Override
+    public synchronized void save(Subscription subscription) {
+        final String user = subscription.getUser();
+        final List<Subscription> subscriptions = subscriptionsByUser.get(user);
+        if (subscriptions == null) {
+            final List<Subscription> newSubscriptions  = new ArrayList<Subscription>();
+            newSubscriptions.add(subscription);
+            subscriptionsByUser.put(user, newSubscriptions);
+        } else {
+            subscriptions.add(subscription);
+        }
+    }
+
+    @Override
+    public void endRequest() {
+        // nothing todo
+    }
+
+}
diff --git a/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java
new file mode 100644
index 0000000..872ede2
--- /dev/null
+++ b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java
@@ -0,0 +1,82 @@
+/****************************************************************
+ * 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;
+
+import java.util.UUID;
+
+import org.apache.james.mailbox.AbstractMailboxManagerTest;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.acl.GroupMembershipResolver;
+import org.apache.james.mailbox.acl.MailboxACLResolver;
+import org.apache.james.mailbox.acl.SimpleGroupMembershipResolver;
+import org.apache.james.mailbox.acl.UnionMailboxACLResolver;
+import org.apache.james.mailbox.cassandra.mail.CassandraMailboxMapper;
+import org.apache.james.mailbox.cassandra.mail.CassandraMessageMapper;
+import org.apache.james.mailbox.cassandra.mail.CassandraModSeqProvider;
+import org.apache.james.mailbox.cassandra.mail.CassandraUidProvider;
+import org.apache.james.mailbox.cassandra.user.CassandraSubscriptionMapper;
+import org.apache.james.mailbox.exception.BadCredentialsException;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.store.MockAuthenticator;
+import org.apache.james.mailbox.store.StoreMailboxManager;
+import org.cassandraunit.CassandraCQLUnit;
+import org.cassandraunit.dataset.cql.ClassPathCQLDataSet;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.slf4j.LoggerFactory;
+
+/**
+ * InMemoryMailboxManagerTest that extends the MailboxManagerTest.
+ */
+public class CassandraMailboxManagerTest extends AbstractMailboxManagerTest {
+    
+	 @Rule public CassandraCQLUnit cassandraCQLUnit = 
+	    	new CassandraCQLUnit(new ClassPathCQLDataSet("mailbox.cql","mailbox"));
+
+	 @Before
+    public void setup() throws Exception {
+        createMailboxManager();
+    }
+    
+    @After
+    public void tearDown() throws BadCredentialsException, MailboxException {
+        MailboxSession session = getMailboxManager().createSystemSession("test", LoggerFactory.getLogger("Test"));
+        session.close();
+    }
+
+    @Override
+    protected void createMailboxManager() throws MailboxException {
+    	CassandraMailboxMapper mailboxMapper = new CassandraMailboxMapper(cassandraCQLUnit.session);
+    	CassandraMessageMapper messageMapper = new CassandraMessageMapper(cassandraCQLUnit.session, 
+    			new CassandraUidProvider(cassandraCQLUnit.session), 
+    			new CassandraModSeqProvider(cassandraCQLUnit.session));
+    	CassandraSubscriptionMapper subscriptionMapper = new CassandraSubscriptionMapper();
+        CassandraMailboxSessionMapperFactory factory = new CassandraMailboxSessionMapperFactory(mailboxMapper, messageMapper, subscriptionMapper);
+        MailboxACLResolver aclResolver = new UnionMailboxACLResolver();
+        GroupMembershipResolver groupMembershipResolver = new SimpleGroupMembershipResolver();
+
+        StoreMailboxManager<UUID> mailboxManager = new StoreMailboxManager<UUID>(factory, new MockAuthenticator(), aclResolver, groupMembershipResolver);
+        mailboxManager.init();
+        
+        setMailboxManager(mailboxManager);
+
+    }
+    
+}
diff --git a/cassandra/src/test/resources/logback.xml b/cassandra/src/test/resources/logback.xml
new file mode 100644
index 0000000..a50ae2f
--- /dev/null
+++ b/cassandra/src/test/resources/logback.xml
@@ -0,0 +1,15 @@
+<configuration debug="true">
+	<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+		<!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder 
+			by default -->
+		<encoder>
+			<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+			</pattern>
+		</encoder>
+	</appender>
+
+
+	<root level="debug">
+		<appender-ref ref="STDOUT" />
+	</root>
+</configuration>
diff --git a/cassandra/src/test/resources/mailbox.cql b/cassandra/src/test/resources/mailbox.cql
new file mode 100644
index 0000000..25c0f7b
--- /dev/null
+++ b/cassandra/src/test/resources/mailbox.cql
@@ -0,0 +1,40 @@
+CREATE TABLE mailbox (
+	id UUID PRIMARY KEY,
+	name text, namespace text,
+	uidvalidity bigint,
+	user text,
+	path text
+);
+CREATE INDEX ON mailbox(path);
+
+CREATE TABLE mailboxCounters (
+	mailboxId UUID PRIMARY KEY,
+	count counter, 
+	unseen counter,
+	nextUid counter,
+	nextModSeq counter
+);
+
+CREATE TABLE message (
+	mailboxId UUID, 
+	uid bigint,
+	internalDate timestamp, 
+	bodyStartOctet int,
+	content blob,
+	modSeq bigint,
+	mediaType text,
+	subType text,
+	fullContentOctets int,
+	bodyOctets int,
+	textualLineCount int,
+	bodyContent blob,
+	headerContent blob,
+	flagAnswered boolean,
+	flagDeleted boolean,
+	flagDraft boolean,
+	flagRecent boolean,
+	flagSeen boolean,
+	flagFlagged boolean,
+	flagUser boolean,
+	PRIMARY KEY (mailboxId, uid)
+	);
diff --git a/pom.xml b/pom.xml
index 8fd084d..4c1d0dc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -61,6 +61,7 @@
         <module>spring</module>
         <module>tool</module>
         <module>zoo-seq-provider</module>
+        <module>cassandra</module>
     </modules>
 
     <scm>
-- 
2.0.3


From 1b4aeca562d3e84fe2166bb1e86decb8ea9f3ff5 Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 14:19:07 +0200
Subject: [PATCH 02/35] Format all Java file

---
 .../CassandraMailboxSessionMapperFactory.java      |   9 +-
 .../cassandra/mail/CassandraMailboxMapper.java     |  66 ++--
 .../cassandra/mail/CassandraMessageMapper.java     | 408 +++++++++------------
 .../cassandra/mail/CassandraModSeqProvider.java    |  36 +-
 .../cassandra/mail/CassandraUidProvider.java       |  38 +-
 .../user/CassandraSubscriptionMapper.java          |   8 +-
 .../cassandra/CassandraMailboxManagerTest.java     |  22 +-
 7 files changed, 256 insertions(+), 331 deletions(-)

diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
index 6b7515d..4c9a9d7 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
@@ -41,14 +41,15 @@
     private MailboxMapper<UUID> mailboxMapper;
     private MessageMapper<UUID> messageMapper;
     private SubscriptionMapper subscriptionMapper;
-    
+
     @Inject
-    @VisibleForTesting CassandraMailboxSessionMapperFactory(CassandraMailboxMapper mailboxMapper, CassandraMessageMapper messageMapper, SubscriptionMapper subscriptionMapper) {
+    @VisibleForTesting
+    CassandraMailboxSessionMapperFactory(CassandraMailboxMapper mailboxMapper, CassandraMessageMapper messageMapper, SubscriptionMapper subscriptionMapper) {
         this.mailboxMapper = mailboxMapper;
         this.messageMapper = messageMapper;
-		this.subscriptionMapper = subscriptionMapper;
+        this.subscriptionMapper = subscriptionMapper;
     }
-    
+
     @Override
     public MailboxMapper<UUID> createMailboxMapper(MailboxSession session) throws MailboxException {
         return mailboxMapper;
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
index f0fe060..bcd60cc 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
@@ -50,9 +50,9 @@
 import com.google.common.collect.ImmutableList.Builder;
 
 public class CassandraMailboxMapper implements MailboxMapper<UUID> {
-    
-	private static final String[] FIELDS = {ID, USER, NAMESPACE, UIDVALIDITY, NAME, PATH};
-	private Session session;
+
+    private static final String[] FIELDS = { ID, USER, NAMESPACE, UIDVALIDITY, NAME, PATH };
+    private Session session;
 
     @Inject
     public CassandraMailboxMapper(Session session) {
@@ -74,22 +74,17 @@ public void delete(Mailbox<UUID> mailbox) throws MailboxException {
         }
     }
 
-	private SimpleMailbox<UUID> mailbox(Row row) {
-		SimpleMailbox<UUID> mailbox = new SimpleMailbox<UUID>(
-				new MailboxPath(
-						row.getString(NAMESPACE),
-						row.getString(USER),
-						row.getString(NAME)),
-				row.getLong(UIDVALIDITY));
-		mailbox.setMailboxId(row.getUUID(ID));
-		return mailbox;
-	}
-
-	@Override
+    private SimpleMailbox<UUID> mailbox(Row row) {
+        SimpleMailbox<UUID> mailbox = new SimpleMailbox<UUID>(new MailboxPath(row.getString(NAMESPACE), row.getString(USER), row.getString(NAME)), row.getLong(UIDVALIDITY));
+        mailbox.setMailboxId(row.getUUID(ID));
+        return mailbox;
+    }
+
+    @Override
     public List<Mailbox<UUID>> findMailboxWithPathLike(MailboxPath path) throws MailboxException {
         final String regex = path.getName().replace("%", ".*");
-        Builder<Mailbox<UUID>> result = ImmutableList.<Mailbox<UUID>>builder();
-        for (Row row: session.execute(select(FIELDS).from(TABLE_NAME))) {
+        Builder<Mailbox<UUID>> result = ImmutableList.<Mailbox<UUID>> builder();
+        for (Row row : session.execute(select(FIELDS).from(TABLE_NAME))) {
             if (row.getString(PATH).matches(regex)) {
                 result.add(mailbox(row));
             }
@@ -99,9 +94,9 @@ public void delete(Mailbox<UUID> mailbox) throws MailboxException {
 
     @Override
     public void save(Mailbox<UUID> mailbox) throws MailboxException {
-    	Preconditions.checkArgument(mailbox instanceof SimpleMailbox<?>);
-    	SimpleMailbox<UUID> simpleMailbox = (SimpleMailbox<UUID>) mailbox;
-    	UUID id = simpleMailbox.getMailboxId();
+        Preconditions.checkArgument(mailbox instanceof SimpleMailbox<?>);
+        SimpleMailbox<UUID> simpleMailbox = (SimpleMailbox<UUID>) mailbox;
+        UUID id = simpleMailbox.getMailboxId();
         if (id == null) {
             id = UUID.randomUUID();
             simpleMailbox.setMailboxId(id);
@@ -110,20 +105,13 @@ public void save(Mailbox<UUID> mailbox) throws MailboxException {
     }
 
     private void upsertMailbox(SimpleMailbox<UUID> mailbox) {
-    	session.execute(insertInto(TABLE_NAME)
-    			.value(ID, mailbox.getMailboxId())
-    			.value(NAME, mailbox.getName())
-    			.value(NAMESPACE, mailbox.getNamespace())
-    			.value(UIDVALIDITY, mailbox.getUidValidity())
-    			.value(USER, mailbox.getUser())
-    			.value(PATH, path(mailbox).toString())
-    			);
+        session.execute(insertInto(TABLE_NAME).value(ID, mailbox.getMailboxId()).value(NAME, mailbox.getName()).value(NAMESPACE, mailbox.getNamespace()).value(UIDVALIDITY, mailbox.getUidValidity()).value(USER, mailbox.getUser()).value(PATH, path(mailbox).toString()));
     }
-    
+
     private MailboxPath path(Mailbox<?> mailbox) {
-    	return new MailboxPath(mailbox.getNamespace(), mailbox.getUser(), mailbox.getName());
+        return new MailboxPath(mailbox.getNamespace(), mailbox.getUser(), mailbox.getName());
     }
-    
+
     @Override
     public void endRequest() {
         // Do nothing
@@ -131,23 +119,21 @@ public void endRequest() {
 
     @Override
     public boolean hasChildren(Mailbox<UUID> mailbox, char delimiter) throws MailboxException, MailboxNotFoundException {
-        return !findMailboxWithPathLike(
-        			new MailboxPath(mailbox.getNamespace(), mailbox.getUser(), mailbox.getName() + delimiter + "%"))
-        		.isEmpty();
+        return !findMailboxWithPathLike(new MailboxPath(mailbox.getNamespace(), mailbox.getUser(), mailbox.getName() + delimiter + "%")).isEmpty();
     }
 
     @Override
     public List<Mailbox<UUID>> list() throws MailboxException {
-        Builder<Mailbox<UUID>> result = ImmutableList.<Mailbox<UUID>>builder();
-    	for (Row row: session.execute(select(FIELDS).from(TABLE_NAME))) {
-    		result.add(mailbox(row));
-    	}
-    	return result.build();
+        Builder<Mailbox<UUID>> result = ImmutableList.<Mailbox<UUID>> builder();
+        for (Row row : session.execute(select(FIELDS).from(TABLE_NAME))) {
+            result.add(mailbox(row));
+        }
+        return result.build();
     }
 
     @Override
     public <T> T execute(Transaction<T> transaction) throws MailboxException {
         return transaction.run();
     }
-    
+
 }
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
index c12c8bf..255a424 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
@@ -74,184 +74,156 @@
 
 public class CassandraMessageMapper implements MessageMapper<UUID> {
 
-	private static final String[] FIELDS = {
-		MessageTable.MAILBOX_ID, MessageTable.IMAP_UID, MessageTable.INTERNAL_DATE, MessageTable.MOD_SEQ,
-		MessageTable.BODY_START_OCTET,
-		MessageTable.MEDIA_TYPE, MessageTable.SUB_TYPE, MessageTable.FULL_CONTENT_OCTETS,
-		MessageTable.BODY_OCTECTS, MessageTable.Flag.ANSWERED, MessageTable.Flag.DELETED,
-		MessageTable.Flag.DRAFT, MessageTable.Flag.FLAGGED, MessageTable.Flag.RECENT,
-		MessageTable.Flag.SEEN,	MessageTable.Flag.USER, MessageTable.BODY_CONTENT, MessageTable.HEADER_CONTENT};
-	private Session session;
-	private ModSeqProvider<UUID> modSeqProvider;
-	private MailboxSession mailboxSession;
-	private UidProvider<UUID> uidProvider;
+    private static final String[] FIELDS = { MessageTable.MAILBOX_ID, MessageTable.IMAP_UID, MessageTable.INTERNAL_DATE, MessageTable.MOD_SEQ, MessageTable.BODY_START_OCTET, MessageTable.MEDIA_TYPE, MessageTable.SUB_TYPE, MessageTable.FULL_CONTENT_OCTETS, MessageTable.BODY_OCTECTS,
+            MessageTable.Flag.ANSWERED, MessageTable.Flag.DELETED, MessageTable.Flag.DRAFT, MessageTable.Flag.FLAGGED, MessageTable.Flag.RECENT, MessageTable.Flag.SEEN, MessageTable.Flag.USER, MessageTable.BODY_CONTENT, MessageTable.HEADER_CONTENT };
+    private Session session;
+    private ModSeqProvider<UUID> modSeqProvider;
+    private MailboxSession mailboxSession;
+    private UidProvider<UUID> uidProvider;
 
     @Inject
-    public CassandraMessageMapper(Session session, UidProvider<UUID> uidProvider,
-            ModSeqProvider<UUID> modSeqProvider) {
-		this.session = session;
-		this.uidProvider = uidProvider;
-		this.modSeqProvider = modSeqProvider;
+    public CassandraMessageMapper(Session session, UidProvider<UUID> uidProvider, ModSeqProvider<UUID> modSeqProvider) {
+        this.session = session;
+        this.uidProvider = uidProvider;
+        this.modSeqProvider = modSeqProvider;
     }
 
     @Override
     public long countMessagesInMailbox(Mailbox<UUID> mailbox) throws MailboxException {
-        ResultSet results = session.execute(
-        		select(MailboxCountersTable.COUNT).from(MailboxCountersTable.TABLE_NAME).where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
+        ResultSet results = session.execute(select(MailboxCountersTable.COUNT).from(MailboxCountersTable.TABLE_NAME).where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
         if (results.isExhausted()) {
-        	return 0;
+            return 0;
         } else {
-        	return results.one().getLong(MailboxCountersTable.COUNT);
+            return results.one().getLong(MailboxCountersTable.COUNT);
         }
     }
 
     @Override
     public long countUnseenMessagesInMailbox(Mailbox<UUID> mailbox) throws MailboxException {
-    	ResultSet results = session.execute(
-        		select(MailboxCountersTable.COUNT).from(MailboxCountersTable.TABLE_NAME).where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
+        ResultSet results = session.execute(select(MailboxCountersTable.COUNT).from(MailboxCountersTable.TABLE_NAME).where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
         if (!results.isExhausted()) {
-        	Row row = results.one();
-        	if (row.getColumnDefinitions().contains(MailboxCountersTable.UNSEEN)) {
-        		return row.getLong(MailboxCountersTable.UNSEEN);
-        	}
+            Row row = results.one();
+            if (row.getColumnDefinitions().contains(MailboxCountersTable.UNSEEN)) {
+                return row.getLong(MailboxCountersTable.UNSEEN);
+            }
         }
         return 0;
     }
 
     @Override
     public void delete(Mailbox<UUID> mailbox, Message<UUID> message) throws MailboxException {
-    	session.execute(QueryBuilder.delete()
-    			.from(MessageTable.TABLE_NAME)
-    			.where(eq(MessageTable.MAILBOX_ID, mailbox.getMailboxId()))
-    			.and(eq(MessageTable.IMAP_UID, message.getUid())));
-    	decrementCount(mailbox);
-    	if (!message.isSeen()) {
-    		decrementUnseen(mailbox);
-    	}
+        session.execute(QueryBuilder.delete().from(MessageTable.TABLE_NAME).where(eq(MessageTable.MAILBOX_ID, mailbox.getMailboxId())).and(eq(MessageTable.IMAP_UID, message.getUid())));
+        decrementCount(mailbox);
+        if (!message.isSeen()) {
+            decrementUnseen(mailbox);
+        }
+    }
+
+    private void decrementCount(Mailbox<UUID> mailbox) {
+        updateMailbox(mailbox, decr(MailboxCountersTable.COUNT));
     }
 
-	private void decrementCount(Mailbox<UUID> mailbox) {
-		updateMailbox(mailbox, decr(MailboxCountersTable.COUNT));
-	}
-
-	private void incrementCount(Mailbox<UUID> mailbox) {
-		updateMailbox(mailbox, incr(MailboxCountersTable.COUNT));
-	}
-	
-	private void decrementUnseen(Mailbox<UUID> mailbox) {
-		updateMailbox(mailbox, decr(MailboxCountersTable.UNSEEN));
-	}
-
-	private void incrementUnseen(Mailbox<UUID> mailbox) {
-		updateMailbox(mailbox, incr(MailboxCountersTable.UNSEEN));
-	}
-
-	
-	private void updateMailbox(Mailbox<UUID> mailbox, Assignment operation) {
-		session.execute(update(MailboxCountersTable.TABLE_NAME)
-				.with(operation)
-				.where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
-	}
+    private void incrementCount(Mailbox<UUID> mailbox) {
+        updateMailbox(mailbox, incr(MailboxCountersTable.COUNT));
+    }
+
+    private void decrementUnseen(Mailbox<UUID> mailbox) {
+        updateMailbox(mailbox, decr(MailboxCountersTable.UNSEEN));
+    }
+
+    private void incrementUnseen(Mailbox<UUID> mailbox) {
+        updateMailbox(mailbox, incr(MailboxCountersTable.UNSEEN));
+    }
+
+    private void updateMailbox(Mailbox<UUID> mailbox, Assignment operation) {
+        session.execute(update(MailboxCountersTable.TABLE_NAME).with(operation).where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
+    }
 
     @Override
-    public Iterator<Message<UUID>> findInMailbox(Mailbox<UUID> mailbox, MessageRange set, FetchType ftype, int max)
-            throws MailboxException {
-    	Builder<Message<UUID>> result = ImmutableSortedSet.<Message<UUID>>naturalOrder();
-    	ResultSet rows = session.execute(buildQuery(mailbox, set));
-        for (Row row: rows) {
-        	result.add(message(row));
+    public Iterator<Message<UUID>> findInMailbox(Mailbox<UUID> mailbox, MessageRange set, FetchType ftype, int max) throws MailboxException {
+        Builder<Message<UUID>> result = ImmutableSortedSet.<Message<UUID>> naturalOrder();
+        ResultSet rows = session.execute(buildQuery(mailbox, set));
+        for (Row row : rows) {
+            result.add(message(row));
         }
         return result.build().iterator();
     }
 
-	private Message<UUID> message(Row row) {
-		SimpleMessage<UUID> message = new SimpleMessage<UUID>(
-				row.getDate(MessageTable.INTERNAL_DATE),
-				row.getInt(MessageTable.FULL_CONTENT_OCTETS),
-				row.getInt(MessageTable.BODY_START_OCTET),
-				new SharedByteArrayInputStream(row.getBytes(MessageTable.BODY_CONTENT).array()),
-				new Flags(),
-				new PropertyBuilder(), 
-				row.getUUID(MessageTable.MAILBOX_ID));
-		message.setUid(row.getLong(MessageTable.IMAP_UID));
-		return message;
-	}
-	
-	private Where buildQuery(Mailbox<UUID> mailbox, MessageRange set) {
-		final MessageRange.Type type = set.getType();
+    private Message<UUID> message(Row row) {
+        SimpleMessage<UUID> message = new SimpleMessage<UUID>(row.getDate(MessageTable.INTERNAL_DATE), row.getInt(MessageTable.FULL_CONTENT_OCTETS), row.getInt(MessageTable.BODY_START_OCTET), new SharedByteArrayInputStream(row.getBytes(MessageTable.BODY_CONTENT).array()), new Flags(),
+                new PropertyBuilder(), row.getUUID(MessageTable.MAILBOX_ID));
+        message.setUid(row.getLong(MessageTable.IMAP_UID));
+        return message;
+    }
+
+    private Where buildQuery(Mailbox<UUID> mailbox, MessageRange set) {
+        final MessageRange.Type type = set.getType();
         switch (type) {
         case ALL:
             return selectAll(mailbox);
         case FROM:
-        	return selectFrom(mailbox, set.getUidFrom());
+            return selectFrom(mailbox, set.getUidFrom());
         case RANGE:
-        	return selectRange(mailbox, set.getUidFrom(), set.getUidTo());
+            return selectRange(mailbox, set.getUidFrom(), set.getUidTo());
         case ONE:
-        	return selectMessage(mailbox, set.getUidFrom());
+            return selectMessage(mailbox, set.getUidFrom());
         }
         throw new UnsupportedOperationException();
-	}
-
-	private Where selectAll(Mailbox<UUID> mailbox) {
-		return select(FIELDS).from(MessageTable.TABLE_NAME).where(eq(MessageTable.MAILBOX_ID, mailbox.getMailboxId()));
-	}
-	
-	private Where selectFrom(Mailbox<UUID> mailbox, long uid) {
-		return select(FIELDS).from(MessageTable.TABLE_NAME).where(eq(MessageTable.MAILBOX_ID, mailbox.getMailboxId())).and(gt(MessageTable.IMAP_UID, uid));
-	}
-
-
-	private Where selectRange(Mailbox<UUID> mailbox, long from, long to) {
-		return select(FIELDS).from(MessageTable.TABLE_NAME)
-					.where(eq(MessageTable.MAILBOX_ID, mailbox.getMailboxId()))
-					.and(gt(MessageTable.IMAP_UID, from))
-					.and(lt(MessageTable.IMAP_UID, to));
-	}
-
-	private Where selectMessage(Mailbox<UUID> mailbox, long uid) {
-		return select(FIELDS).from(MessageTable.TABLE_NAME)
-				.where(eq(MessageTable.MAILBOX_ID, mailbox.getMailboxId()))
-				.and(eq(MessageTable.IMAP_UID, uid));
-	}
-	
-	@Override
-	public List<Long> findRecentMessageUidsInMailbox(Mailbox<UUID> mailbox) throws MailboxException {
-		ImmutableList.Builder<Long> result = ImmutableList.<Long>builder();
-    	ResultSet rows = session.execute(selectAll(mailbox).orderBy(asc(MessageTable.IMAP_UID)));
-        for (Row row: rows) {
-        	Message<UUID> message = message(row);
-        	if (message.isRecent()) {
-        		result.add(message.getUid());
-        	}
+    }
+
+    private Where selectAll(Mailbox<UUID> mailbox) {
+        return select(FIELDS).from(MessageTable.TABLE_NAME).where(eq(MessageTable.MAILBOX_ID, mailbox.getMailboxId()));
+    }
+
+    private Where selectFrom(Mailbox<UUID> mailbox, long uid) {
+        return select(FIELDS).from(MessageTable.TABLE_NAME).where(eq(MessageTable.MAILBOX_ID, mailbox.getMailboxId())).and(gt(MessageTable.IMAP_UID, uid));
+    }
+
+    private Where selectRange(Mailbox<UUID> mailbox, long from, long to) {
+        return select(FIELDS).from(MessageTable.TABLE_NAME).where(eq(MessageTable.MAILBOX_ID, mailbox.getMailboxId())).and(gt(MessageTable.IMAP_UID, from)).and(lt(MessageTable.IMAP_UID, to));
+    }
+
+    private Where selectMessage(Mailbox<UUID> mailbox, long uid) {
+        return select(FIELDS).from(MessageTable.TABLE_NAME).where(eq(MessageTable.MAILBOX_ID, mailbox.getMailboxId())).and(eq(MessageTable.IMAP_UID, uid));
+    }
+
+    @Override
+    public List<Long> findRecentMessageUidsInMailbox(Mailbox<UUID> mailbox) throws MailboxException {
+        ImmutableList.Builder<Long> result = ImmutableList.<Long> builder();
+        ResultSet rows = session.execute(selectAll(mailbox).orderBy(asc(MessageTable.IMAP_UID)));
+        for (Row row : rows) {
+            Message<UUID> message = message(row);
+            if (message.isRecent()) {
+                result.add(message.getUid());
+            }
         }
         return result.build();
     }
 
-
-	@Override
+    @Override
     public Long findFirstUnseenMessageUid(Mailbox<UUID> mailbox) throws MailboxException {
-		ResultSet rows = session.execute(selectAll(mailbox).orderBy(asc(MessageTable.IMAP_UID)));
-        for (Row row: rows) {
-        	Message<UUID> message = message(row);
-        	if (!message.isSeen()) {
-        		return message.getUid();
-        	}
+        ResultSet rows = session.execute(selectAll(mailbox).orderBy(asc(MessageTable.IMAP_UID)));
+        for (Row row : rows) {
+            Message<UUID> message = message(row);
+            if (!message.isSeen()) {
+                return message.getUid();
+            }
         }
         return null;
     }
 
     @Override
     public Map<Long, MessageMetaData> expungeMarkedForDeletionInMailbox(final Mailbox<UUID> mailbox, MessageRange set) throws MailboxException {
-    	ImmutableMap.Builder<Long, MessageMetaData> deletedMessages = ImmutableMap.builder();
-    	ResultSet messages = session.execute(buildQuery(mailbox, set));
-    	for (Row row: messages) {
-    		Message<UUID> message = message(row);
-    		if (message.isDeleted()) {
-    			delete(mailbox, message);
-    			deletedMessages.put(message.getUid(), new SimpleMessageMetaData(message));
-    		}
-    	}
-    	return deletedMessages.build();
+        ImmutableMap.Builder<Long, MessageMetaData> deletedMessages = ImmutableMap.builder();
+        ResultSet messages = session.execute(buildQuery(mailbox, set));
+        for (Row row : messages) {
+            Message<UUID> message = message(row);
+            if (message.isDeleted()) {
+                delete(mailbox, message);
+                deletedMessages.put(message.getUid(), new SimpleMessageMetaData(message));
+            }
+        }
+        return deletedMessages.build();
     }
 
     @Override
@@ -266,106 +238,86 @@ public void endRequest() {
 
     @Override
     public long getHighestModSeq(Mailbox<UUID> mailbox) throws MailboxException {
-    	return modSeqProvider.highestModSeq(mailboxSession, mailbox);
+        return modSeqProvider.highestModSeq(mailboxSession, mailbox);
     }
 
-	@Override
-	public <T> T execute(Transaction<T> transaction) throws MailboxException {
-		return transaction.run();
-	}
-
-	@Override
-	public MessageMetaData add(Mailbox<UUID> mailbox, Message<UUID> message)
-			throws MailboxException {
-		message.setUid(uidProvider.nextUid(mailboxSession, mailbox));
-		message.setModSeq(modSeqProvider.nextModSeq(mailboxSession, mailbox));
-		MessageMetaData messageMetaData = save(mailbox, message);
-		incrementUnseen(mailbox);
-		incrementCount(mailbox);
-		return messageMetaData;
-	}
-
-	private MessageMetaData save(Mailbox<UUID> mailbox, Message<UUID> message) throws MailboxException {
-		try {
-			Insert query = insertInto(MessageTable.TABLE_NAME)
-				.value(MessageTable.MAILBOX_ID, mailbox.getMailboxId())
-				.value(MessageTable.IMAP_UID, message.getUid())
-				.value(MessageTable.MOD_SEQ, message.getModSeq())
-				.value(MessageTable.INTERNAL_DATE, message.getInternalDate())
-				.value(MessageTable.MEDIA_TYPE, message.getMediaType())
-				.value(MessageTable.SUB_TYPE, message.getSubType())
-				.value(MessageTable.FULL_CONTENT_OCTETS, message.getFullContentOctets())
-				.value(MessageTable.BODY_OCTECTS, message.getBodyOctets())
-				.value(MessageTable.Flag.ANSWERED, message.isAnswered())
-				.value(MessageTable.Flag.DELETED, message.isDeleted())
-				.value(MessageTable.Flag.DRAFT, message.isDraft())
-				.value(MessageTable.Flag.FLAGGED, message.isFlagged())
-				.value(MessageTable.Flag.RECENT, message.isRecent())
-				.value(MessageTable.Flag.SEEN, message.isSeen())
-				.value(MessageTable.Flag.USER, message.createFlags().contains(Flag.USER))
-				.value(MessageTable.BODY_CONTENT, bindMarker())
-				.value(MessageTable.HEADER_CONTENT, bindMarker());
-			if (message.getTextualLineCount() != null) {
-				query.value(MessageTable.TEXTUAL_LINE_COUNT, message.getTextualLineCount());
-			}
-			PreparedStatement preparedStatement = session.prepare(query.toString());
-			BoundStatement boundStatement = preparedStatement.bind(
-					toByteBuffer(message.getBodyContent()),
-					toByteBuffer(message.getHeaderContent()));
-			session.execute(boundStatement);
-			return new SimpleMessageMetaData(message);
-		} catch (IOException e) {
-			throw new MailboxException("Error saving mail", e);
-		}
-	}
-
-	private ByteBuffer toByteBuffer(InputStream stream) throws IOException {
-		return ByteBuffer.wrap(ByteStreams.toByteArray(stream));
-	}
-
-	@Override
-	public Iterator<UpdatedFlags> updateFlags(Mailbox<UUID> mailbox,
-			Flags flags, boolean value, boolean replace, MessageRange set)
-			throws MailboxException {
-		ImmutableList.Builder<UpdatedFlags> result = ImmutableList.builder();
-		ResultSet messages = session.execute(buildQuery(mailbox, set));
-    	for (Row row: messages) {
-    		Message<UUID> message = message(row);
-    		Flags originFlags = message.createFlags();
-    		Flags updatedFlags = buildFlags(message, flags, value, replace);
-    		message.setFlags(updatedFlags);
-    		message.setModSeq(modSeqProvider.nextModSeq(mailboxSession, mailbox));
-    		save(mailbox, message);
-    		result.add(new UpdatedFlags(message.getUid(), message.getModSeq(), originFlags, updatedFlags));
-    	}
-    	return result.build().iterator();
-	}
-
-	private Flags buildFlags(Message<UUID> message, Flags flags, boolean value, boolean replace) {
-		if (replace) {
-			return message.createFlags();
-		} else {
-			Flags updatedFlags = message.createFlags();
-			if (value) {
-				updatedFlags.add(flags);
-			} else {
-				updatedFlags.remove(flags);
-			}
-			return updatedFlags;
-		}
-	}
-
-	@Override
-	public MessageMetaData copy(Mailbox<UUID> mailbox, Message<UUID> original) throws MailboxException {
+    @Override
+    public <T> T execute(Transaction<T> transaction) throws MailboxException {
+        return transaction.run();
+    }
+
+    @Override
+    public MessageMetaData add(Mailbox<UUID> mailbox, Message<UUID> message) throws MailboxException {
+        message.setUid(uidProvider.nextUid(mailboxSession, mailbox));
+        message.setModSeq(modSeqProvider.nextModSeq(mailboxSession, mailbox));
+        MessageMetaData messageMetaData = save(mailbox, message);
+        incrementUnseen(mailbox);
+        incrementCount(mailbox);
+        return messageMetaData;
+    }
+
+    private MessageMetaData save(Mailbox<UUID> mailbox, Message<UUID> message) throws MailboxException {
+        try {
+            Insert query = insertInto(MessageTable.TABLE_NAME).value(MessageTable.MAILBOX_ID, mailbox.getMailboxId()).value(MessageTable.IMAP_UID, message.getUid()).value(MessageTable.MOD_SEQ, message.getModSeq()).value(MessageTable.INTERNAL_DATE, message.getInternalDate())
+                    .value(MessageTable.MEDIA_TYPE, message.getMediaType()).value(MessageTable.SUB_TYPE, message.getSubType()).value(MessageTable.FULL_CONTENT_OCTETS, message.getFullContentOctets()).value(MessageTable.BODY_OCTECTS, message.getBodyOctets())
+                    .value(MessageTable.Flag.ANSWERED, message.isAnswered()).value(MessageTable.Flag.DELETED, message.isDeleted()).value(MessageTable.Flag.DRAFT, message.isDraft()).value(MessageTable.Flag.FLAGGED, message.isFlagged()).value(MessageTable.Flag.RECENT, message.isRecent())
+                    .value(MessageTable.Flag.SEEN, message.isSeen()).value(MessageTable.Flag.USER, message.createFlags().contains(Flag.USER)).value(MessageTable.BODY_CONTENT, bindMarker()).value(MessageTable.HEADER_CONTENT, bindMarker());
+            if (message.getTextualLineCount() != null) {
+                query.value(MessageTable.TEXTUAL_LINE_COUNT, message.getTextualLineCount());
+            }
+            PreparedStatement preparedStatement = session.prepare(query.toString());
+            BoundStatement boundStatement = preparedStatement.bind(toByteBuffer(message.getBodyContent()), toByteBuffer(message.getHeaderContent()));
+            session.execute(boundStatement);
+            return new SimpleMessageMetaData(message);
+        } catch (IOException e) {
+            throw new MailboxException("Error saving mail", e);
+        }
+    }
+
+    private ByteBuffer toByteBuffer(InputStream stream) throws IOException {
+        return ByteBuffer.wrap(ByteStreams.toByteArray(stream));
+    }
+
+    @Override
+    public Iterator<UpdatedFlags> updateFlags(Mailbox<UUID> mailbox, Flags flags, boolean value, boolean replace, MessageRange set) throws MailboxException {
+        ImmutableList.Builder<UpdatedFlags> result = ImmutableList.builder();
+        ResultSet messages = session.execute(buildQuery(mailbox, set));
+        for (Row row : messages) {
+            Message<UUID> message = message(row);
+            Flags originFlags = message.createFlags();
+            Flags updatedFlags = buildFlags(message, flags, value, replace);
+            message.setFlags(updatedFlags);
+            message.setModSeq(modSeqProvider.nextModSeq(mailboxSession, mailbox));
+            save(mailbox, message);
+            result.add(new UpdatedFlags(message.getUid(), message.getModSeq(), originFlags, updatedFlags));
+        }
+        return result.build().iterator();
+    }
+
+    private Flags buildFlags(Message<UUID> message, Flags flags, boolean value, boolean replace) {
+        if (replace) {
+            return message.createFlags();
+        } else {
+            Flags updatedFlags = message.createFlags();
+            if (value) {
+                updatedFlags.add(flags);
+            } else {
+                updatedFlags.remove(flags);
+            }
+            return updatedFlags;
+        }
+    }
+
+    @Override
+    public MessageMetaData copy(Mailbox<UUID> mailbox, Message<UUID> original) throws MailboxException {
         original.setUid(uidProvider.nextUid(mailboxSession, mailbox));
         original.setModSeq(modSeqProvider.nextModSeq(mailboxSession, mailbox));
         return save(mailbox, original);
-	}
-
-	@Override
-	public long getLastUid(Mailbox<UUID> mailbox) throws MailboxException {
-		return uidProvider.lastUid(mailboxSession, mailbox);
-	}
-    
-    
+    }
+
+    @Override
+    public long getLastUid(Mailbox<UUID> mailbox) throws MailboxException {
+        return uidProvider.lastUid(mailboxSession, mailbox);
+    }
+
 }
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProvider.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProvider.java
index 5d1ef12..034b391 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProvider.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProvider.java
@@ -40,32 +40,26 @@
 @Singleton
 public class CassandraModSeqProvider implements ModSeqProvider<UUID> {
 
-	private Session session;
-	
-	@Inject
-	public CassandraModSeqProvider(Session session) {
-		this.session = session;
-	}
-	
+    private Session session;
+
+    @Inject
+    public CassandraModSeqProvider(Session session) {
+        this.session = session;
+    }
+
     @Override
     public long nextModSeq(MailboxSession mailboxSession, Mailbox<UUID> mailbox) throws MailboxException {
-    	session.execute(
-    			update(MailboxCountersTable.TABLE_NAME)
-    				.with(incr(MailboxCountersTable.NEXT_MOD_SEQ))
-    				.where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
-    	return highestModSeq(mailboxSession, mailbox);
+        session.execute(update(MailboxCountersTable.TABLE_NAME).with(incr(MailboxCountersTable.NEXT_MOD_SEQ)).where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
+        return highestModSeq(mailboxSession, mailbox);
     }
 
     @Override
     public long highestModSeq(MailboxSession mailboxSession, Mailbox<UUID> mailbox) throws MailboxException {
-    	ResultSet result = session.execute(
-    			select(MailboxCountersTable.NEXT_MOD_SEQ)
-    				.from(MailboxCountersTable.TABLE_NAME)
-    				.where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
-    	if (result.isExhausted()) {
-    		return 0;
-    	} else {
-    		return result.one().getLong(MailboxCountersTable.NEXT_MOD_SEQ);
-    	}        
+        ResultSet result = session.execute(select(MailboxCountersTable.NEXT_MOD_SEQ).from(MailboxCountersTable.TABLE_NAME).where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
+        if (result.isExhausted()) {
+            return 0;
+        } else {
+            return result.one().getLong(MailboxCountersTable.NEXT_MOD_SEQ);
+        }
     }
 }
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProvider.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProvider.java
index 16fc681..93225cc 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProvider.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProvider.java
@@ -37,34 +37,28 @@
 import com.datastax.driver.core.Session;
 
 public class CassandraUidProvider implements UidProvider<UUID> {
-    
-	private Session session;
-	
-	@Inject
-	public CassandraUidProvider(Session session) {
-		this.session = session;
-	}
 
-	@Override
+    private Session session;
+
+    @Inject
+    public CassandraUidProvider(Session session) {
+        this.session = session;
+    }
+
+    @Override
     public long nextUid(MailboxSession mailboxSession, Mailbox<UUID> mailbox) throws MailboxException {
-    	session.execute(
-    			update(MailboxCountersTable.TABLE_NAME)
-    				.with(incr(MailboxCountersTable.NEXT_UID))
-    				.where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
-    	return lastUid(mailboxSession, mailbox);
+        session.execute(update(MailboxCountersTable.TABLE_NAME).with(incr(MailboxCountersTable.NEXT_UID)).where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
+        return lastUid(mailboxSession, mailbox);
     }
 
     @Override
     public long lastUid(MailboxSession mailboxSession, Mailbox<UUID> mailbox) throws MailboxException {
-    	ResultSet result = session.execute(
-    			select(MailboxCountersTable.NEXT_UID)
-    				.from(MailboxCountersTable.TABLE_NAME)
-    				.where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
-    	if (result.isExhausted()) {
-    		return 0;
-    	} else {
-    		return result.one().getLong(MailboxCountersTable.NEXT_UID);
-    	}        
+        ResultSet result = session.execute(select(MailboxCountersTable.NEXT_UID).from(MailboxCountersTable.TABLE_NAME).where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
+        if (result.isExhausted()) {
+            return 0;
+        } else {
+            return result.one().getLong(MailboxCountersTable.NEXT_UID);
+        }
     }
 
 }
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java
index 1bc52ee..4ca752e 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java
@@ -32,10 +32,10 @@
 
 @Singleton
 public class CassandraSubscriptionMapper extends NonTransactionalMapper implements SubscriptionMapper {
-    
+
     private static final int INITIAL_SIZE = 64;
     private final Map<String, List<Subscription>> subscriptionsByUser;
-    
+
     public CassandraSubscriptionMapper() {
         subscriptionsByUser = new ConcurrentHashMap<String, List<Subscription>>(INITIAL_SIZE);
     }
@@ -54,7 +54,7 @@ public Subscription findMailboxSubscriptionForUser(String user, String mailbox)
         final List<Subscription> subscriptions = subscriptionsByUser.get(user);
         Subscription result = null;
         if (subscriptions != null) {
-            for(Subscription subscription:subscriptions) {
+            for (Subscription subscription : subscriptions) {
                 if (subscription.getMailbox().equals(mailbox)) {
                     result = subscription;
                     break;
@@ -82,7 +82,7 @@ public synchronized void save(Subscription subscription) {
         final String user = subscription.getUser();
         final List<Subscription> subscriptions = subscriptionsByUser.get(user);
         if (subscriptions == null) {
-            final List<Subscription> newSubscriptions  = new ArrayList<Subscription>();
+            final List<Subscription> newSubscriptions = new ArrayList<Subscription>();
             newSubscriptions.add(subscription);
             subscriptionsByUser.put(user, newSubscriptions);
         } else {
diff --git a/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java
index 872ede2..1384bdb 100644
--- a/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java
+++ b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java
@@ -46,15 +46,15 @@
  * InMemoryMailboxManagerTest that extends the MailboxManagerTest.
  */
 public class CassandraMailboxManagerTest extends AbstractMailboxManagerTest {
-    
-	 @Rule public CassandraCQLUnit cassandraCQLUnit = 
-	    	new CassandraCQLUnit(new ClassPathCQLDataSet("mailbox.cql","mailbox"));
 
-	 @Before
+    @Rule
+    public CassandraCQLUnit cassandraCQLUnit = new CassandraCQLUnit(new ClassPathCQLDataSet("mailbox.cql", "mailbox"));
+
+    @Before
     public void setup() throws Exception {
         createMailboxManager();
     }
-    
+
     @After
     public void tearDown() throws BadCredentialsException, MailboxException {
         MailboxSession session = getMailboxManager().createSystemSession("test", LoggerFactory.getLogger("Test"));
@@ -63,20 +63,18 @@ public void tearDown() throws BadCredentialsException, MailboxException {
 
     @Override
     protected void createMailboxManager() throws MailboxException {
-    	CassandraMailboxMapper mailboxMapper = new CassandraMailboxMapper(cassandraCQLUnit.session);
-    	CassandraMessageMapper messageMapper = new CassandraMessageMapper(cassandraCQLUnit.session, 
-    			new CassandraUidProvider(cassandraCQLUnit.session), 
-    			new CassandraModSeqProvider(cassandraCQLUnit.session));
-    	CassandraSubscriptionMapper subscriptionMapper = new CassandraSubscriptionMapper();
+        CassandraMailboxMapper mailboxMapper = new CassandraMailboxMapper(cassandraCQLUnit.session);
+        CassandraMessageMapper messageMapper = new CassandraMessageMapper(cassandraCQLUnit.session, new CassandraUidProvider(cassandraCQLUnit.session), new CassandraModSeqProvider(cassandraCQLUnit.session));
+        CassandraSubscriptionMapper subscriptionMapper = new CassandraSubscriptionMapper();
         CassandraMailboxSessionMapperFactory factory = new CassandraMailboxSessionMapperFactory(mailboxMapper, messageMapper, subscriptionMapper);
         MailboxACLResolver aclResolver = new UnionMailboxACLResolver();
         GroupMembershipResolver groupMembershipResolver = new SimpleGroupMembershipResolver();
 
         StoreMailboxManager<UUID> mailboxManager = new StoreMailboxManager<UUID>(factory, new MockAuthenticator(), aclResolver, groupMembershipResolver);
         mailboxManager.init();
-        
+
         setMailboxManager(mailboxManager);
 
     }
-    
+
 }
-- 
2.0.3


From c1f9f985f41253fddcdd4115811d22e7bc4008e5 Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 14:29:43 +0200
Subject: [PATCH 03/35] Remove old description table

---
 .../cassandra/mail/MailboxCountersTable.java       | 42 ---------------
 .../james/mailbox/cassandra/mail/MailboxTable.java | 43 ---------------
 .../james/mailbox/cassandra/mail/MessageTable.java | 63 ----------------------
 3 files changed, 148 deletions(-)
 delete mode 100644 cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MailboxCountersTable.java
 delete mode 100644 cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MailboxTable.java
 delete mode 100644 cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MessageTable.java

diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MailboxCountersTable.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MailboxCountersTable.java
deleted file mode 100644
index 7b76f14..0000000
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MailboxCountersTable.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * 
- * Copyright (C) 2013 Linagora
- *
- * This program is free software: you can redistribute it and/or 
- * modify it under the terms of the GNU Affero General Public License as 
- * published by the Free Software Foundation, either version 3 of the 
- * License, or (at your option) any later version, provided you comply 
- * with the Additional Terms applicable for OBM connector by Linagora 
- * pursuant to Section 7 of the GNU Affero General Public License, 
- * subsections (b), (c), and (e), pursuant to which you must notably (i) retain 
- * the “Message sent thanks to OBM, Free Communication by Linagora” 
- * signature notice appended to any and all outbound messages 
- * (notably e-mail and meeting requests), (ii) retain all hypertext links between 
- * OBM and obm.org, as well as between Linagora and linagora.com, and (iii) refrain 
- * from infringing Linagora intellectual property rights over its trademarks 
- * and commercial brands. Other Additional Terms apply, 
- * see <http://www.linagora.com/licenses/> for more details. 
- *
- * This program is distributed in the hope that it will be useful, 
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
- * for more details. 
- *
- * You should have received a copy of the GNU Affero General Public License 
- * and its applicable Additional Terms for OBM along with this program. If not, 
- * see <http://www.gnu.org/licenses/> for the GNU Affero General Public License version 3 
- * and <http://www.linagora.com/licenses/> for the Additional Terms applicable to 
- * OBM connectors. 
- * 
- * ***** END LICENSE BLOCK ***** */
-package org.apache.james.mailbox.cassandra.mail;
-
-public interface MailboxCountersTable {
-	String TABLE_NAME = "mailboxCounters";
-	String MAILBOX_ID = "mailboxId";
-	String COUNT = "count";
-	String UNSEEN = "unseen";
-	String NEXT_UID = "nextUid";
-	String NEXT_MOD_SEQ = "nextModSeq";
-
-}
\ No newline at end of file
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MailboxTable.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MailboxTable.java
deleted file mode 100644
index 337d2ae..0000000
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MailboxTable.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * 
- * Copyright (C) 2013 Linagora
- *
- * This program is free software: you can redistribute it and/or 
- * modify it under the terms of the GNU Affero General Public License as 
- * published by the Free Software Foundation, either version 3 of the 
- * License, or (at your option) any later version, provided you comply 
- * with the Additional Terms applicable for OBM connector by Linagora 
- * pursuant to Section 7 of the GNU Affero General Public License, 
- * subsections (b), (c), and (e), pursuant to which you must notably (i) retain 
- * the “Message sent thanks to OBM, Free Communication by Linagora” 
- * signature notice appended to any and all outbound messages 
- * (notably e-mail and meeting requests), (ii) retain all hypertext links between 
- * OBM and obm.org, as well as between Linagora and linagora.com, and (iii) refrain 
- * from infringing Linagora intellectual property rights over its trademarks 
- * and commercial brands. Other Additional Terms apply, 
- * see <http://www.linagora.com/licenses/> for more details. 
- *
- * This program is distributed in the hope that it will be useful, 
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
- * for more details. 
- *
- * You should have received a copy of the GNU Affero General Public License 
- * and its applicable Additional Terms for OBM along with this program. If not, 
- * see <http://www.gnu.org/licenses/> for the GNU Affero General Public License version 3 
- * and <http://www.linagora.com/licenses/> for the Additional Terms applicable to 
- * OBM connectors. 
- * 
- * ***** END LICENSE BLOCK ***** */
-package org.apache.james.mailbox.cassandra.mail;
-
-public interface MailboxTable {
-
-	String TABLE_NAME = "mailbox";
-	String ID = "id";
-    String USER = "user";
-    String PATH = "path";
-    String NAMESPACE = "namespace";
-	String UIDVALIDITY = "uidvalidity";
-	String NAME = "name";
-}
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MessageTable.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MessageTable.java
deleted file mode 100644
index f58f5cb..0000000
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MessageTable.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * 
- * Copyright (C) 2013 Linagora
- *
- * This program is free software: you can redistribute it and/or 
- * modify it under the terms of the GNU Affero General Public License as 
- * published by the Free Software Foundation, either version 3 of the 
- * License, or (at your option) any later version, provided you comply 
- * with the Additional Terms applicable for OBM connector by Linagora 
- * pursuant to Section 7 of the GNU Affero General Public License, 
- * subsections (b), (c), and (e), pursuant to which you must notably (i) retain 
- * the “Message sent thanks to OBM, Free Communication by Linagora” 
- * signature notice appended to any and all outbound messages 
- * (notably e-mail and meeting requests), (ii) retain all hypertext links between 
- * OBM and obm.org, as well as between Linagora and linagora.com, and (iii) refrain 
- * from infringing Linagora intellectual property rights over its trademarks 
- * and commercial brands. Other Additional Terms apply, 
- * see <http://www.linagora.com/licenses/> for more details. 
- *
- * This program is distributed in the hope that it will be useful, 
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
- * for more details. 
- *
- * You should have received a copy of the GNU Affero General Public License 
- * and its applicable Additional Terms for OBM along with this program. If not, 
- * see <http://www.gnu.org/licenses/> for the GNU Affero General Public License version 3 
- * and <http://www.linagora.com/licenses/> for the Additional Terms applicable to 
- * OBM connectors. 
- * 
- * ***** END LICENSE BLOCK ***** */
-package org.apache.james.mailbox.cassandra.mail;
-
-public interface MessageTable {
-
-	String TABLE_NAME = "message";
-	String MAILBOX_ID = "mailboxId";
-	String IMAP_UID = "uid";
-	String INTERNAL_DATE = "internalDate";
-	String BODY_START_OCTET = "bodyStartOctet";
-	String CONTENT = "content";
-	String MOD_SEQ = "modSeq";
-	String MEDIA_TYPE = "mediaType";
-	String SUB_TYPE = "subType";
-	String FULL_CONTENT_OCTETS = "fullContentOctets";
-	String BODY_OCTECTS = "bodyOctets";
-	String TEXTUAL_LINE_COUNT = "textualLineCount";
-	String BODY_CONTENT = "bodyContent";
-	String HEADER_CONTENT = "headerContent";
-	
-	interface Flag {
-		String ANSWERED = "flagAnswered";
-		String DELETED = "flagDeleted";
-		String DRAFT = "flagDraft";
-		String RECENT = "flagRecent";
-		String SEEN = "flagSeen";
-		String FLAGGED = "flagFlagged";
-		String USER = "flagUser";
-		String[] ALL = {ANSWERED, DELETED, DRAFT, RECENT, SEEN, FLAGGED, USER};
-	}
-	
-	
-}
-- 
2.0.3


From 0eb935a76b55615bc06dad8ad438d981678f1544 Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 14:30:35 +0200
Subject: [PATCH 04/35] Created the new description table

---
 .../table/CassandraMailboxCountersTable.java       | 41 +++++++++++++
 .../cassandra/table/CassandraMailboxTable.java     | 44 ++++++++++++++
 .../cassandra/table/CassandraMessageTable.java     | 70 ++++++++++++++++++++++
 .../cassandra/table/CassandraMessageUidTable.java  | 39 ++++++++++++
 .../table/CassandraSubscriptionTable.java          | 10 ++++
 5 files changed, 204 insertions(+)
 create mode 100644 cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMailboxCountersTable.java
 create mode 100644 cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMailboxTable.java
 create mode 100644 cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageTable.java
 create mode 100644 cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageUidTable.java
 create mode 100644 cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraSubscriptionTable.java

diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMailboxCountersTable.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMailboxCountersTable.java
new file mode 100644
index 0000000..bb40fbf
--- /dev/null
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMailboxCountersTable.java
@@ -0,0 +1,41 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * 
+ * Copyright (C) 2013 Linagora
+ *
+ * This program is free software: you can redistribute it and/or 
+ * modify it under the terms of the GNU Affero General Public License as 
+ * published by the Free Software Foundation, either version 3 of the 
+ * License, or (at your option) any later version, provided you comply 
+ * with the Additional Terms applicable for OBM connector by Linagora 
+ * pursuant to Section 7 of the GNU Affero General Public License, 
+ * subsections (b), (c), and (e), pursuant to which you must notably (i) retain 
+ * the “Message sent thanks to OBM, Free Communication by Linagora” 
+ * signature notice appended to any and all outbound messages 
+ * (notably e-mail and meeting requests), (ii) retain all hypertext links between 
+ * OBM and obm.org, as well as between Linagora and linagora.com, and (iii) refrain 
+ * from infringing Linagora intellectual property rights over its trademarks 
+ * and commercial brands. Other Additional Terms apply, 
+ * see <http://www.linagora.com/licenses/> for more details. 
+ *
+ * This program is distributed in the hope that it will be useful, 
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
+ * for more details. 
+ *
+ * You should have received a copy of the GNU Affero General Public License 
+ * and its applicable Additional Terms for OBM along with this program. If not, 
+ * see <http://www.gnu.org/licenses/> for the GNU Affero General Public License version 3 
+ * and <http://www.linagora.com/licenses/> for the Additional Terms applicable to 
+ * OBM connectors. 
+ * 
+ * ***** END LICENSE BLOCK ***** */
+
+package org.apache.james.mailbox.cassandra.table;
+
+public interface CassandraMailboxCountersTable {
+    String TABLE_NAME = "mailboxCounters";
+    String MAILBOX_ID = "mailboxId";
+    String COUNT = "count";
+    String UNSEEN = "unseen";
+    String NEXT_MOD_SEQ = "nextModSeq";
+}
\ No newline at end of file
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMailboxTable.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMailboxTable.java
new file mode 100644
index 0000000..02b29b3
--- /dev/null
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMailboxTable.java
@@ -0,0 +1,44 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * 
+ * Copyright (C) 2013 Linagora
+ *
+ * This program is free software: you can redistribute it and/or 
+ * modify it under the terms of the GNU Affero General Public License as 
+ * published by the Free Software Foundation, either version 3 of the 
+ * License, or (at your option) any later version, provided you comply 
+ * with the Additional Terms applicable for OBM connector by Linagora 
+ * pursuant to Section 7 of the GNU Affero General Public License, 
+ * subsections (b), (c), and (e), pursuant to which you must notably (i) retain 
+ * the “Message sent thanks to OBM, Free Communication by Linagora” 
+ * signature notice appended to any and all outbound messages 
+ * (notably e-mail and meeting requests), (ii) retain all hypertext links between 
+ * OBM and obm.org, as well as between Linagora and linagora.com, and (iii) refrain 
+ * from infringing Linagora intellectual property rights over its trademarks 
+ * and commercial brands. Other Additional Terms apply, 
+ * see <http://www.linagora.com/licenses/> for more details. 
+ *
+ * This program is distributed in the hope that it will be useful, 
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
+ * for more details. 
+ *
+ * You should have received a copy of the GNU Affero General Public License 
+ * and its applicable Additional Terms for OBM along with this program. If not, 
+ * see <http://www.gnu.org/licenses/> for the GNU Affero General Public License version 3 
+ * and <http://www.linagora.com/licenses/> for the Additional Terms applicable to 
+ * OBM connectors. 
+ * 
+ * ***** END LICENSE BLOCK ***** */
+
+package org.apache.james.mailbox.cassandra.table;
+
+public interface CassandraMailboxTable {
+    String TABLE_NAME = "mailbox";
+    String ID = "id";
+    String USER = "user";
+    String PATH = "path";
+    String NAMESPACE = "namespace";
+    String UIDVALIDITY = "uidvalidity";
+    String NAME = "name";
+    String[] FIELDS = { ID, USER, NAMESPACE, UIDVALIDITY, NAME, PATH };
+}
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageTable.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageTable.java
new file mode 100644
index 0000000..78cc004
--- /dev/null
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageTable.java
@@ -0,0 +1,70 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * 
+ * Copyright (C) 2013 Linagora
+ *
+ * This program is free software: you can redistribute it and/or 
+ * modify it under the terms of the GNU Affero General Public License as 
+ * published by the Free Software Foundation, either version 3 of the 
+ * License, or (at your option) any later version, provided you comply 
+ * with the Additional Terms applicable for OBM connector by Linagora 
+ * pursuant to Section 7 of the GNU Affero General Public License, 
+ * subsections (b), (c), and (e), pursuant to which you must notably (i) retain 
+ * the “Message sent thanks to OBM, Free Communication by Linagora” 
+ * signature notice appended to any and all outbound messages 
+ * (notably e-mail and meeting requests), (ii) retain all hypertext links between 
+ * OBM and obm.org, as well as between Linagora and linagora.com, and (iii) refrain 
+ * from infringing Linagora intellectual property rights over its trademarks 
+ * and commercial brands. Other Additional Terms apply, 
+ * see <http://www.linagora.com/licenses/> for more details. 
+ *
+ * This program is distributed in the hope that it will be useful, 
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
+ * for more details. 
+ *
+ * You should have received a copy of the GNU Affero General Public License 
+ * and its applicable Additional Terms for OBM along with this program. If not, 
+ * see <http://www.gnu.org/licenses/> for the GNU Affero General Public License version 3 
+ * and <http://www.linagora.com/licenses/> for the Additional Terms applicable to 
+ * OBM connectors. 
+ * 
+ * ***** END LICENSE BLOCK ***** */
+
+package org.apache.james.mailbox.cassandra.table;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
+
+public interface CassandraMessageTable {
+
+    String TABLE_NAME = "message";
+    String MAILBOX_ID = "mailboxId";
+    String IMAP_UID = "uid";
+    String INTERNAL_DATE = "internalDate";
+    String BODY_START_OCTET = "bodyStartOctet";
+    String CONTENT = "content";
+    String MOD_SEQ = "modSeq";
+    String MEDIA_TYPE = "mediaType";
+    String SUB_TYPE = "subType";
+    String FULL_CONTENT_OCTETS = "fullContentOctets";
+    String BODY_OCTECTS = "bodyOctets";
+    String TEXTUAL_LINE_COUNT = "textualLineCount";
+    String BODY_CONTENT = "bodyContent";
+    String HEADER_CONTENT = "headerContent";
+    String[] FIELDS = { MAILBOX_ID, IMAP_UID, INTERNAL_DATE, MOD_SEQ, BODY_START_OCTET, MEDIA_TYPE, SUB_TYPE, FULL_CONTENT_OCTETS, BODY_OCTECTS, Flag.ANSWERED, Flag.DELETED, Flag.DRAFT, Flag.FLAGGED, Flag.RECENT, Flag.SEEN, Flag.USER, BODY_CONTENT, HEADER_CONTENT, TEXTUAL_LINE_COUNT };
+
+    interface Flag {
+        String ANSWERED = "flagAnswered";
+        String DELETED = "flagDeleted";
+        String DRAFT = "flagDraft";
+        String RECENT = "flagRecent";
+        String SEEN = "flagSeen";
+        String FLAGGED = "flagFlagged";
+        String USER = "flagUser";
+        String[] ALL = { ANSWERED, DELETED, DRAFT, RECENT, SEEN, FLAGGED, USER };
+
+        ImmutableMap<String, javax.mail.Flags.Flag> JAVAX_MAIL_FLAG = new Builder<String, javax.mail.Flags.Flag>().put(ANSWERED, javax.mail.Flags.Flag.ANSWERED).put(DELETED, javax.mail.Flags.Flag.DELETED).put(DRAFT, javax.mail.Flags.Flag.DRAFT).put(RECENT, javax.mail.Flags.Flag.RECENT)
+                .put(SEEN, javax.mail.Flags.Flag.SEEN).put(FLAGGED, javax.mail.Flags.Flag.FLAGGED).put(USER, javax.mail.Flags.Flag.USER).build();
+
+    }
+}
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageUidTable.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageUidTable.java
new file mode 100644
index 0000000..1563fd0
--- /dev/null
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageUidTable.java
@@ -0,0 +1,39 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * 
+ * Copyright (C) 2013 Linagora
+ *
+ * This program is free software: you can redistribute it and/or 
+ * modify it under the terms of the GNU Affero General Public License as 
+ * published by the Free Software Foundation, either version 3 of the 
+ * License, or (at your option) any later version, provided you comply 
+ * with the Additional Terms applicable for OBM connector by Linagora 
+ * pursuant to Section 7 of the GNU Affero General Public License, 
+ * subsections (b), (c), and (e), pursuant to which you must notably (i) retain 
+ * the “Message sent thanks to OBM, Free Communication by Linagora” 
+ * signature notice appended to any and all outbound messages 
+ * (notably e-mail and meeting requests), (ii) retain all hypertext links between 
+ * OBM and obm.org, as well as between Linagora and linagora.com, and (iii) refrain 
+ * from infringing Linagora intellectual property rights over its trademarks 
+ * and commercial brands. Other Additional Terms apply, 
+ * see <http://www.linagora.com/licenses/> for more details. 
+ *
+ * This program is distributed in the hope that it will be useful, 
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
+ * for more details. 
+ *
+ * You should have received a copy of the GNU Affero General Public License 
+ * and its applicable Additional Terms for OBM along with this program. If not, 
+ * see <http://www.gnu.org/licenses/> for the GNU Affero General Public License version 3 
+ * and <http://www.linagora.com/licenses/> for the Additional Terms applicable to 
+ * OBM connectors. 
+ * 
+ * ***** END LICENSE BLOCK ***** */
+
+package org.apache.james.mailbox.cassandra.table;
+
+public interface CassandraMessageUidTable {
+    String TABLE_NAME = "messageCounter";
+    String MAILBOX_ID = "mailboxId";
+    String NEXT_UID = "nextUid";
+}
\ No newline at end of file
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraSubscriptionTable.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraSubscriptionTable.java
new file mode 100644
index 0000000..4b7a7c4
--- /dev/null
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraSubscriptionTable.java
@@ -0,0 +1,10 @@
+package org.apache.james.mailbox.cassandra.table;
+
+public interface CassandraSubscriptionTable {
+
+    String TABLE_NAME = "subscription";
+    String USER = "user";
+    String MAILBOX = "mailbox";
+    String[] FIELDS = { MAILBOX, USER };
+
+}
-- 
2.0.3


From de8cf1744f795c7f02a29a2de9acc349d71f02e7 Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 14:31:29 +0200
Subject: [PATCH 05/35] Removed unused files in test/ressources

---
 cassandra/src/test/resources/logback.xml | 15 ------------
 cassandra/src/test/resources/mailbox.cql | 40 --------------------------------
 2 files changed, 55 deletions(-)
 delete mode 100644 cassandra/src/test/resources/logback.xml
 delete mode 100644 cassandra/src/test/resources/mailbox.cql

diff --git a/cassandra/src/test/resources/logback.xml b/cassandra/src/test/resources/logback.xml
deleted file mode 100644
index a50ae2f..0000000
--- a/cassandra/src/test/resources/logback.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<configuration debug="true">
-	<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-		<!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder 
-			by default -->
-		<encoder>
-			<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
-			</pattern>
-		</encoder>
-	</appender>
-
-
-	<root level="debug">
-		<appender-ref ref="STDOUT" />
-	</root>
-</configuration>
diff --git a/cassandra/src/test/resources/mailbox.cql b/cassandra/src/test/resources/mailbox.cql
deleted file mode 100644
index 25c0f7b..0000000
--- a/cassandra/src/test/resources/mailbox.cql
+++ /dev/null
@@ -1,40 +0,0 @@
-CREATE TABLE mailbox (
-	id UUID PRIMARY KEY,
-	name text, namespace text,
-	uidvalidity bigint,
-	user text,
-	path text
-);
-CREATE INDEX ON mailbox(path);
-
-CREATE TABLE mailboxCounters (
-	mailboxId UUID PRIMARY KEY,
-	count counter, 
-	unseen counter,
-	nextUid counter,
-	nextModSeq counter
-);
-
-CREATE TABLE message (
-	mailboxId UUID, 
-	uid bigint,
-	internalDate timestamp, 
-	bodyStartOctet int,
-	content blob,
-	modSeq bigint,
-	mediaType text,
-	subType text,
-	fullContentOctets int,
-	bodyOctets int,
-	textualLineCount int,
-	bodyContent blob,
-	headerContent blob,
-	flagAnswered boolean,
-	flagDeleted boolean,
-	flagDraft boolean,
-	flagRecent boolean,
-	flagSeen boolean,
-	flagFlagged boolean,
-	flagUser boolean,
-	PRIMARY KEY (mailboxId, uid)
-	);
-- 
2.0.3


From 50bcb5780a0015ba30602798d7537c582e94fbc7 Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 14:32:00 +0200
Subject: [PATCH 06/35] Update cassandra pom.xml

---
 cassandra/pom.xml | 96 ++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 60 insertions(+), 36 deletions(-)

diff --git a/cassandra/pom.xml b/cassandra/pom.xml
index f4e6428..5d81909 100644
--- a/cassandra/pom.xml
+++ b/cassandra/pom.xml
@@ -28,8 +28,8 @@
     </parent>
 
     <artifactId>apache-james-mailbox-cassandra</artifactId>
+    <description>Apache James Mailbox implementation over Cassandra</description>
     <name>Apache James :: Mailbox :: Cassandra</name>
-    <packaging>bundle</packaging>
 
     <dependencies>
         <dependency>
@@ -37,17 +37,13 @@
             <artifactId>${javax.mail.artifactId}</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.apache.james</groupId>
-            <artifactId>apache-james-mailbox-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.james</groupId>
-            <artifactId>apache-james-mailbox-store</artifactId>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
-            <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
@@ -55,41 +51,69 @@
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.apache.james</groupId>
+            <groupId>${project.groupId}</groupId>
             <artifactId>apache-james-mailbox-api</artifactId>
-            <scope>test</scope>
-            <type>test-jar</type>
         </dependency>
         <dependency>
-            <groupId>org.apache.james</groupId>
+            <groupId>${project.groupId}</groupId>
             <artifactId>apache-james-mailbox-store</artifactId>
-            <type>test-jar</type>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>apache-james-mailbox-api</artifactId>
             <scope>test</scope>
+            <type>test-jar</type>
         </dependency>
         <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
+	  <groupId>com.datastax.cassandra</groupId>
+	  <artifactId>cassandra-driver-core</artifactId>
+	  <version>${cassandra-driver-core.version}</version>
+	</dependency>
+	<dependency>
+    	    <groupId>org.cassandraunit</groupId>
+   	    <artifactId>cassandra-unit</artifactId>
+            <version>${cassandra-unit.version}</version>
         </dependency>
-                <dependency>
-			<groupId>org.cassandraunit</groupId>
-			<artifactId>cassandra-unit</artifactId>
-			<version>1.2.0.1</version>
-			<scope>test</scope>
-		</dependency>
-		<dependency>
-			<groupId>com.datastax.cassandra</groupId>
-			<artifactId>cassandra-driver-core</artifactId>
-			<version>1.0.0</version>
-		</dependency>
-		<dependency>
-			<groupId>javax.inject</groupId>
-			<artifactId>javax.inject</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>ch.qos.logback</groupId>
-			<artifactId>logback-classic</artifactId>
-			<version>1.0.13</version>
-			<scope>test</scope>
-		</dependency>
     </dependencies>
+
+    <profiles>
+        <profile>
+            <id>noTest</id>
+            <activation>
+                <os>
+                    <family>windows</family>
+                </os>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <configuration>
+                            <skipTests>true</skipTests>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <mainClass>fully.qualified.MainClass</mainClass>
+                         </manifest>
+                    </archive>
+                    <descriptorRefs>
+                        <descriptorRef>jar-with-dependencies</descriptorRef>
+                    </descriptorRefs>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
 </project>
-- 
2.0.3


From 9c67cd03aec5b035a8b1679e4050de6ee39c6ec2 Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 14:36:30 +0200
Subject: [PATCH 07/35] Removed Guice injection

---
 .../CassandraMailboxSessionMapperFactory.java      | 25 +++++++++-------------
 .../cassandra/mail/CassandraMailboxMapper.java     |  1 -
 .../cassandra/mail/CassandraMessageMapper.java     |  4 +---
 .../cassandra/mail/CassandraModSeqProvider.java    |  5 -----
 .../cassandra/mail/CassandraUidProvider.java       |  4 ----
 .../user/CassandraSubscriptionMapper.java          | 13 ++++++++---
 6 files changed, 21 insertions(+), 31 deletions(-)

diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
index 4c9a9d7..3fda712 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
@@ -16,13 +16,11 @@
  * specific language governing permissions and limitations      *
  * under the License.                                           *
  ****************************************************************/
+
 package org.apache.james.mailbox.cassandra;
 
 import java.util.UUID;
 
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.cassandra.mail.CassandraMailboxMapper;
 import org.apache.james.mailbox.cassandra.mail.CassandraMessageMapper;
@@ -33,21 +31,18 @@
 import org.apache.james.mailbox.store.mail.MessageMapper;
 import org.apache.james.mailbox.store.user.SubscriptionMapper;
 
-import com.google.common.annotations.VisibleForTesting;
+import com.datastax.driver.core.Session;
 
-@Singleton
+/**
+ * Cassandra implementation of {@link MailboxSessionMapperFactory}
+ * 
+ */
 public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFactory<UUID> {
 
-    private MailboxMapper<UUID> mailboxMapper;
-    private MessageMapper<UUID> messageMapper;
-    private SubscriptionMapper subscriptionMapper;
-
-    @Inject
-    @VisibleForTesting
-    CassandraMailboxSessionMapperFactory(CassandraMailboxMapper mailboxMapper, CassandraMessageMapper messageMapper, SubscriptionMapper subscriptionMapper) {
-        this.mailboxMapper = mailboxMapper;
-        this.messageMapper = messageMapper;
-        this.subscriptionMapper = subscriptionMapper;
+    public CassandraMailboxSessionMapperFactory(CassandraUidProvider uidProvider, ModSeqProvider<UUID> modSeqProvider, CassandraSession session) {
+        this.uidProvider = uidProvider;
+        this.modSeqProvider = modSeqProvider;
+        this.session = session;
     }
 
     @Override
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
index bcd60cc..051c0df 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
@@ -54,7 +54,6 @@
     private static final String[] FIELDS = { ID, USER, NAMESPACE, UIDVALIDITY, NAME, PATH };
     private Session session;
 
-    @Inject
     public CassandraMailboxMapper(Session session) {
         this.session = session;
     }
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
index 255a424..f7e2b7e 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
@@ -38,7 +38,6 @@
 import java.util.Map;
 import java.util.UUID;
 
-import javax.inject.Inject;
 import javax.mail.Flags;
 import javax.mail.Flags.Flag;
 import javax.mail.util.SharedByteArrayInputStream;
@@ -81,8 +80,7 @@
     private MailboxSession mailboxSession;
     private UidProvider<UUID> uidProvider;
 
-    @Inject
-    public CassandraMessageMapper(Session session, UidProvider<UUID> uidProvider, ModSeqProvider<UUID> modSeqProvider) {
+    public CassandraMessageMapper(Session session, CassandraUidProvider uidProvider, ModSeqProvider<UUID> modSeqProvider) {
         this.session = session;
         this.uidProvider = uidProvider;
         this.modSeqProvider = modSeqProvider;
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProvider.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProvider.java
index 034b391..02eb01b 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProvider.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProvider.java
@@ -26,9 +26,6 @@
 
 import java.util.UUID;
 
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.store.mail.ModSeqProvider;
@@ -37,12 +34,10 @@
 import com.datastax.driver.core.ResultSet;
 import com.datastax.driver.core.Session;
 
-@Singleton
 public class CassandraModSeqProvider implements ModSeqProvider<UUID> {
 
     private Session session;
 
-    @Inject
     public CassandraModSeqProvider(Session session) {
         this.session = session;
     }
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProvider.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProvider.java
index 93225cc..e804ea2 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProvider.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProvider.java
@@ -26,8 +26,6 @@
 
 import java.util.UUID;
 
-import javax.inject.Inject;
-
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.store.mail.UidProvider;
@@ -37,10 +35,8 @@
 import com.datastax.driver.core.Session;
 
 public class CassandraUidProvider implements UidProvider<UUID> {
-
     private Session session;
 
-    @Inject
     public CassandraUidProvider(Session session) {
         this.session = session;
     }
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java
index 4ca752e..f9ba663 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java
@@ -16,6 +16,7 @@
  * specific language governing permissions and limitations      *
  * under the License.                                           *
  ****************************************************************/
+
 package org.apache.james.mailbox.cassandra.user;
 
 import java.util.ArrayList;
@@ -24,14 +25,20 @@
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
-import javax.inject.Singleton;
+import java.util.List;
 
 import org.apache.james.mailbox.store.transaction.NonTransactionalMapper;
 import org.apache.james.mailbox.store.user.SubscriptionMapper;
 import org.apache.james.mailbox.store.user.model.Subscription;
 
-@Singleton
-public class CassandraSubscriptionMapper extends NonTransactionalMapper implements SubscriptionMapper {
+import com.datastax.driver.core.ResultSet;
+import com.datastax.driver.core.Row;
+import com.datastax.driver.core.Session;
+import com.datastax.driver.core.querybuilder.Insert;
+import com.datastax.driver.core.querybuilder.QueryBuilder;
+import com.datastax.driver.core.querybuilder.Select;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableList.Builder;
 
     private static final int INITIAL_SIZE = 64;
     private final Map<String, List<Subscription>> subscriptionsByUser;
-- 
2.0.3


From fa5012259f61bf05e969db7296d19105cd145ce7 Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 14:47:01 +0200
Subject: [PATCH 08/35] Update reference to our description table

---
 .../cassandra/mail/CassandraMailboxMapper.java     | 20 +++---
 .../cassandra/mail/CassandraMessageMapper.java     | 76 ++++++++++++++--------
 .../cassandra/mail/CassandraModSeqProvider.java    |  5 +-
 .../cassandra/mail/CassandraUidProvider.java       |  3 +
 .../user/CassandraSubscriptionMapper.java          | 12 ++--
 5 files changed, 72 insertions(+), 44 deletions(-)

diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
index 051c0df..041929f 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
@@ -16,24 +16,25 @@
  * specific language governing permissions and limitations      *
  * under the License.                                           *
  ****************************************************************/
+
 package org.apache.james.mailbox.cassandra.mail;
 
 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 static org.apache.james.mailbox.cassandra.mail.MailboxTable.ID;
-import static org.apache.james.mailbox.cassandra.mail.MailboxTable.TABLE_NAME;
-import static org.apache.james.mailbox.cassandra.mail.MailboxTable.NAME;
-import static org.apache.james.mailbox.cassandra.mail.MailboxTable.NAMESPACE;
-import static org.apache.james.mailbox.cassandra.mail.MailboxTable.PATH;
-import static org.apache.james.mailbox.cassandra.mail.MailboxTable.UIDVALIDITY;
-import static org.apache.james.mailbox.cassandra.mail.MailboxTable.USER;
+
+import static org.apache.james.mailbox.cassandra.table.CassandraMailboxTable.FIELDS;
+import static org.apache.james.mailbox.cassandra.table.CassandraMailboxTable.ID;
+import static org.apache.james.mailbox.cassandra.table.CassandraMailboxTable.NAME;
+import static org.apache.james.mailbox.cassandra.table.CassandraMailboxTable.NAMESPACE;
+import static org.apache.james.mailbox.cassandra.table.CassandraMailboxTable.PATH;
+import static org.apache.james.mailbox.cassandra.table.CassandraMailboxTable.TABLE_NAME;
+import static org.apache.james.mailbox.cassandra.table.CassandraMailboxTable.UIDVALIDITY;
+import static org.apache.james.mailbox.cassandra.table.CassandraMailboxTable.USER;
 
 import java.util.List;
 import java.util.UUID;
 
-import javax.inject.Inject;
-
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.exception.MailboxNotFoundException;
 import org.apache.james.mailbox.model.MailboxPath;
@@ -51,7 +52,6 @@
 
 public class CassandraMailboxMapper implements MailboxMapper<UUID> {
 
-    private static final String[] FIELDS = { ID, USER, NAMESPACE, UIDVALIDITY, NAME, PATH };
     private Session session;
 
     public CassandraMailboxMapper(Session session) {
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
index f7e2b7e..2745d42 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
@@ -29,6 +29,28 @@
 import static com.datastax.driver.core.querybuilder.QueryBuilder.lt;
 import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
 import static com.datastax.driver.core.querybuilder.QueryBuilder.update;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.BODY_CONTENT;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.BODY_OCTECTS;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.BODY_START_OCTET;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.FIELDS;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.FULL_CONTENT_OCTETS;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.HEADER_CONTENT;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.IMAP_UID;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.INTERNAL_DATE;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.MAILBOX_ID;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.MEDIA_TYPE;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.MOD_SEQ;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.SUB_TYPE;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.TABLE_NAME;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.TEXTUAL_LINE_COUNT;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.Flag.ANSWERED;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.Flag.DELETED;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.Flag.DRAFT;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.Flag.FLAGGED;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.Flag.JAVAX_MAIL_FLAG;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.Flag.RECENT;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.Flag.SEEN;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageTable.Flag.USER;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -43,6 +65,8 @@
 import javax.mail.util.SharedByteArrayInputStream;
 
 import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.cassandra.table.CassandraMailboxCountersTable;
+import org.apache.james.mailbox.cassandra.table.CassandraMessageTable;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.MessageMetaData;
 import org.apache.james.mailbox.model.MessageRange;
@@ -73,8 +97,6 @@
 
 public class CassandraMessageMapper implements MessageMapper<UUID> {
 
-    private static final String[] FIELDS = { MessageTable.MAILBOX_ID, MessageTable.IMAP_UID, MessageTable.INTERNAL_DATE, MessageTable.MOD_SEQ, MessageTable.BODY_START_OCTET, MessageTable.MEDIA_TYPE, MessageTable.SUB_TYPE, MessageTable.FULL_CONTENT_OCTETS, MessageTable.BODY_OCTECTS,
-            MessageTable.Flag.ANSWERED, MessageTable.Flag.DELETED, MessageTable.Flag.DRAFT, MessageTable.Flag.FLAGGED, MessageTable.Flag.RECENT, MessageTable.Flag.SEEN, MessageTable.Flag.USER, MessageTable.BODY_CONTENT, MessageTable.HEADER_CONTENT };
     private Session session;
     private ModSeqProvider<UUID> modSeqProvider;
     private MailboxSession mailboxSession;
@@ -98,11 +120,11 @@ public long countMessagesInMailbox(Mailbox<UUID> mailbox) throws MailboxExceptio
 
     @Override
     public long countUnseenMessagesInMailbox(Mailbox<UUID> mailbox) throws MailboxException {
-        ResultSet results = session.execute(select(MailboxCountersTable.COUNT).from(MailboxCountersTable.TABLE_NAME).where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
+        ResultSet results = session.execute(select(CassandraMailboxCountersTable.UNSEEN).from(CassandraMailboxCountersTable.TABLE_NAME).where(eq(CassandraMailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
         if (!results.isExhausted()) {
             Row row = results.one();
-            if (row.getColumnDefinitions().contains(MailboxCountersTable.UNSEEN)) {
-                return row.getLong(MailboxCountersTable.UNSEEN);
+            if (row.getColumnDefinitions().contains(CassandraMailboxCountersTable.UNSEEN)) {
+                return row.getLong(CassandraMailboxCountersTable.UNSEEN);
             }
         }
         return 0;
@@ -110,7 +132,7 @@ public long countUnseenMessagesInMailbox(Mailbox<UUID> mailbox) throws MailboxEx
 
     @Override
     public void delete(Mailbox<UUID> mailbox, Message<UUID> message) throws MailboxException {
-        session.execute(QueryBuilder.delete().from(MessageTable.TABLE_NAME).where(eq(MessageTable.MAILBOX_ID, mailbox.getMailboxId())).and(eq(MessageTable.IMAP_UID, message.getUid())));
+        session.execute(QueryBuilder.delete().from(TABLE_NAME).where(eq(MAILBOX_ID, mailbox.getMailboxId())).and(eq(IMAP_UID, message.getUid())));
         decrementCount(mailbox);
         if (!message.isSeen()) {
             decrementUnseen(mailbox);
@@ -118,23 +140,23 @@ public void delete(Mailbox<UUID> mailbox, Message<UUID> message) throws MailboxE
     }
 
     private void decrementCount(Mailbox<UUID> mailbox) {
-        updateMailbox(mailbox, decr(MailboxCountersTable.COUNT));
+        updateMailbox(mailbox, decr(CassandraMailboxCountersTable.COUNT));
     }
 
     private void incrementCount(Mailbox<UUID> mailbox) {
-        updateMailbox(mailbox, incr(MailboxCountersTable.COUNT));
+        updateMailbox(mailbox, incr(CassandraMailboxCountersTable.COUNT));
     }
 
     private void decrementUnseen(Mailbox<UUID> mailbox) {
-        updateMailbox(mailbox, decr(MailboxCountersTable.UNSEEN));
+        updateMailbox(mailbox, decr(CassandraMailboxCountersTable.UNSEEN));
     }
 
     private void incrementUnseen(Mailbox<UUID> mailbox) {
-        updateMailbox(mailbox, incr(MailboxCountersTable.UNSEEN));
+        updateMailbox(mailbox, incr(CassandraMailboxCountersTable.UNSEEN));
     }
 
     private void updateMailbox(Mailbox<UUID> mailbox, Assignment operation) {
-        session.execute(update(MailboxCountersTable.TABLE_NAME).with(operation).where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
+        session.execute(update(CassandraMailboxCountersTable.TABLE_NAME).with(operation).where(eq(CassandraMailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
     }
 
     @Override
@@ -148,9 +170,8 @@ private void updateMailbox(Mailbox<UUID> mailbox, Assignment operation) {
     }
 
     private Message<UUID> message(Row row) {
-        SimpleMessage<UUID> message = new SimpleMessage<UUID>(row.getDate(MessageTable.INTERNAL_DATE), row.getInt(MessageTable.FULL_CONTENT_OCTETS), row.getInt(MessageTable.BODY_START_OCTET), new SharedByteArrayInputStream(row.getBytes(MessageTable.BODY_CONTENT).array()), new Flags(),
-                new PropertyBuilder(), row.getUUID(MessageTable.MAILBOX_ID));
-        message.setUid(row.getLong(MessageTable.IMAP_UID));
+        SimpleMessage<UUID> message = new SimpleMessage<UUID>(row.getDate(INTERNAL_DATE), row.getInt(FULL_CONTENT_OCTETS), row.getInt(BODY_START_OCTET), new SharedByteArrayInputStream(getFullContent(row)), getFlags(row), getPropertyBuilder(row), row.getUUID(MAILBOX_ID));
+        message.setUid(row.getLong(IMAP_UID));
         return message;
     }
 
@@ -170,25 +191,25 @@ private Where buildQuery(Mailbox<UUID> mailbox, MessageRange set) {
     }
 
     private Where selectAll(Mailbox<UUID> mailbox) {
-        return select(FIELDS).from(MessageTable.TABLE_NAME).where(eq(MessageTable.MAILBOX_ID, mailbox.getMailboxId()));
+        return select(FIELDS).from(TABLE_NAME).where(eq(MAILBOX_ID, mailbox.getMailboxId()));
     }
 
     private Where selectFrom(Mailbox<UUID> mailbox, long uid) {
-        return select(FIELDS).from(MessageTable.TABLE_NAME).where(eq(MessageTable.MAILBOX_ID, mailbox.getMailboxId())).and(gt(MessageTable.IMAP_UID, uid));
+        return select(FIELDS).from(TABLE_NAME).where(eq(MAILBOX_ID, mailbox.getMailboxId())).and(gt(IMAP_UID, uid));
     }
 
     private Where selectRange(Mailbox<UUID> mailbox, long from, long to) {
-        return select(FIELDS).from(MessageTable.TABLE_NAME).where(eq(MessageTable.MAILBOX_ID, mailbox.getMailboxId())).and(gt(MessageTable.IMAP_UID, from)).and(lt(MessageTable.IMAP_UID, to));
+        return select(FIELDS).from(TABLE_NAME).where(eq(MAILBOX_ID, mailbox.getMailboxId())).and(gt(IMAP_UID, from)).and(lt(IMAP_UID, to));
     }
 
     private Where selectMessage(Mailbox<UUID> mailbox, long uid) {
-        return select(FIELDS).from(MessageTable.TABLE_NAME).where(eq(MessageTable.MAILBOX_ID, mailbox.getMailboxId())).and(eq(MessageTable.IMAP_UID, uid));
+        return select(FIELDS).from(TABLE_NAME).where(eq(MAILBOX_ID, mailbox.getMailboxId())).and(eq(IMAP_UID, uid));
     }
 
     @Override
     public List<Long> findRecentMessageUidsInMailbox(Mailbox<UUID> mailbox) throws MailboxException {
         ImmutableList.Builder<Long> result = ImmutableList.<Long> builder();
-        ResultSet rows = session.execute(selectAll(mailbox).orderBy(asc(MessageTable.IMAP_UID)));
+        ResultSet rows = session.execute(selectAll(mailbox).orderBy(asc(IMAP_UID)));
         for (Row row : rows) {
             Message<UUID> message = message(row);
             if (message.isRecent()) {
@@ -200,7 +221,7 @@ private Where selectMessage(Mailbox<UUID> mailbox, long uid) {
 
     @Override
     public Long findFirstUnseenMessageUid(Mailbox<UUID> mailbox) throws MailboxException {
-        ResultSet rows = session.execute(selectAll(mailbox).orderBy(asc(MessageTable.IMAP_UID)));
+        ResultSet rows = session.execute(selectAll(mailbox).orderBy(asc(IMAP_UID)));
         for (Row row : rows) {
             Message<UUID> message = message(row);
             if (!message.isSeen()) {
@@ -249,20 +270,19 @@ public MessageMetaData add(Mailbox<UUID> mailbox, Message<UUID> message) throws
         message.setUid(uidProvider.nextUid(mailboxSession, mailbox));
         message.setModSeq(modSeqProvider.nextModSeq(mailboxSession, mailbox));
         MessageMetaData messageMetaData = save(mailbox, message);
-        incrementUnseen(mailbox);
+        if (!message.isSeen()) {
+            incrementUnseen(mailbox);
+        }
         incrementCount(mailbox);
         return messageMetaData;
     }
 
     private MessageMetaData save(Mailbox<UUID> mailbox, Message<UUID> message) throws MailboxException {
         try {
-            Insert query = insertInto(MessageTable.TABLE_NAME).value(MessageTable.MAILBOX_ID, mailbox.getMailboxId()).value(MessageTable.IMAP_UID, message.getUid()).value(MessageTable.MOD_SEQ, message.getModSeq()).value(MessageTable.INTERNAL_DATE, message.getInternalDate())
-                    .value(MessageTable.MEDIA_TYPE, message.getMediaType()).value(MessageTable.SUB_TYPE, message.getSubType()).value(MessageTable.FULL_CONTENT_OCTETS, message.getFullContentOctets()).value(MessageTable.BODY_OCTECTS, message.getBodyOctets())
-                    .value(MessageTable.Flag.ANSWERED, message.isAnswered()).value(MessageTable.Flag.DELETED, message.isDeleted()).value(MessageTable.Flag.DRAFT, message.isDraft()).value(MessageTable.Flag.FLAGGED, message.isFlagged()).value(MessageTable.Flag.RECENT, message.isRecent())
-                    .value(MessageTable.Flag.SEEN, message.isSeen()).value(MessageTable.Flag.USER, message.createFlags().contains(Flag.USER)).value(MessageTable.BODY_CONTENT, bindMarker()).value(MessageTable.HEADER_CONTENT, bindMarker());
-            if (message.getTextualLineCount() != null) {
-                query.value(MessageTable.TEXTUAL_LINE_COUNT, message.getTextualLineCount());
-            }
+            Insert query = insertInto(TABLE_NAME).value(MAILBOX_ID, mailbox.getMailboxId()).value(IMAP_UID, message.getUid()).value(MOD_SEQ, message.getModSeq()).value(INTERNAL_DATE, message.getInternalDate()).value(MEDIA_TYPE, message.getMediaType())
+                    .value(BODY_START_OCTET, message.getFullContentOctets() - message.getBodyOctets()).value(SUB_TYPE, message.getSubType()).value(FULL_CONTENT_OCTETS, message.getFullContentOctets()).value(BODY_OCTECTS, message.getBodyOctets()).value(ANSWERED, message.isAnswered())
+                    .value(DELETED, message.isDeleted()).value(DRAFT, message.isDraft()).value(FLAGGED, message.isFlagged()).value(RECENT, message.isRecent()).value(SEEN, message.isSeen()).value(USER, message.createFlags().contains(Flag.USER)).value(BODY_CONTENT, bindMarker())
+                    .value(HEADER_CONTENT, bindMarker()).value(TEXTUAL_LINE_COUNT, message.getTextualLineCount());
             PreparedStatement preparedStatement = session.prepare(query.toString());
             BoundStatement boundStatement = preparedStatement.bind(toByteBuffer(message.getBodyContent()), toByteBuffer(message.getHeaderContent()));
             session.execute(boundStatement);
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProvider.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProvider.java
index 02eb01b..de20cc4 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProvider.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProvider.java
@@ -23,6 +23,9 @@
 import static com.datastax.driver.core.querybuilder.QueryBuilder.incr;
 import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
 import static com.datastax.driver.core.querybuilder.QueryBuilder.update;
+import static org.apache.james.mailbox.cassandra.table.CassandraMailboxCountersTable.MAILBOX_ID;
+import static org.apache.james.mailbox.cassandra.table.CassandraMailboxCountersTable.NEXT_MOD_SEQ;
+import static org.apache.james.mailbox.cassandra.table.CassandraMailboxCountersTable.TABLE_NAME;
 
 import java.util.UUID;
 
@@ -44,7 +47,7 @@ public CassandraModSeqProvider(Session session) {
 
     @Override
     public long nextModSeq(MailboxSession mailboxSession, Mailbox<UUID> mailbox) throws MailboxException {
-        session.execute(update(MailboxCountersTable.TABLE_NAME).with(incr(MailboxCountersTable.NEXT_MOD_SEQ)).where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
+        session.execute(update(TABLE_NAME).with(incr(NEXT_MOD_SEQ)).where(eq(MAILBOX_ID, mailbox.getMailboxId())));
         return highestModSeq(mailboxSession, mailbox);
     }
 
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProvider.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProvider.java
index e804ea2..0143d32 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProvider.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProvider.java
@@ -23,6 +23,9 @@
 import static com.datastax.driver.core.querybuilder.QueryBuilder.incr;
 import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
 import static com.datastax.driver.core.querybuilder.QueryBuilder.update;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageUidTable.MAILBOX_ID;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageUidTable.NEXT_UID;
+import static org.apache.james.mailbox.cassandra.table.CassandraMessageUidTable.TABLE_NAME;
 
 import java.util.UUID;
 
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java
index f9ba663..6aba5f2 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java
@@ -19,11 +19,13 @@
 
 package org.apache.james.mailbox.cassandra.user;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
+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 static org.apache.james.mailbox.cassandra.table.CassandraSubscriptionTable.FIELDS;
+import static org.apache.james.mailbox.cassandra.table.CassandraSubscriptionTable.MAILBOX;
+import static org.apache.james.mailbox.cassandra.table.CassandraSubscriptionTable.TABLE_NAME;
+import static org.apache.james.mailbox.cassandra.table.CassandraSubscriptionTable.USER;
 
 import java.util.List;
 
-- 
2.0.3


From 92dff1dd539e6a160941ab9da36b47c78acf2ec5 Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 14:49:44 +0200
Subject: [PATCH 09/35] Create CassandraSession, an implemention of Datastax
 Session

---
 .../james/mailbox/cassandra/CassandraSession.java  | 162 +++++++++++++++++++++
 1 file changed, 162 insertions(+)
 create mode 100644 cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraSession.java

diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraSession.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraSession.java
new file mode 100644
index 0000000..795e063
--- /dev/null
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraSession.java
@@ -0,0 +1,162 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * 
+ * Copyright (C) 2013 Linagora
+ *
+ * This program is free software: you can redistribute it and/or 
+ * modify it under the terms of the GNU Affero General Public License as 
+ * published by the Free Software Foundation, either version 3 of the 
+ * License, or (at your option) any later version, provided you comply 
+ * with the Additional Terms applicable for OBM connector by Linagora 
+ * pursuant to Section 7 of the GNU Affero General Public License, 
+ * subsections (b), (c), and (e), pursuant to which you must notably (i) retain 
+ * the “Message sent thanks to OBM, Free Communication by Linagora” 
+ * signature notice appended to any and all outbound messages 
+ * (notably e-mail and meeting requests), (ii) retain all hypertext links between 
+ * OBM and obm.org, as well as between Linagora and linagora.com, and (iii) refrain 
+ * from infringing Linagora intellectual property rights over its trademarks 
+ * and commercial brands. Other Additional Terms apply, 
+ * see <http://www.linagora.com/licenses/> for more details. 
+ *
+ * This program is distributed in the hope that it will be useful, 
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
+ * for more details. 
+ *
+ * You should have received a copy of the GNU Affero General Public License 
+ * and its applicable Additional Terms for OBM along with this program. If not, 
+ * see <http://www.gnu.org/licenses/> for the GNU Affero General Public License version 3 
+ * and <http://www.linagora.com/licenses/> for the Additional Terms applicable to 
+ * OBM connectors. 
+ * 
+ * ***** END LICENSE BLOCK ***** */
+
+package org.apache.james.mailbox.cassandra;
+
+import com.datastax.driver.core.CloseFuture;
+import com.datastax.driver.core.Cluster;
+import com.datastax.driver.core.PreparedStatement;
+import com.datastax.driver.core.RegularStatement;
+import com.datastax.driver.core.ResultSet;
+import com.datastax.driver.core.ResultSetFuture;
+import com.datastax.driver.core.Session;
+import com.datastax.driver.core.Statement;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * A Cassandra session with the default keyspace
+ * 
+ */
+public class CassandraSession implements Session {
+    private final static String DEFAULT_CLUSTER_IP = "localhost";
+    private final static int DEFAULT_CLUSTER_PORT = 9042;
+    private final static String DEFAULT_KEYSPACE_NAME = "apache_james";
+    private final static int DEFAULT_REPLICATION_FACTOR = 1;
+
+    private Session session;
+
+    public CassandraSession(String ip, int port, String keyspace, int replicationFactor) {
+        Cluster cluster = Cluster.builder().addContactPoint(ip).withPort(port).build();
+        if (cluster.getMetadata().getKeyspace(keyspace) == null) {
+            initDatabase(cluster, keyspace, replicationFactor);
+        }
+        session = cluster.connect(keyspace);
+    }
+
+    private void initDatabase(Cluster cluster, String keyspace, int replicationFactor) {
+        session = cluster.connect();
+        session.execute("CREATE KEYSPACE IF NOT EXISTS " + keyspace + " WITH replication " + "= {'class':'SimpleStrategy', 'replication_factor':" + replicationFactor + "};");
+        session.execute("CREATE TABLE IF NOT EXISTS " + keyspace + ".mailbox (" + "id uuid PRIMARY KEY," + "name text, namespace text," + "uidvalidity bigint," + "user text," + "path text" + ");");
+        session.execute("CREATE INDEX IF NOT EXISTS ON " + keyspace + ".mailbox(path);");
+        session.execute("CREATE TABLE IF NOT EXISTS " + keyspace + ".messageCounter (" + "mailboxId UUID PRIMARY KEY," + "nextUid bigint," + ");");
+        session.execute("CREATE TABLE IF NOT EXISTS " + keyspace + ".mailboxCounters (" + "mailboxId UUID PRIMARY KEY," + "count counter," + "unseen counter," + "nextModSeq counter" + ");");
+        session.execute("CREATE TABLE IF NOT EXISTS " + keyspace + ".message (" + "mailboxId UUID," + "uid bigint," + "internalDate timestamp," + "bodyStartOctet int," + "content blob," + "modSeq bigint," + "mediaType text," + "subType text," + "fullContentOctets int," + "bodyOctets int,"
+                + "textualLineCount bigint," + "bodyContent blob," + "headerContent blob," + "flagAnswered boolean," + "flagDeleted boolean," + "flagDraft boolean," + "flagRecent boolean," + "flagSeen boolean," + "flagFlagged boolean," + "flagUser boolean," + "PRIMARY KEY (mailboxId, uid)" + ");");
+        session.execute("CREATE TABLE IF NOT EXISTS " + keyspace + ".subscription (" + "user text," + "mailbox text," + "PRIMARY KEY (mailbox, user)" + ");");
+        session.close();
+    }
+
+    public CassandraSession() {
+        this(DEFAULT_CLUSTER_IP, DEFAULT_CLUSTER_PORT, DEFAULT_KEYSPACE_NAME, DEFAULT_REPLICATION_FACTOR);
+    }
+
+    @Override
+    public String getLoggedKeyspace() {
+        return session.getLoggedKeyspace();
+    }
+
+    @Override
+    public Session init() {
+        return session.init();
+    }
+
+    @Override
+    public ResultSet execute(String query) {
+        return session.execute(query);
+    }
+
+    @Override
+    public ResultSet execute(String query, Object... values) {
+        return session.execute(query, values);
+    }
+
+    @Override
+    public ResultSet execute(Statement statement) {
+        return session.execute(statement);
+    }
+
+    @Override
+    public ResultSetFuture executeAsync(String query) {
+        return session.executeAsync(query);
+    }
+
+    @Override
+    public ResultSetFuture executeAsync(String query, Object... values) {
+        return session.executeAsync(query, values);
+    }
+
+    @Override
+    public ResultSetFuture executeAsync(Statement statement) {
+        return session.executeAsync(statement);
+    }
+
+    @Override
+    public PreparedStatement prepare(String query) {
+        return session.prepare(query);
+    }
+
+    @Override
+    public PreparedStatement prepare(RegularStatement statement) {
+        return session.prepare(statement);
+    }
+
+    @Override
+    public ListenableFuture<PreparedStatement> prepareAsync(String query) {
+        return session.prepareAsync(query);
+    }
+
+    @Override
+    public ListenableFuture<PreparedStatement> prepareAsync(RegularStatement statement) {
+        return session.prepareAsync(statement);
+    }
+
+    @Override
+    public CloseFuture closeAsync() {
+        return session.closeAsync();
+    }
+
+    @Override
+    public void close() {
+        session.close();
+    }
+
+    @Override
+    public boolean isClosed() {
+        return session.isClosed();
+    }
+
+    @Override
+    public Cluster getCluster() {
+        return session.getCluster();
+    }
+
+}
-- 
2.0.3


From d5e77c7cc2f9af86746f946ec3a39c0a3ae3041f Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 14:50:13 +0200
Subject: [PATCH 10/35] Used CassandraSession in
 CassandraMailboxSessionMapperFactory

---
 .../CassandraMailboxSessionMapperFactory.java      | 29 +++++++++++++++-------
 1 file changed, 20 insertions(+), 9 deletions(-)

diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
index 3fda712..c736ab0 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
@@ -24,11 +24,12 @@
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.cassandra.mail.CassandraMailboxMapper;
 import org.apache.james.mailbox.cassandra.mail.CassandraMessageMapper;
-import org.apache.james.mailbox.exception.MailboxException;
-import org.apache.james.mailbox.exception.SubscriptionException;
+import org.apache.james.mailbox.cassandra.mail.CassandraUidProvider;
+import org.apache.james.mailbox.cassandra.user.CassandraSubscriptionMapper;
 import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
 import org.apache.james.mailbox.store.mail.MailboxMapper;
-import org.apache.james.mailbox.store.mail.MessageMapper;
+import org.apache.james.mailbox.store.mail.ModSeqProvider;
+import org.apache.james.mailbox.store.mail.UidProvider;
 import org.apache.james.mailbox.store.user.SubscriptionMapper;
 
 import com.datastax.driver.core.Session;
@@ -38,6 +39,9 @@
  * 
  */
 public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFactory<UUID> {
+    private Session session;
+    private CassandraUidProvider uidProvider;
+    private ModSeqProvider<UUID> modSeqProvider;
 
     public CassandraMailboxSessionMapperFactory(CassandraUidProvider uidProvider, ModSeqProvider<UUID> modSeqProvider, CassandraSession session) {
         this.uidProvider = uidProvider;
@@ -46,18 +50,25 @@ public CassandraMailboxSessionMapperFactory(CassandraUidProvider uidProvider, Mo
     }
 
     @Override
-    public MailboxMapper<UUID> createMailboxMapper(MailboxSession session) throws MailboxException {
-        return mailboxMapper;
+    public CassandraMessageMapper createMessageMapper(MailboxSession mailboxSession) {
+        return new CassandraMessageMapper(session, uidProvider, modSeqProvider);
     }
 
     @Override
-    public MessageMapper<UUID> createMessageMapper(MailboxSession session) throws MailboxException {
-        return messageMapper;
+    public MailboxMapper<UUID> createMailboxMapper(MailboxSession mailboxSession) {
+        return new CassandraMailboxMapper(session);
     }
 
     @Override
-    public SubscriptionMapper createSubscriptionMapper(MailboxSession session) throws SubscriptionException {
-        return subscriptionMapper;
+    public SubscriptionMapper createSubscriptionMapper(MailboxSession mailboxSession) {
+        return new CassandraSubscriptionMapper(session);
     }
 
+    public ModSeqProvider<UUID> getModSeqProvider() {
+        return modSeqProvider;
+    }
+
+    public UidProvider<UUID> getUidProvider() {
+        return uidProvider;
+    }
 }
-- 
2.0.3


From 6219fd922270825275882b7220a865a0db0640e4 Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 14:52:11 +0200
Subject: [PATCH 11/35] Add comments

---
 .../apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java    | 3 +++
 .../apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java    | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
index 041929f..fcd6a1f 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
@@ -50,6 +50,9 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableList.Builder;
 
+/**
+ * Data access management for mailbox.
+ */
 public class CassandraMailboxMapper implements MailboxMapper<UUID> {
 
     private Session session;
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
index 2745d42..6a79f4a 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
@@ -95,6 +95,9 @@
 import com.google.common.collect.ImmutableSortedSet.Builder;
 import com.google.common.io.ByteStreams;
 
+/**
+ * Cassandra implementation of a {@link MessageMapper}.
+ */
 public class CassandraMessageMapper implements MessageMapper<UUID> {
 
     private Session session;
-- 
2.0.3


From 1de53a679e9a03cd6d9efe609fa32b08696b88f3 Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 14:54:46 +0200
Subject: [PATCH 12/35] Rewrite the find methods of CassandraMailboxMapper

---
 .../mailbox/cassandra/mail/CassandraMailboxMapper.java   | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
index fcd6a1f..44a2574 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
@@ -84,10 +84,11 @@ public void delete(Mailbox<UUID> mailbox) throws MailboxException {
 
     @Override
     public List<Mailbox<UUID>> findMailboxWithPathLike(MailboxPath path) throws MailboxException {
-        final String regex = path.getName().replace("%", ".*");
+        final String regexWithUser = ".*" + path.getNamespace() + ".*" + path.getUser() + ".*" + path.getName() + ".*";
+        final String regexWithoutUser = ".*" + path.getNamespace() + ".*null.*" + path.getName() + ".*";
         Builder<Mailbox<UUID>> result = ImmutableList.<Mailbox<UUID>> builder();
         for (Row row : session.execute(select(FIELDS).from(TABLE_NAME))) {
-            if (row.getString(PATH).matches(regex)) {
+            if (row.getString(PATH).matches(regexWithUser) || row.getString(PATH).matches(regexWithoutUser)) {
                 result.add(mailbox(row));
             }
         }
@@ -120,8 +121,15 @@ public void endRequest() {
     }
 
     @Override
-    public boolean hasChildren(Mailbox<UUID> mailbox, char delimiter) throws MailboxException, MailboxNotFoundException {
-        return !findMailboxWithPathLike(new MailboxPath(mailbox.getNamespace(), mailbox.getUser(), mailbox.getName() + delimiter + "%")).isEmpty();
+    public boolean hasChildren(Mailbox<UUID> mailbox, char delimiter) {
+        final String regexWithUser = ".*" + mailbox.getNamespace() + ".*" + mailbox.getUser() + ".*" + mailbox.getName() + delimiter + ".*";
+        final String regexWithoutUser = ".*" + mailbox.getNamespace() + ".*null.*" + mailbox.getName() + delimiter + ".*";
+        for (Row row : session.execute(select(PATH).from(TABLE_NAME))) {
+            if (row.getString(PATH).matches(regexWithUser) || row.getString(PATH).matches(regexWithoutUser)) {
+                return true;
+            }
+        }
+        return false;
     }
 
     @Override
-- 
2.0.3


From 0ff617eff52c798005d4833155128d02c08c8d78 Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 14:55:34 +0200
Subject: [PATCH 13/35] Better condition in the save method of
 CassandraMailboxMapper

---
 .../apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
index 44a2574..8b5f018 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
@@ -99,10 +99,8 @@ public void delete(Mailbox<UUID> mailbox) throws MailboxException {
     public void save(Mailbox<UUID> mailbox) throws MailboxException {
         Preconditions.checkArgument(mailbox instanceof SimpleMailbox<?>);
         SimpleMailbox<UUID> simpleMailbox = (SimpleMailbox<UUID>) mailbox;
-        UUID id = simpleMailbox.getMailboxId();
-        if (id == null) {
-            id = UUID.randomUUID();
-            simpleMailbox.setMailboxId(id);
+        if (simpleMailbox.getMailboxId() == null) {
+            simpleMailbox.setMailboxId(UUID.randomUUID());
         }
         upsertMailbox(simpleMailbox);
     }
-- 
2.0.3


From 0bd00c25358160fc2d0116536270202d78dd7c43 Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 14:58:49 +0200
Subject: [PATCH 14/35] Add private methods to build message for an specific
 row

---
 .../cassandra/mail/CassandraMessageMapper.java     | 27 ++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
index 6a79f4a..3283a9d 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
@@ -94,6 +94,7 @@
 import com.google.common.collect.ImmutableSortedSet;
 import com.google.common.collect.ImmutableSortedSet.Builder;
 import com.google.common.io.ByteStreams;
+import com.google.common.primitives.Bytes;
 
 /**
  * Cassandra implementation of a {@link MessageMapper}.
@@ -172,6 +173,32 @@ private void updateMailbox(Mailbox<UUID> mailbox, Assignment operation) {
         return result.build().iterator();
     }
 
+    private byte[] getFullContent(Row row) {
+        byte[] headerContent = new byte[row.getBytes(HEADER_CONTENT).remaining()];
+        byte[] bodyContent = new byte[row.getBytes(BODY_CONTENT).remaining()];
+        row.getBytes(HEADER_CONTENT).get(headerContent);
+        row.getBytes(BODY_CONTENT).get(bodyContent);
+        return Bytes.concat(headerContent, bodyContent);
+    }
+
+    private Flags getFlags(Row row) {
+        Flags flags = new Flags();
+        for (String flag : CassandraMessageTable.Flag.ALL) {
+            if (row.getBool(flag)) {
+                flags.add(JAVAX_MAIL_FLAG.get(flag));
+            }
+        }
+        return flags;
+    }
+
+    private PropertyBuilder getPropertyBuilder(Row row) {
+        PropertyBuilder property = new PropertyBuilder();
+        property.setSubType(row.getString(SUB_TYPE));
+        property.setMediaType(row.getString(MEDIA_TYPE));
+        property.setTextualLineCount(row.getLong(TEXTUAL_LINE_COUNT));
+        return property;
+    }
+
     private Message<UUID> message(Row row) {
         SimpleMessage<UUID> message = new SimpleMessage<UUID>(row.getDate(INTERNAL_DATE), row.getInt(FULL_CONTENT_OCTETS), row.getInt(BODY_START_OCTET), new SharedByteArrayInputStream(getFullContent(row)), getFlags(row), getPropertyBuilder(row), row.getUUID(MAILBOX_ID));
         message.setUid(row.getLong(IMAP_UID));
-- 
2.0.3


From 36418aab57d20f40a420f28287cfdba79741bc8c Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 14:59:23 +0200
Subject: [PATCH 15/35] Add a new constructor for CassandraMessageMapper

---
 .../apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java  | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
index 3283a9d..61df1f3 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
@@ -112,6 +112,11 @@ public CassandraMessageMapper(Session session, CassandraUidProvider uidProvider,
         this.modSeqProvider = modSeqProvider;
     }
 
+    public CassandraMessageMapper(Session session, CassandraUidProvider uidProvider, CassandraModSeqProvider modSeqProvider, MailboxSession mailboxSession) {
+        this(session, uidProvider, modSeqProvider);
+        this.mailboxSession = mailboxSession;
+    }
+
     @Override
     public long countMessagesInMailbox(Mailbox<UUID> mailbox) throws MailboxException {
         ResultSet results = session.execute(select(MailboxCountersTable.COUNT).from(MailboxCountersTable.TABLE_NAME).where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
-- 
2.0.3


From 2ba56b70bee7e8650a1aa68734c59ee83ec38787 Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 15:08:13 +0200
Subject: [PATCH 16/35] Used ternaire operator in return statement

---
 .../james/mailbox/cassandra/mail/CassandraMessageMapper.java      | 8 ++------
 .../james/mailbox/cassandra/mail/CassandraModSeqProvider.java     | 8 ++------
 .../apache/james/mailbox/cassandra/mail/CassandraUidProvider.java | 8 ++------
 3 files changed, 6 insertions(+), 18 deletions(-)

diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
index 61df1f3..48f06d8 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
@@ -119,12 +119,8 @@ public CassandraMessageMapper(Session session, CassandraUidProvider uidProvider,
 
     @Override
     public long countMessagesInMailbox(Mailbox<UUID> mailbox) throws MailboxException {
-        ResultSet results = session.execute(select(MailboxCountersTable.COUNT).from(MailboxCountersTable.TABLE_NAME).where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
-        if (results.isExhausted()) {
-            return 0;
-        } else {
-            return results.one().getLong(MailboxCountersTable.COUNT);
-        }
+        ResultSet results = session.execute(select(CassandraMailboxCountersTable.COUNT).from(CassandraMailboxCountersTable.TABLE_NAME).where(eq(CassandraMailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
+        return results.isExhausted() ? 0 : results.one().getLong(CassandraMailboxCountersTable.COUNT);
     }
 
     @Override
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProvider.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProvider.java
index de20cc4..118d7dc 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProvider.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProvider.java
@@ -53,11 +53,7 @@ public long nextModSeq(MailboxSession mailboxSession, Mailbox<UUID> mailbox) thr
 
     @Override
     public long highestModSeq(MailboxSession mailboxSession, Mailbox<UUID> mailbox) throws MailboxException {
-        ResultSet result = session.execute(select(MailboxCountersTable.NEXT_MOD_SEQ).from(MailboxCountersTable.TABLE_NAME).where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
-        if (result.isExhausted()) {
-            return 0;
-        } else {
-            return result.one().getLong(MailboxCountersTable.NEXT_MOD_SEQ);
-        }
+        ResultSet result = session.execute(select(NEXT_MOD_SEQ).from(TABLE_NAME).where(eq(MAILBOX_ID, mailbox.getMailboxId())));
+        return result.isExhausted() ? 0 : result.one().getLong(NEXT_MOD_SEQ);
     }
 }
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProvider.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProvider.java
index 0143d32..0ee9b71 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProvider.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProvider.java
@@ -52,12 +52,8 @@ public long nextUid(MailboxSession mailboxSession, Mailbox<UUID> mailbox) throws
 
     @Override
     public long lastUid(MailboxSession mailboxSession, Mailbox<UUID> mailbox) throws MailboxException {
-        ResultSet result = session.execute(select(MailboxCountersTable.NEXT_UID).from(MailboxCountersTable.TABLE_NAME).where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
-        if (result.isExhausted()) {
-            return 0;
-        } else {
-            return result.one().getLong(MailboxCountersTable.NEXT_UID);
-        }
+        ResultSet result = session.execute(select(NEXT_UID).from(TABLE_NAME).where(eq(MAILBOX_ID, mailbox.getMailboxId())));
+        return result.isExhausted() ? 0 : result.one().getLong(NEXT_UID);
     }
 
 }
-- 
2.0.3


From ed082718d7161401217abf8818af3cbdcb736d14 Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 15:10:18 +0200
Subject: [PATCH 17/35] Used method on row to don't build ans unused message

---
 .../mailbox/cassandra/mail/CassandraMessageMapper.java     | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
index 48f06d8..d54352f 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
@@ -242,9 +242,8 @@ private Where selectMessage(Mailbox<UUID> mailbox, long uid) {
         ImmutableList.Builder<Long> result = ImmutableList.<Long> builder();
         ResultSet rows = session.execute(selectAll(mailbox).orderBy(asc(IMAP_UID)));
         for (Row row : rows) {
-            Message<UUID> message = message(row);
-            if (message.isRecent()) {
-                result.add(message.getUid());
+            if (row.getBool(RECENT)) {
+                result.add(row.getLong(IMAP_UID));
             }
         }
         return result.build();
@@ -254,9 +253,8 @@ private Where selectMessage(Mailbox<UUID> mailbox, long uid) {
     public Long findFirstUnseenMessageUid(Mailbox<UUID> mailbox) throws MailboxException {
         ResultSet rows = session.execute(selectAll(mailbox).orderBy(asc(IMAP_UID)));
         for (Row row : rows) {
-            Message<UUID> message = message(row);
-            if (!message.isSeen()) {
-                return message.getUid();
+            if (!row.getBool(SEEN)) {
+                return row.getLong(IMAP_UID);
             }
         }
         return null;
@@ -267,8 +265,8 @@ public Long findFirstUnseenMessageUid(Mailbox<UUID> mailbox) throws MailboxExcep
         ImmutableMap.Builder<Long, MessageMetaData> deletedMessages = ImmutableMap.builder();
         ResultSet messages = session.execute(buildQuery(mailbox, set));
         for (Row row : messages) {
-            Message<UUID> message = message(row);
-            if (message.isDeleted()) {
+            if (row.getBool(DELETED)) {
+                Message<UUID> message = message(row);
                 delete(mailbox, message);
                 deletedMessages.put(message.getUid(), new SimpleMessageMetaData(message));
             }
-- 
2.0.3


From 7f0aa6401d92ca57decf88d05622efd8f681d964 Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 15:11:34 +0200
Subject: [PATCH 18/35] Use foreach on the query in CassandraMessageMapper

---
 .../apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java    | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
index d54352f..3a1de08 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
@@ -328,8 +328,7 @@ private ByteBuffer toByteBuffer(InputStream stream) throws IOException {
     @Override
     public Iterator<UpdatedFlags> updateFlags(Mailbox<UUID> mailbox, Flags flags, boolean value, boolean replace, MessageRange set) throws MailboxException {
         ImmutableList.Builder<UpdatedFlags> result = ImmutableList.builder();
-        ResultSet messages = session.execute(buildQuery(mailbox, set));
-        for (Row row : messages) {
+        for (Row row : session.execute(buildQuery(mailbox, set))) {
             Message<UUID> message = message(row);
             Flags originFlags = message.createFlags();
             Flags updatedFlags = buildFlags(message, flags, value, replace);
-- 
2.0.3


From 027cc10982a9aca7d72ef4e7b05f46c9adbabefa Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 15:12:30 +0200
Subject: [PATCH 19/35] Rewrite method nextUid of CassandraUidProvider

---
 .../mailbox/cassandra/mail/CassandraUidProvider.java     | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProvider.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProvider.java
index 0ee9b71..2f2574d 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProvider.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProvider.java
@@ -20,8 +20,8 @@
 package org.apache.james.mailbox.cassandra.mail;
 
 import static com.datastax.driver.core.querybuilder.QueryBuilder.eq;
-import static com.datastax.driver.core.querybuilder.QueryBuilder.incr;
 import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.set;
 import static com.datastax.driver.core.querybuilder.QueryBuilder.update;
 import static org.apache.james.mailbox.cassandra.table.CassandraMessageUidTable.MAILBOX_ID;
 import static org.apache.james.mailbox.cassandra.table.CassandraMessageUidTable.NEXT_UID;
@@ -39,6 +39,7 @@
 
 public class CassandraUidProvider implements UidProvider<UUID> {
     private Session session;
+    private final int applied = 0;
 
     public CassandraUidProvider(Session session) {
         this.session = session;
@@ -46,8 +47,17 @@ public CassandraUidProvider(Session session) {
 
     @Override
     public long nextUid(MailboxSession mailboxSession, Mailbox<UUID> mailbox) throws MailboxException {
-        session.execute(update(MailboxCountersTable.TABLE_NAME).with(incr(MailboxCountersTable.NEXT_UID)).where(eq(MailboxCountersTable.MAILBOX_ID, mailbox.getMailboxId())));
-        return lastUid(mailboxSession, mailbox);
+        ResultSet resultat = null;
+        long lastUid = lastUid(mailboxSession, mailbox);
+        if (lastUid == 0) {
+            resultat = session.execute(update(TABLE_NAME).with(set(NEXT_UID, ++lastUid)).where(eq(MAILBOX_ID, mailbox.getMailboxId())));
+        } else {
+            do {
+                lastUid = lastUid(mailboxSession, mailbox);
+                resultat = session.execute(update(TABLE_NAME).onlyIf(eq(NEXT_UID, lastUid)).with(set(NEXT_UID, ++lastUid)).where(eq(MAILBOX_ID, mailbox.getMailboxId())));
+            } while (!resultat.one().getBool(applied));
+        }
+        return lastUid;
     }
 
     @Override
-- 
2.0.3


From bc19fccb5153924a7fa46a55932213ee8e51926b Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 15:18:18 +0200
Subject: [PATCH 20/35] New constructor of CassandraSubscriptionMapper

---
 .../james/mailbox/cassandra/user/CassandraSubscriptionMapper.java | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java
index 6aba5f2..712d9c4 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java
@@ -42,11 +42,11 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableList.Builder;
 
-    private static final int INITIAL_SIZE = 64;
-    private final Map<String, List<Subscription>> subscriptionsByUser;
+public class CassandraSubscriptionMapper extends NonTransactionalMapper implements SubscriptionMapper {
+    private Session session;
 
-    public CassandraSubscriptionMapper() {
-        subscriptionsByUser = new ConcurrentHashMap<String, List<Subscription>>(INITIAL_SIZE);
+    public CassandraSubscriptionMapper(Session session) {
+        this.session = session;
     }
 
     @Override
-- 
2.0.3


From 941ee4144d7924608453507af2706d35507dbb5c Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 15:22:20 +0200
Subject: [PATCH 21/35] Use Cassandra instead a private List in
 CassandraSubscriptionMapper

---
 .../user/CassandraSubscriptionMapper.java          | 34 +++++++---------------
 1 file changed, 10 insertions(+), 24 deletions(-)

diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java
index 712d9c4..522883a 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java
@@ -51,39 +51,25 @@ public CassandraSubscriptionMapper(Session session) {
 
     @Override
     public synchronized void delete(Subscription subscription) {
-        final String user = subscription.getUser();
-        final List<Subscription> subscriptions = subscriptionsByUser.get(user);
-        if (subscriptions != null) {
-            subscriptions.remove(subscription);
-        }
+        session.execute(QueryBuilder.delete().from(TABLE_NAME).where(eq(USER, subscription.getUser())).and(eq(MAILBOX, subscription.getMailbox())));
     }
 
     @Override
     public Subscription findMailboxSubscriptionForUser(String user, String mailbox) {
-        final List<Subscription> subscriptions = subscriptionsByUser.get(user);
-        Subscription result = null;
-        if (subscriptions != null) {
-            for (Subscription subscription : subscriptions) {
-                if (subscription.getMailbox().equals(mailbox)) {
-                    result = subscription;
-                    break;
-                }
-            }
-        }
-        return result;
+        ResultSet results = session.execute(select(MAILBOX).from(TABLE_NAME).where(eq(USER, user)).and(eq(MAILBOX, mailbox)));
+        return !results.isExhausted() ? new SimpleSubscription(user, mailbox) : null;
     }
 
     @Override
     public List<Subscription> findSubscriptionsForUser(String user) {
-        final List<Subscription> subcriptions = subscriptionsByUser.get(user);
-        final List<Subscription> results;
-        if (subcriptions == null) {
-            results = Collections.EMPTY_LIST;
-        } else {
-            // Make a copy to prevent concurrent modifications
-            results = new ArrayList<Subscription>(subcriptions);
+        Builder<Subscription> result = ImmutableList.<Subscription> builder();
+        Select query = select(MAILBOX).from(TABLE_NAME);
+        query.where(eq(USER, user));
+        query.allowFiltering();
+        for (Row row : session.execute(query)) {
+            result.add(new SimpleSubscription(user, row.getString(MAILBOX)));
         }
-        return results;
+        return result.build();
     }
 
     @Override
-- 
2.0.3


From a95a16e89bca22fa569df46c7a44b0e51ac1b4e3 Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 15:23:44 +0200
Subject: [PATCH 22/35] Fix save method of CassandraSubscriptionMapper and add
 the list method

---
 .../cassandra/user/CassandraSubscriptionMapper.java    | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java
index 522883a..77d45ca 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapper.java
@@ -32,6 +32,7 @@
 import org.apache.james.mailbox.store.transaction.NonTransactionalMapper;
 import org.apache.james.mailbox.store.user.SubscriptionMapper;
 import org.apache.james.mailbox.store.user.model.Subscription;
+import org.apache.james.mailbox.store.user.model.impl.SimpleSubscription;
 
 import com.datastax.driver.core.ResultSet;
 import com.datastax.driver.core.Row;
@@ -74,15 +75,16 @@ public Subscription findMailboxSubscriptionForUser(String user, String mailbox)
 
     @Override
     public synchronized void save(Subscription subscription) {
-        final String user = subscription.getUser();
-        final List<Subscription> subscriptions = subscriptionsByUser.get(user);
-        if (subscriptions == null) {
-            final List<Subscription> newSubscriptions = new ArrayList<Subscription>();
-            newSubscriptions.add(subscription);
-            subscriptionsByUser.put(user, newSubscriptions);
-        } else {
-            subscriptions.add(subscription);
+        Insert query = insertInto(TABLE_NAME).value(USER, subscription.getUser()).value(MAILBOX, subscription.getMailbox());
+        session.execute(query);
+    }
+
+    public List<SimpleSubscription> list() {
+        Builder<SimpleSubscription> result = ImmutableList.<SimpleSubscription> builder();
+        for (Row row : session.execute(select(FIELDS).from(TABLE_NAME))) {
+            result.add(new SimpleSubscription(row.getString(USER), row.getString(MAILBOX)));
         }
+        return result.build();
     }
 
     @Override
-- 
2.0.3


From e180b6f526f1d1ee4ca7fbbb69ba0252787fe3c5 Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 15:33:39 +0200
Subject: [PATCH 23/35] Rewrite the CassandraMailboxManagerTest class

---
 .../cassandra/CassandraMailboxManagerTest.java     | 170 +++++++++++----------
 1 file changed, 90 insertions(+), 80 deletions(-)

diff --git a/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java
index 1384bdb..8ff72ed 100644
--- a/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java
+++ b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java
@@ -1,80 +1,90 @@
-/****************************************************************
- * 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;
-
-import java.util.UUID;
-
-import org.apache.james.mailbox.AbstractMailboxManagerTest;
-import org.apache.james.mailbox.MailboxSession;
-import org.apache.james.mailbox.acl.GroupMembershipResolver;
-import org.apache.james.mailbox.acl.MailboxACLResolver;
-import org.apache.james.mailbox.acl.SimpleGroupMembershipResolver;
-import org.apache.james.mailbox.acl.UnionMailboxACLResolver;
-import org.apache.james.mailbox.cassandra.mail.CassandraMailboxMapper;
-import org.apache.james.mailbox.cassandra.mail.CassandraMessageMapper;
-import org.apache.james.mailbox.cassandra.mail.CassandraModSeqProvider;
-import org.apache.james.mailbox.cassandra.mail.CassandraUidProvider;
-import org.apache.james.mailbox.cassandra.user.CassandraSubscriptionMapper;
-import org.apache.james.mailbox.exception.BadCredentialsException;
-import org.apache.james.mailbox.exception.MailboxException;
-import org.apache.james.mailbox.store.MockAuthenticator;
-import org.apache.james.mailbox.store.StoreMailboxManager;
-import org.cassandraunit.CassandraCQLUnit;
-import org.cassandraunit.dataset.cql.ClassPathCQLDataSet;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.slf4j.LoggerFactory;
-
-/**
- * InMemoryMailboxManagerTest that extends the MailboxManagerTest.
- */
-public class CassandraMailboxManagerTest extends AbstractMailboxManagerTest {
-
-    @Rule
-    public CassandraCQLUnit cassandraCQLUnit = new CassandraCQLUnit(new ClassPathCQLDataSet("mailbox.cql", "mailbox"));
-
-    @Before
-    public void setup() throws Exception {
-        createMailboxManager();
-    }
-
-    @After
-    public void tearDown() throws BadCredentialsException, MailboxException {
-        MailboxSession session = getMailboxManager().createSystemSession("test", LoggerFactory.getLogger("Test"));
-        session.close();
-    }
-
-    @Override
-    protected void createMailboxManager() throws MailboxException {
-        CassandraMailboxMapper mailboxMapper = new CassandraMailboxMapper(cassandraCQLUnit.session);
-        CassandraMessageMapper messageMapper = new CassandraMessageMapper(cassandraCQLUnit.session, new CassandraUidProvider(cassandraCQLUnit.session), new CassandraModSeqProvider(cassandraCQLUnit.session));
-        CassandraSubscriptionMapper subscriptionMapper = new CassandraSubscriptionMapper();
-        CassandraMailboxSessionMapperFactory factory = new CassandraMailboxSessionMapperFactory(mailboxMapper, messageMapper, subscriptionMapper);
-        MailboxACLResolver aclResolver = new UnionMailboxACLResolver();
-        GroupMembershipResolver groupMembershipResolver = new SimpleGroupMembershipResolver();
-
-        StoreMailboxManager<UUID> mailboxManager = new StoreMailboxManager<UUID>(factory, new MockAuthenticator(), aclResolver, groupMembershipResolver);
-        mailboxManager.init();
-
-        setMailboxManager(mailboxManager);
-
-    }
-
-}
+/****************************************************************
+ * 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;
+
+import org.apache.james.mailbox.AbstractMailboxManagerTest;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.cassandra.mail.CassandraModSeqProvider;
+import org.apache.james.mailbox.cassandra.mail.CassandraUidProvider;
+import org.apache.james.mailbox.cassandra.table.CassandraMailboxTable;
+import org.apache.james.mailbox.exception.BadCredentialsException;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.store.JVMMailboxPathLocker;
+import org.junit.After;
+import org.junit.Before;
+import org.slf4j.LoggerFactory;
+
+/**
+ * CassandraMailboxManagerTest that extends the StoreMailboxManagerTest.
+ * 
+ */
+public class CassandraMailboxManagerTest extends AbstractMailboxManagerTest {
+
+    private static final CassandraClusterSingleton CLUSTER = CassandraClusterSingleton.build();
+
+    /**
+     * Setup the mailboxManager.
+     * 
+     * @throws Exception
+     */
+    @Before
+    public void setup() throws Exception {
+        CLUSTER.ensureAllTables();
+        CLUSTER.clearAllTables();
+        createMailboxManager();
+    }
+
+    /**
+     * Close the system session and entityManagerFactory
+     * 
+     * @throws MailboxException
+     * @throws BadCredentialsException
+     */
+    @After
+    public void tearDown() throws Exception {
+        deleteAllMailboxes();
+        MailboxSession session = getMailboxManager().createSystemSession("test", LoggerFactory.getLogger("Test"));
+        session.close();
+    }
+
+    /*
+     * (non-Javadoc)i deve
+     * 
+     * @see org.apache.james.mailbox.MailboxManagerTest#createMailboxManager()
+     */
+    @Override
+    protected void createMailboxManager() throws MailboxException {
+        final CassandraUidProvider uidProvider = new CassandraUidProvider(CLUSTER.getConf());
+        final CassandraModSeqProvider modSeqProvider = new CassandraModSeqProvider(CLUSTER.getConf());
+        final CassandraMailboxSessionMapperFactory mapperFactory = new CassandraMailboxSessionMapperFactory(uidProvider, modSeqProvider, (CassandraSession) CLUSTER.getConf());
+
+        final CassandraMailboxManager manager = new CassandraMailboxManager(mapperFactory, null, new JVMMailboxPathLocker());
+        manager.init();
+
+        setMailboxManager(manager);
+
+        deleteAllMailboxes();
+    }
+
+    private void deleteAllMailboxes() throws BadCredentialsException, MailboxException {
+        MailboxSession session = getMailboxManager().createSystemSession("test", LoggerFactory.getLogger("Test"));
+        CLUSTER.clearTable(CassandraMailboxTable.TABLE_NAME);
+        session.close();
+    }
+}
-- 
2.0.3


From 97b18b6e87f935c6b3ef28874890c0ad27d0881a Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 15:34:16 +0200
Subject: [PATCH 24/35] Create the CassandraMailboxManager file

---
 .../mailbox/cassandra/CassandraMailboxManager.java | 57 ++++++++++++++++++++++
 1 file changed, 57 insertions(+)
 create mode 100644 cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxManager.java

diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxManager.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxManager.java
new file mode 100644
index 0000000..e33b5f1
--- /dev/null
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxManager.java
@@ -0,0 +1,57 @@
+/****************************************************************
+ * 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;
+
+import java.util.UUID;
+
+import org.apache.james.mailbox.MailboxPathLocker;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.acl.SimpleGroupMembershipResolver;
+import org.apache.james.mailbox.acl.UnionMailboxACLResolver;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.store.Authenticator;
+import org.apache.james.mailbox.store.StoreMailboxManager;
+import org.apache.james.mailbox.store.StoreMessageManager;
+import org.apache.james.mailbox.store.mail.model.Mailbox;
+import org.apache.james.mailbox.store.mail.model.impl.SimpleMailbox;
+
+/**
+ * Cassandra implementation of {@link StoreMailboxManager}
+ */
+public class CassandraMailboxManager extends StoreMailboxManager<UUID> {
+    private MailboxPathLocker locker;
+
+    public CassandraMailboxManager(CassandraMailboxSessionMapperFactory mapperFactory, Authenticator authenticator, final MailboxPathLocker locker) {
+        super(mapperFactory, authenticator, locker, new UnionMailboxACLResolver(), new SimpleGroupMembershipResolver());
+        this.locker = locker;
+    }
+
+    @Override
+    protected Mailbox<UUID> doCreateMailbox(MailboxPath mailboxPath, MailboxSession session) throws MailboxException {
+        return new SimpleMailbox<UUID>(mailboxPath, randomUidValidity());
+    }
+
+    @Override
+    protected StoreMessageManager<UUID> createMessageManager(Mailbox<UUID> mailboxRow, MailboxSession session) throws MailboxException {
+        return new CassandraMessageManager(getMapperFactory(), getMessageSearchIndex(), getEventDispatcher(), this.locker, mailboxRow);
+    }
+
+}
-- 
2.0.3


From 28fb53d71b083486f956f6d2e9c15af375cb7393 Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 15:34:37 +0200
Subject: [PATCH 25/35] Create the CassandraMessageManager file

---
 .../mailbox/cassandra/CassandraMessageManager.java | 57 ++++++++++++++++++++++
 1 file changed, 57 insertions(+)
 create mode 100644 cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMessageManager.java

diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMessageManager.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMessageManager.java
new file mode 100644
index 0000000..12b306e
--- /dev/null
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMessageManager.java
@@ -0,0 +1,57 @@
+/****************************************************************
+ * 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;
+
+import java.util.UUID;
+
+import javax.mail.Flags;
+
+import org.apache.james.mailbox.MailboxPathLocker;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.acl.SimpleGroupMembershipResolver;
+import org.apache.james.mailbox.acl.UnionMailboxACLResolver;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.store.MailboxEventDispatcher;
+import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
+import org.apache.james.mailbox.store.StoreMessageManager;
+import org.apache.james.mailbox.store.mail.model.Mailbox;
+import org.apache.james.mailbox.store.search.MessageSearchIndex;
+
+/**
+ * Cassandra implementation of {@link StoreMessageManager}
+ * 
+ */
+public class CassandraMessageManager extends StoreMessageManager<UUID> {
+
+    public CassandraMessageManager(MailboxSessionMapperFactory<UUID> mapperFactory, MessageSearchIndex<UUID> index, MailboxEventDispatcher<UUID> dispatcher, MailboxPathLocker locker, Mailbox<UUID> mailbox) throws MailboxException {
+        super(mapperFactory, index, dispatcher, locker, mailbox, new UnionMailboxACLResolver(), new SimpleGroupMembershipResolver());
+
+    }
+
+    /**
+     * Support user flags
+     */
+    @Override
+    protected Flags getPermanentFlags(MailboxSession session) {
+        Flags flags = super.getPermanentFlags(session);
+        flags.add(Flags.Flag.USER);
+        return flags;
+    }
+}
-- 
2.0.3


From ebc180d4727ea07da9a3fecd76651b32cc9e54c5 Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 15:34:58 +0200
Subject: [PATCH 26/35] Create the CassandraSubscriptionManager file

---
 .../cassandra/CassandraSubscriptionManager.java    | 43 ++++++++++++++++++++++
 1 file changed, 43 insertions(+)
 create mode 100644 cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManager.java

diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManager.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManager.java
new file mode 100644
index 0000000..8ba938e
--- /dev/null
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManager.java
@@ -0,0 +1,43 @@
+/****************************************************************
+ * 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;
+
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.store.StoreSubscriptionManager;
+import org.apache.james.mailbox.store.user.model.Subscription;
+import org.apache.james.mailbox.store.user.model.impl.SimpleSubscription;
+
+/**
+ * Cassandra implementation of {@link StoreSubscriptionManager}
+ * 
+ */
+public class CassandraSubscriptionManager extends StoreSubscriptionManager {
+
+    public CassandraSubscriptionManager(CassandraMailboxSessionMapperFactory mapperFactory) {
+        super(mapperFactory);
+    }
+
+    /**
+     * @see org.apache.james.mailbox.store.StoreSubscriptionManager#createSubscription(org.apache.james.mailbox.MailboxSession,
+     *      java.lang.String)
+     */
+    protected Subscription createSubscription(MailboxSession session, String mailbox) {
+        return new SimpleSubscription(session.getUser().getUserName(), mailbox);
+    }
+}
-- 
2.0.3


From 8b71d0cdc903ecaac273638dca84a56a4164e8c1 Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 15:40:53 +0200
Subject: [PATCH 27/35] Create the Cassandra unit tests, based on the HBase
 unit test

---
 .../cassandra/CassandraClusterSingleton.java       | 128 +++++++++++
 .../CassandraMailboxSessionMapperFactoryTest.java  | 122 +++++++++++
 .../cassandra/mail/CassandraMailboxMapperTest.java | 240 +++++++++++++++++++++
 .../cassandra/mail/CassandraMessageMapperTest.java | 208 ++++++++++++++++++
 .../mail/CassandraUidAndModSeqProviderTest.java    | 163 ++++++++++++++
 .../user/CassandraSubscriptionMapperTest.java      | 180 ++++++++++++++++
 6 files changed, 1041 insertions(+)
 create mode 100644 cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraClusterSingleton.java
 create mode 100644 cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactoryTest.java
 create mode 100644 cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java
 create mode 100644 cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapperTest.java
 create mode 100644 cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraUidAndModSeqProviderTest.java
 create mode 100644 cassandra/src/test/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapperTest.java

diff --git a/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraClusterSingleton.java b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraClusterSingleton.java
new file mode 100644
index 0000000..0f3119d
--- /dev/null
+++ b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraClusterSingleton.java
@@ -0,0 +1,128 @@
+/****************************************************************
+ * 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;
+
+import org.apache.commons.lang.NotImplementedException;
+import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.datastax.driver.core.Session;
+
+/**
+ * Class that will creates a single instance of Cassandra session.
+ */
+public final class CassandraClusterSingleton {
+    private final static String CLUSTER_IP = "localhost";
+    private final static int CLUSTER_PORT_TEST = 9142;
+    private final static String KEYSPACE_NAME = "apache_james";
+    private final static int DEFAULT_REPLICATION_FACTOR = 1;
+
+    private static final Logger LOG = LoggerFactory.getLogger(CassandraClusterSingleton.class);
+    private static CassandraClusterSingleton cluster = null;
+    private CassandraSession session;
+
+    /**
+     * Builds a MiniCluster instance.
+     * 
+     * @return the {@link CassandraClusterSingleton} instance
+     * @throws RuntimeException
+     */
+    public static synchronized CassandraClusterSingleton build() throws RuntimeException {
+        LOG.info("Retrieving cluster instance.");
+        if (cluster == null) {
+            cluster = new CassandraClusterSingleton();
+        }
+        return cluster;
+    }
+
+    private CassandraClusterSingleton() throws RuntimeException {
+        try {
+            EmbeddedCassandraServerHelper.startEmbeddedCassandra();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        this.session = new CassandraSession(CLUSTER_IP, CLUSTER_PORT_TEST, KEYSPACE_NAME, DEFAULT_REPLICATION_FACTOR);
+    }
+
+    /**
+     * Return a configuration for the runnning MiniCluster.
+     * 
+     * @return
+     */
+    public Session getConf() {
+        return session;
+    }
+
+    /**
+     * Create a specific table.
+     * 
+     * @param tableName
+     *            the table name
+     */
+    public void ensureTable(String tableName) {
+        if (tableName.equals("mailbox")) {
+            session.execute("CREATE TABLE IF NOT EXISTS " + session.getLoggedKeyspace() + ".mailbox (" + "id uuid PRIMARY KEY," + "name text, namespace text," + "uidvalidity bigint," + "user text," + "path text" + ");");
+
+            session.execute("CREATE INDEX IF NOT EXISTS ON " + session.getLoggedKeyspace() + ".mailbox(path);");
+        } else if (tableName.equals("messageCounter")) {
+            session.execute("CREATE TABLE IF NOT EXISTS " + session.getLoggedKeyspace() + ".messageCounter (" + "mailboxId UUID PRIMARY KEY," + "nextUid bigint," + ");");
+        } else if (tableName.equals("mailboxCounters")) {
+            session.execute("CREATE TABLE IF NOT EXISTS " + session.getLoggedKeyspace() + ".mailboxCounters (" + "mailboxId UUID PRIMARY KEY," + "count counter," + "unseen counter," + "nextModSeq counter" + ");");
+        } else if (tableName.equals("message")) {
+            session.execute("CREATE TABLE IF NOT EXISTS " + session.getLoggedKeyspace() + ".message (" + "mailboxId UUID," + "uid bigint," + "internalDate timestamp," + "bodyStartOctet int," + "content blob," + "modSeq bigint," + "mediaType text," + "subType text," + "fullContentOctets int,"
+                    + "bodyOctets int," + "textualLineCount bigint," + "bodyContent blob," + "headerContent blob," + "flagAnswered boolean," + "flagDeleted boolean," + "flagDraft boolean," + "flagRecent boolean," + "flagSeen boolean," + "flagFlagged boolean," + "flagUser boolean,"
+                    + "PRIMARY KEY (mailboxId, uid)" + ");");
+        } else if (tableName.equals("subscription")) {
+            session.execute("CREATE TABLE IF NOT EXISTS " + session.getLoggedKeyspace() + ".subscription (" + "user text," + "mailbox text," + "PRIMARY KEY (mailbox, user)" + ");");
+        } else {
+            throw new NotImplementedException("We don't support the class " + tableName);
+        }
+    }
+
+    /**
+     * Ensure all tables
+     */
+    public void ensureAllTables() {
+        ensureTable("mailbox");
+        ensureTable("mailboxCounters");
+        ensureTable("message");
+        ensureTable("subscription");
+    }
+
+    /**
+     * Delete all rows from specified table.
+     * 
+     * @param tableName
+     */
+    public void clearTable(String tableName) {
+        session.execute("TRUNCATE " + tableName + ";");
+    }
+
+    /**
+     * Delete all rows for all tables.
+     */
+    public void clearAllTables() {
+        clearTable("mailbox");
+        clearTable("mailboxCounters");
+        clearTable("message");
+        clearTable("subscription");
+    }
+
+}
diff --git a/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactoryTest.java b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactoryTest.java
new file mode 100644
index 0000000..bcabfe2
--- /dev/null
+++ b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactoryTest.java
@@ -0,0 +1,122 @@
+/****************************************************************
+ * 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;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.UUID;
+
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.cassandra.mail.CassandraModSeqProvider;
+import org.apache.james.mailbox.cassandra.mail.CassandraUidProvider;
+import org.apache.james.mailbox.store.mail.MailboxMapper;
+import org.apache.james.mailbox.store.mail.MessageMapper;
+import org.apache.james.mailbox.store.mail.ModSeqProvider;
+import org.apache.james.mailbox.store.mail.UidProvider;
+import org.apache.james.mailbox.store.user.SubscriptionMapper;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The MailboxSessionMapperFactory test.
+ * 
+ */
+public class CassandraMailboxSessionMapperFactoryTest {
+    private static final CassandraClusterSingleton CLUSTER = CassandraClusterSingleton.build();
+    private final static Logger LOG = LoggerFactory.getLogger(CassandraMailboxSessionMapperFactoryTest.class);
+
+    @Before
+    public void beforeMethod() throws IOException {
+        CLUSTER.ensureAllTables();
+        CLUSTER.clearAllTables();
+    }
+
+    /**
+     * Test of createMessageMapper method, of class
+     * CassandraMailboxSessionMapperFactory.
+     */
+    @Test
+    public void testCreateMessageMapper() throws Exception {
+        LOG.info("createMessageMapper");
+        MailboxSession session = null;
+        CassandraMailboxSessionMapperFactory instance = new CassandraMailboxSessionMapperFactory(null, null, null);
+        MessageMapper<UUID> messageMapper = instance.createMessageMapper(session);
+        assertNotNull(messageMapper);
+        assertTrue(messageMapper instanceof MessageMapper);
+    }
+
+    /**
+     * Test of createMailboxMapper method, of class
+     * CassandraMailboxSessionMapperFactory.
+     */
+    @Test
+    public void testCreateMailboxMapper() throws Exception {
+        LOG.info("createMailboxMapper");
+        MailboxSession session = null;
+        CassandraMailboxSessionMapperFactory instance = new CassandraMailboxSessionMapperFactory(null, null, null);
+        MailboxMapper<UUID> mailboxMapper = instance.createMailboxMapper(session);
+        assertNotNull(mailboxMapper);
+        assertTrue(mailboxMapper instanceof MailboxMapper);
+    }
+
+    /**
+     * Test of createSubscriptionMapper method, of class
+     * CassandraMailboxSessionMapperFactory.
+     */
+    @Test
+    public void testCreateSubscriptionMapper() throws Exception {
+        LOG.info("createSubscriptionMapper");
+        MailboxSession session = null;
+        CassandraMailboxSessionMapperFactory instance = new CassandraMailboxSessionMapperFactory(null, null, null);
+        SubscriptionMapper subscriptionMapper = instance.createSubscriptionMapper(session);
+        assertNotNull(subscriptionMapper);
+        assertTrue(subscriptionMapper instanceof SubscriptionMapper);
+    }
+
+    /**
+     * Test of getModSeqProvider method, of class
+     * CassandraMailboxSessionMapperFactory.
+     */
+    @Test
+    public void testGetModSeqProvider() {
+        LOG.info("getModSeqProvider");
+        ModSeqProvider<UUID> expResult = new CassandraModSeqProvider(CLUSTER.getConf());
+        CassandraMailboxSessionMapperFactory instance = new CassandraMailboxSessionMapperFactory(null, expResult, null);
+        ModSeqProvider<UUID> result = instance.getModSeqProvider();
+        assertEquals(expResult, result);
+    }
+
+    /**
+     * Test of getUidProvider method, of class
+     * CassandraMailboxSessionMapperFactory.
+     */
+    @Test
+    public void testGetUidProvider() {
+        LOG.info("getUidProvider");
+        UidProvider<UUID> expResult = new CassandraUidProvider(CLUSTER.getConf());
+        CassandraMailboxSessionMapperFactory instance = new CassandraMailboxSessionMapperFactory((CassandraUidProvider) expResult, null, null);
+        UidProvider<UUID> result = instance.getUidProvider();
+        assertEquals(expResult, result);
+    }
+}
diff --git a/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java
new file mode 100644
index 0000000..0ab1be3
--- /dev/null
+++ b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java
@@ -0,0 +1,240 @@
+/****************************************************************
+ * 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.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.UUID;
+
+import org.apache.james.mailbox.cassandra.CassandraClusterSingleton;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.exception.MailboxNotFoundException;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.store.mail.model.Mailbox;
+import org.apache.james.mailbox.store.mail.model.impl.SimpleMailbox;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.datastax.driver.core.Session;
+
+/**
+ * CassandraMailboxMapper unit tests.
+ * 
+ */
+public class CassandraMailboxMapperTest {
+
+    private static final Logger LOG = LoggerFactory.getLogger(CassandraMailboxMapperTest.class);
+    public static final CassandraClusterSingleton CLUSTER = CassandraClusterSingleton.build();
+    private static CassandraMailboxMapper mapper;
+    private static List<SimpleMailbox<UUID>> mailboxList;
+    private static List<MailboxPath> pathsList;
+    private static final int NAMESPACES = 5;
+    private static final int USERS = 5;
+    private static final int MAILBOX_NO = 5;
+    private static final char SEPARATOR = '%';
+    private Session session;
+
+    @Before
+    public void setUp() throws Exception {
+        CLUSTER.ensureAllTables();
+        CLUSTER.clearAllTables();
+        session = CLUSTER.getConf();
+        fillMailboxList();
+        mapper = new CassandraMailboxMapper(session);
+        for (SimpleMailbox<UUID> mailbox : mailboxList) {
+            mapper.save(mailbox);
+        }
+    }
+
+    /**
+     * Test an ordered scenario with list, delete... methods.
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void testMailboxMapperScenario() throws Exception {
+        testFindMailboxByPath();
+        testFindMailboxWithPathLike();
+        testList();
+        testSave();
+        testDelete();
+        testHasChildren();
+        // testDeleteAllMemberships(); // Ignore this test
+    }
+
+    /**
+     * Test of findMailboxByPath method, of class CassandraMailboxMapper.
+     */
+    private void testFindMailboxByPath() throws Exception {
+        LOG.info("findMailboxByPath");
+        SimpleMailbox<UUID> mailbox;
+        for (MailboxPath path : pathsList) {
+            LOG.info("Searching for " + path);
+            mailbox = (SimpleMailbox<UUID>) mapper.findMailboxByPath(path);
+            assertEquals(path, new MailboxPath(mailbox.getNamespace(), mailbox.getUser(), mailbox.getName()));
+        }
+    }
+
+    /**
+     * Test of findMailboxWithPathLike method, of class CassandraMailboxMapper.
+     */
+    private void testFindMailboxWithPathLike() throws Exception {
+        LOG.info("findMailboxWithPathLike");
+        MailboxPath path = pathsList.get(pathsList.size() / 2);
+
+        List<Mailbox<UUID>> result = mapper.findMailboxWithPathLike(path);
+        assertEquals(1, result.size());
+
+        int start = 3;
+        int end = 7;
+        MailboxPath newPath;
+
+        for (int i = start; i < end; i++) {
+            newPath = new MailboxPath(path);
+            newPath.setName(i + newPath.getName() + " " + i);
+            // test for paths with null user
+            if (i % 2 == 0) {
+                newPath.setUser(null);
+            }
+            addMailbox(new SimpleMailbox<UUID>(newPath, 1234));
+        }
+        result = mapper.findMailboxWithPathLike(path);
+        assertEquals(end - start + 1, result.size());
+    }
+
+    /**
+     * Test of list method, of class CassandraMailboxMapper.
+     */
+    private void testList() throws Exception {
+        LOG.info("list");
+        List<Mailbox<UUID>> result = mapper.list();
+        assertEquals(mailboxList.size(), result.size());
+
+    }
+
+    /**
+     * Test of save method and list method, of class CassandraMailboxMapper.
+     */
+    private void testSave() throws Exception {
+        LOG.info("save and mailboxFromResult");
+        final List<Mailbox<UUID>> mailboxes = mapper.list();
+        final SimpleMailbox<UUID> mlbx = mailboxList.get(mailboxList.size() / 2);
+        Mailbox<UUID> newValue = null;
+
+        for (Mailbox<UUID> mailbox : mailboxes) {
+            if (mlbx.getMailboxId().equals(mailbox.getMailboxId())) {
+                newValue = mailbox;
+            }
+        }
+
+        assertEquals(mlbx, newValue);
+        assertEquals(mlbx.getUser(), newValue.getUser());
+        assertEquals(mlbx.getName(), newValue.getName());
+        assertEquals(mlbx.getNamespace(), newValue.getNamespace());
+        assertEquals(mlbx.getMailboxId(), newValue.getMailboxId());
+    }
+
+    /**
+     * Test of delete method, of class CassandraMailboxMapper.
+     */
+    private void testDelete() throws Exception {
+        LOG.info("delete");
+        // delete last 5 mailboxes from mailboxList
+        int offset = 5;
+        int notFoundCount = 0;
+
+        Iterator<SimpleMailbox<UUID>> iterator = mailboxList.subList(mailboxList.size() - offset, mailboxList.size()).iterator();
+
+        while (iterator.hasNext()) {
+            SimpleMailbox<UUID> mailbox = iterator.next();
+            mapper.delete(mailbox);
+            iterator.remove();
+            MailboxPath path = new MailboxPath(mailbox.getNamespace(), mailbox.getUser(), mailbox.getName());
+            pathsList.remove(path);
+            LOG.info("Removing mailbox: {}", path);
+            try {
+                mapper.findMailboxByPath(path);
+            } catch (MailboxNotFoundException e) {
+                LOG.info("Succesfully removed {}", mailbox);
+                notFoundCount++;
+            }
+        }
+        assertEquals(offset, notFoundCount);
+        assertEquals(mailboxList.size(), mapper.list().size());
+    }
+
+    /**
+     * Test of hasChildren method, of class CassandraMailboxMapper.
+     */
+    private void testHasChildren() throws Exception {
+        LOG.info("hasChildren");
+        String oldName;
+        for (MailboxPath path : pathsList) {
+            final SimpleMailbox<UUID> mailbox = new SimpleMailbox<UUID>(path, 12455);
+            oldName = mailbox.getName();
+            if (path.getUser().equals("user3")) {
+                mailbox.setName("test");
+            }
+            boolean result = mapper.hasChildren(mailbox, SEPARATOR);
+            mailbox.setName(oldName);
+            if (path.getUser().equals("user3")) {
+                assertTrue(result);
+            } else {
+                assertFalse(result);
+            }
+
+        }
+    }
+
+    private static void fillMailboxList() {
+        mailboxList = new ArrayList<SimpleMailbox<UUID>>();
+        pathsList = new ArrayList<MailboxPath>();
+        MailboxPath path;
+        String name;
+        for (int i = 0; i < NAMESPACES; i++) {
+            for (int j = 0; j < USERS; j++) {
+                for (int k = 0; k < MAILBOX_NO; k++) {
+                    if (j == 3) {
+                        name = "test" + SEPARATOR + "subbox" + k;
+                    } else {
+                        name = "mailbox" + k;
+                    }
+                    path = new MailboxPath("namespace" + i, "user" + j, name);
+                    pathsList.add(path);
+                    mailboxList.add(new SimpleMailbox<UUID>(path, 13));
+                }
+            }
+        }
+        LOG.info("Created test case with {} mailboxes and {} paths", mailboxList.size(), pathsList.size());
+    }
+
+    private void addMailbox(SimpleMailbox<UUID> mailbox) throws MailboxException {
+        mailboxList.add(mailbox);
+        pathsList.add(new MailboxPath(mailbox.getNamespace(), mailbox.getUser(), mailbox.getName()));
+        mapper.save(mailbox);
+        LOG.info("Added new mailbox: {} paths: {}", mailboxList.size(), pathsList.size());
+    }
+}
diff --git a/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapperTest.java b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapperTest.java
new file mode 100644
index 0000000..81648ee
--- /dev/null
+++ b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapperTest.java
@@ -0,0 +1,208 @@
+/****************************************************************
+ * 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.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Random;
+import java.util.UUID;
+
+import javax.mail.Flags;
+import javax.mail.internet.SharedInputStream;
+import javax.mail.util.SharedByteArrayInputStream;
+
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.cassandra.CassandraClusterSingleton;
+import org.apache.james.mailbox.mock.MockMailboxSession;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.store.mail.model.Mailbox;
+import org.apache.james.mailbox.store.mail.model.Message;
+import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder;
+import org.apache.james.mailbox.store.mail.model.impl.SimpleMailbox;
+import org.apache.james.mailbox.store.mail.model.impl.SimpleMessage;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.datastax.driver.core.Session;
+
+/**
+ * Unit tests for CassandraMessageMapper.
+ * 
+ */
+public class CassandraMessageMapperTest {
+
+    private static final Logger LOG = LoggerFactory.getLogger(CassandraMailboxMapperTest.class);
+    public static final CassandraClusterSingleton CLUSTER = CassandraClusterSingleton.build();
+    private static CassandraUidProvider uidProvider;
+    private static CassandraModSeqProvider modSeqProvider;
+    private static CassandraMessageMapper messageMapper;
+    private static final List<MailboxPath> MBOX_PATHS = new ArrayList<MailboxPath>();
+    private static final List<Mailbox<UUID>> MBOXES = new ArrayList<Mailbox<UUID>>();
+    private static final List<Message<UUID>> MESSAGE_NO = new ArrayList<Message<UUID>>();
+    private static final int COUNT = 5;
+    private static Session session;
+    /*
+     * we mock a simple message content
+     */
+    private static final String messageTemplate = "Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)\n" + "From: Fred Foobar <foobar@Blurdybloop.COM>\n" + "Subject: Test 02\n" + "To: mooch@owatagu.siam.edu\n" + "Message-Id: <B27397-0100000@Blurdybloop.COM>\n" + "MIME-Version: 1.0\n"
+            + "Content-Type: TEXT/PLAIN; CHARSET=US-ASCII\n" + "\n" + "Test\n" + "\n.";
+
+    private static SharedInputStream content = new SharedByteArrayInputStream(messageTemplate.getBytes());
+
+    @Before
+    public void setUp() throws Exception {
+        CLUSTER.ensureAllTables();
+        CLUSTER.clearAllTables();
+        session = CLUSTER.getConf();
+        uidProvider = new CassandraUidProvider(session);
+        modSeqProvider = new CassandraModSeqProvider(session);
+        generateTestData();
+        final MailboxSession mailboxSession = new MockMailboxSession("ieugen");
+        messageMapper = new CassandraMessageMapper(session, uidProvider, modSeqProvider, mailboxSession);
+        for (int i = 0; i < MESSAGE_NO.size(); i++) {
+            messageMapper.add(MBOXES.get(1), MESSAGE_NO.get(i));
+        }
+    }
+
+    public static void generateTestData() {
+        final Random random = new Random();
+        MailboxPath mboxPath;
+        final PropertyBuilder propBuilder = new PropertyBuilder();
+        SimpleMailbox<UUID> mailbox;
+
+        for (int i = 0; i < COUNT; i++) {
+            if (i % 2 == 0) {
+                mboxPath = new MailboxPath("gsoc", "ieugen" + i, "INBOX");
+            } else {
+                mboxPath = new MailboxPath("gsoc", "ieugen" + i, "INBOX.box" + i);
+            }
+            MBOX_PATHS.add(mboxPath);
+            mailbox = new SimpleMailbox<UUID>(MBOX_PATHS.get(i), random.nextLong());
+            mailbox.setMailboxId(UUID.randomUUID());
+            MBOXES.add(mailbox);
+            propBuilder.setProperty("gsoc", "prop" + i, "value");
+        }
+        propBuilder.setMediaType("text");
+        propBuilder.setSubType("html");
+        propBuilder.setTextualLineCount(2L);
+
+        SimpleMessage<UUID> myMsg;
+        final Flags flags = new Flags(Flags.Flag.RECENT);
+        final Date today = new Date();
+
+        for (int i = 0; i < COUNT * 2; i++) {
+            myMsg = new SimpleMessage<UUID>(today, messageTemplate.getBytes().length, messageTemplate.getBytes().length - 20, content, flags, propBuilder, MBOXES.get(1).getMailboxId());
+            if (i == COUNT * 2 - 1) {
+                flags.add(Flags.Flag.SEEN);
+                flags.remove(Flags.Flag.RECENT);
+                myMsg.setFlags(flags);
+            }
+            MESSAGE_NO.add(myMsg);
+        }
+    }
+
+    /**
+     * Test an ordered scenario with count, find, add... methods.
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void testMessageMapperScenario() throws Exception {
+        testCountMessagesInMailbox();
+        testCountUnseenMessagesInMailbox();
+        testFindFirstUnseenMessageUid();
+        testFindRecentMessageUidsInMailbox();
+        testAdd();
+        testGetLastUid();
+        testGetHighestModSeq();
+    }
+
+    /**
+     * Test of countMessagesInMailbox method, of class CassandraMessageMapper.
+     */
+    private void testCountMessagesInMailbox() throws Exception {
+        LOG.info("countMessagesInMailbox");
+        long messageCount = messageMapper.countMessagesInMailbox(MBOXES.get(1));
+        assertEquals(MESSAGE_NO.size(), messageCount);
+    }
+
+    /**
+     * Test of countUnseenMessagesInMailbox method, of class
+     * CassandraMessageMapper.
+     */
+    private void testCountUnseenMessagesInMailbox() throws Exception {
+        LOG.info("countUnseenMessagesInMailbox");
+        long unseen = messageMapper.countUnseenMessagesInMailbox(MBOXES.get(1));
+        assertEquals(MESSAGE_NO.size() - 1, unseen);
+    }
+
+    /**
+     * Test of findFirstUnseenMessageUid method, of class
+     * CassandraMessageMapper.
+     */
+    private void testFindFirstUnseenMessageUid() throws Exception {
+        LOG.info("findFirstUnseenMessageUid");
+        final long uid = messageMapper.findFirstUnseenMessageUid(MBOXES.get(1));
+        assertEquals(1, uid);
+    }
+
+    /**
+     * Test of findRecentMessageUidsInMailbox method, of class
+     * CassandraMessageMapper.
+     */
+    private void testFindRecentMessageUidsInMailbox() throws Exception {
+        LOG.info("findRecentMessageUidsInMailbox");
+        List<Long> recentMessages = messageMapper.findRecentMessageUidsInMailbox(MBOXES.get(1));
+        assertEquals(MESSAGE_NO.size() - 1, recentMessages.size());
+    }
+
+    /**
+     * Test of add method, of class CassandraMessageMapper.
+     */
+    private void testAdd() throws Exception {
+        LOG.info("add");
+        // The tables should be deleted every time the tests run.
+        long msgCount = messageMapper.countMessagesInMailbox(MBOXES.get(1));
+        LOG.info(msgCount + " " + MESSAGE_NO.size());
+        assertEquals(MESSAGE_NO.size(), msgCount);
+    }
+
+    /**
+     * Test of getLastUid method, of class CassandraMessageMapper.
+     */
+    private void testGetLastUid() throws Exception {
+        LOG.info("getLastUid");
+        long lastUid = messageMapper.getLastUid(MBOXES.get(1));
+        assertEquals(MESSAGE_NO.size(), lastUid);
+    }
+
+    /**
+     * Test of getHighestModSeq method, of class CassandraMessageMapper.
+     */
+    private void testGetHighestModSeq() throws Exception {
+        LOG.info("getHighestModSeq");
+        long highestModSeq = messageMapper.getHighestModSeq(MBOXES.get(1));
+        assertEquals(MESSAGE_NO.size(), highestModSeq);
+    }
+}
diff --git a/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraUidAndModSeqProviderTest.java b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraUidAndModSeqProviderTest.java
new file mode 100644
index 0000000..a89ac14
--- /dev/null
+++ b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraUidAndModSeqProviderTest.java
@@ -0,0 +1,163 @@
+/****************************************************************
+ * 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.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.apache.james.mailbox.cassandra.CassandraClusterSingleton;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.store.mail.model.impl.SimpleMailbox;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.datastax.driver.core.Session;
+
+/**
+ * Unit tests for UidProvider and ModSeqProvider.
+ * 
+ */
+public class CassandraUidAndModSeqProviderTest {
+
+    private static final Logger LOG = LoggerFactory.getLogger(CassandraUidAndModSeqProviderTest.class);
+    private static final CassandraClusterSingleton CLUSTER = CassandraClusterSingleton.build();
+    private static Session session;
+    private static CassandraUidProvider uidProvider;
+    private static CassandraModSeqProvider modSeqProvider;
+    private static CassandraMailboxMapper mapper;
+    private static List<SimpleMailbox<UUID>> mailboxList;
+    private static List<MailboxPath> pathsList;
+    private static final int NAMESPACES = 5;
+    private static final int USERS = 5;
+    private static final int MAILBOX_NO = 5;
+    private static final char SEPARATOR = '%';
+
+    @Before
+    public void setUpClass() throws Exception {
+        CLUSTER.ensureAllTables();
+        CLUSTER.ensureAllTables();
+        session = CLUSTER.getConf();
+        uidProvider = new CassandraUidProvider(session);
+        modSeqProvider = new CassandraModSeqProvider(session);
+        mapper = new CassandraMailboxMapper(session);
+        fillMailboxList();
+        for (SimpleMailbox<UUID> mailbox : mailboxList) {
+            mapper.save(mailbox);
+        }
+    }
+
+    private static void fillMailboxList() {
+        mailboxList = new ArrayList<SimpleMailbox<UUID>>();
+        pathsList = new ArrayList<MailboxPath>();
+        MailboxPath path;
+        String name;
+        for (int i = 0; i < NAMESPACES; i++) {
+            for (int j = 0; j < USERS; j++) {
+                for (int k = 0; k < MAILBOX_NO; k++) {
+                    if (j == 3) {
+                        name = "test" + SEPARATOR + "subbox" + k;
+                    } else {
+                        name = "mailbox" + k;
+                    }
+                    path = new MailboxPath("namespace" + i, "user" + j, name);
+                    pathsList.add(path);
+                    mailboxList.add(new SimpleMailbox<UUID>(path, 13));
+                }
+            }
+        }
+
+        LOG.info("Created test case with {} mailboxes and {} paths", mailboxList.size(), pathsList.size());
+    }
+
+    /**
+     * Test of lastUid method, of class CassandraUidProvider.
+     */
+    @Test
+    public void testLastUid() throws Exception {
+        LOG.info("lastUid");
+        final MailboxPath path = new MailboxPath("gsoc", "ieugen", "Trash");
+        final SimpleMailbox<UUID> newBox = new SimpleMailbox<UUID>(path, 1234);
+        mapper.save(newBox);
+        mailboxList.add(newBox);
+        pathsList.add(path);
+
+        final long result = uidProvider.lastUid(null, newBox);
+        assertEquals(0, result);
+        for (int i = 1; i < 10; i++) {
+            final long uid = uidProvider.nextUid(null, newBox);
+            assertEquals(uid, uidProvider.lastUid(null, newBox));
+        }
+    }
+
+    /**
+     * Test of nextUid method, of class CassandraUidProvider.
+     */
+    @Test
+    public void testNextUid() throws Exception {
+        LOG.info("nextUid");
+        final SimpleMailbox<UUID> mailbox = mailboxList.get(mailboxList.size() / 2);
+        final long lastUid = uidProvider.lastUid(null, mailbox);
+        long result;
+        for (int i = (int) lastUid + 1; i < (lastUid + 10); i++) {
+            result = uidProvider.nextUid(null, mailbox);
+            assertEquals(i, result);
+        }
+    }
+
+    /**
+     * Test of highestModSeq method, of class CassandraModSeqProvider.
+     */
+    @Test
+    public void testHighestModSeq() throws Exception {
+        LOG.info("highestModSeq");
+        LOG.info("lastUid");
+        MailboxPath path = new MailboxPath("gsoc", "ieugen", "Trash");
+        SimpleMailbox<UUID> newBox = new SimpleMailbox<UUID>(path, 1234);
+        mapper.save(newBox);
+        mailboxList.add(newBox);
+        pathsList.add(path);
+
+        long result = modSeqProvider.highestModSeq(null, newBox);
+        assertEquals(0, result);
+        for (int i = 1; i < 10; i++) {
+            long uid = modSeqProvider.nextModSeq(null, newBox);
+            assertEquals(uid, modSeqProvider.highestModSeq(null, newBox));
+        }
+    }
+
+    /**
+     * Test of nextModSeq method, of class CassandraModSeqProvider.
+     */
+    @Test
+    public void testNextModSeq() throws Exception {
+        LOG.info("nextModSeq");
+        final SimpleMailbox<UUID> mailbox = mailboxList.get(mailboxList.size() / 2);
+        final long lastUid = modSeqProvider.highestModSeq(null, mailbox);
+        long result;
+        for (int i = (int) lastUid + 1; i < (lastUid + 10); i++) {
+            result = modSeqProvider.nextModSeq(null, mailbox);
+            assertEquals(i, result);
+        }
+    }
+}
diff --git a/cassandra/src/test/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapperTest.java b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapperTest.java
new file mode 100644
index 0000000..b62b31f
--- /dev/null
+++ b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapperTest.java
@@ -0,0 +1,180 @@
+/****************************************************************
+ * 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.user;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.james.mailbox.cassandra.CassandraClusterSingleton;
+import org.apache.james.mailbox.exception.SubscriptionException;
+import org.apache.james.mailbox.store.user.model.Subscription;
+import org.apache.james.mailbox.store.user.model.impl.SimpleSubscription;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.datastax.driver.core.Session;
+
+/**
+ * Runs tests for SubscriptionMapper.
+ * 
+ */
+public class CassandraSubscriptionMapperTest {
+
+    private static final Logger LOG = LoggerFactory.getLogger(CassandraSubscriptionMapperTest.class);
+    private static final CassandraClusterSingleton CLUSTER = CassandraClusterSingleton.build();
+    private static Session session;
+    private static CassandraSubscriptionMapper mapper;
+    private static Map<String, List<SimpleSubscription>> subscriptionList;
+    private static final int USERS = 5;
+    private static final int MAILBOX_NO = 5;
+
+    @Before
+    public void setUp() throws Exception {
+        CLUSTER.ensureAllTables();
+        CLUSTER.clearAllTables();
+        session = CLUSTER.getConf();
+        mapper = new CassandraSubscriptionMapper(session);
+        fillSubscriptionList();
+    }
+
+    private static void fillSubscriptionList() throws SubscriptionException {
+        LOG.info("Creating subscription list");
+        SimpleSubscription subscription;
+        String user, mailbox;
+        subscriptionList = new HashMap<String, List<SimpleSubscription>>();
+        for (int i = 0; i < USERS; i++) {
+            user = "user" + i;
+            final List<SimpleSubscription> mailboxes = new ArrayList<SimpleSubscription>();
+            subscriptionList.put(user, mailboxes);
+
+            for (int j = 0; j < MAILBOX_NO; j++) {
+                if (j == 0) {
+                    mailbox = "INBOX";
+                } else {
+                    mailbox = "BOX" + j;
+                }
+                if ((i % 2 == 0) && (j > 0)) {
+                    continue;
+                }
+                subscription = new SimpleSubscription(user, mailbox);
+                mailboxes.add(subscription);
+                mapper.save(subscription);
+                LOG.info("Adding subscription " + subscription);
+            }
+        }
+    }
+
+    /**
+     * Test of findMailboxSubscriptionForUser method, of class
+     * CassandraSubscriptionMapper.
+     */
+    @Test
+    public void testFindMailboxSubscriptionForUser() throws Exception {
+        LOG.info("findMailboxSubscriptionForUser");
+
+        final SimpleSubscription fake1 = new SimpleSubscription("user1", "FAKEBOX");
+        final SimpleSubscription fake2 = new SimpleSubscription("fakeUser", "INBOX");
+
+        for (String user : subscriptionList.keySet()) {
+            LOG.info("Searching for all subscriptions for user:{}", user);
+            for (SimpleSubscription subscription : subscriptionList.get(user)) {
+                final Subscription result = mapper.findMailboxSubscriptionForUser(user, subscription.getMailbox());
+                assertEquals(subscription.getMailbox(), result.getMailbox());
+                assertEquals(subscription.getUser(), result.getUser());
+            }
+        }
+        assertNull(mapper.findMailboxSubscriptionForUser(fake1.getUser(), fake1.getMailbox()));
+        assertNull(mapper.findMailboxSubscriptionForUser(fake2.getUser(), fake2.getMailbox()));
+    }
+
+    /**
+     * Test of save method, of class CassandraSubscriptionMapper.
+     */
+    @Test
+    public void testSave() throws Exception {
+        LOG.info("save");
+        final List<SimpleSubscription> subscriptions = mapper.list();
+        for (String user : subscriptionList.keySet()) {
+            for (Subscription subscription : subscriptionList.get(user)) {
+                assertTrue(containSubscription(subscriptions, subscription));
+            }
+        }
+    }
+
+    /**
+     * Test of findSubscriptionsForUser method, of class
+     * CassandraSubscriptionMapper.
+     */
+    @Test
+    public void testFindSubscriptionsForUser() throws Exception {
+        LOG.info("findSubscriptionsForUser");
+        final SimpleSubscription fake1 = new SimpleSubscription("user1", "FAKEBOX");
+        final SimpleSubscription fake2 = new SimpleSubscription("fakeUser", "INBOX");
+        for (String user : subscriptionList.keySet()) {
+            LOG.info("Searching for all subscriptions for user: " + user);
+            final List<Subscription> found = mapper.findSubscriptionsForUser(user);
+            assertEquals(subscriptionList.get(user).size(), found.size());
+            // TODO: patch Subscription to implement equals
+            // assertTrue(subscriptionList.get(user).containsAll(foundSubscriptions));
+            // assertTrue(foundSubscriptions.containsAll(subscriptionList.get(user)));
+            // assertFalse(foundSubscriptions.contains(fake1));
+            // assertFalse(foundSubscriptions.contains(fake2));
+        }
+        // TODO: check what value we should return in case of no subscriptions:
+        // null or empty list
+        assertEquals(mapper.findSubscriptionsForUser(fake2.getMailbox()).size(), 0);
+
+    }
+
+    /**
+     * Test of delete method, of class CassandraSubscriptionMapper.
+     */
+    @Test
+    public void testDelete() throws Exception {
+        LOG.info("delete");
+        for (String user : subscriptionList.keySet()) {
+            LOG.info("Deleting subscriptions for user: " + user);
+            for (SimpleSubscription subscription : subscriptionList.get(user)) {
+                LOG.info("Deleting subscription : " + subscription);
+                mapper.delete(subscription);
+                assertFalse(containSubscription(mapper.list(), subscription));
+            }
+        }
+        fillSubscriptionList();
+    }
+
+    private boolean containSubscription(List<SimpleSubscription> subscriptions, Subscription subscription) {
+        for (SimpleSubscription s : subscriptions) {
+            if (subscription.getMailbox().equals(s.getMailbox()) && subscription.getUser().equals(s.getUser())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+}
-- 
2.0.3


From 56b917bd07931609fc52f74bf34203fe7bd1a458 Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 15:41:59 +0200
Subject: [PATCH 28/35] Create the spring file of Cassandra

---
 .../META-INF/spring/mailbox-cassandra.xml          | 66 ++++++++++++++++++++++
 1 file changed, 66 insertions(+)
 create mode 100644 cassandra/src/main/resources/META-INF/spring/mailbox-cassandra.xml

diff --git a/cassandra/src/main/resources/META-INF/spring/mailbox-cassandra.xml b/cassandra/src/main/resources/META-INF/spring/mailbox-cassandra.xml
new file mode 100644
index 0000000..6e803aa
--- /dev/null
+++ b/cassandra/src/main/resources/META-INF/spring/mailbox-cassandra.xml
@@ -0,0 +1,66 @@
+<?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.    
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans" 
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+          http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+    <!-- 
+      Mailbox Cassandra
+    -->
+    <bean id="cassandra-mailboxmanager" class="org.apache.james.mailbox.cassandra.CassandraMailboxManager" init-method="init">
+        <constructor-arg index="0" ref="cassandra-sessionMapperFactory"/>
+        <constructor-arg index="1" ref="authenticator"/>
+        <constructor-arg index="2" ref="cassandra-locker"/>
+    </bean>
+
+    <bean id ="cassandra-subscriptionManager" class="org.apache.james.mailbox.cassandra.CassandraSubscriptionManager">
+        <constructor-arg index="0" ref="cassandra-sessionMapperFactory"/>
+    </bean>
+
+    <bean id="cassandra-sessionMapperFactory" class="org.apache.james.mailbox.cassandra.CassandraMailboxSessionMapperFactory">
+        <constructor-arg index="0" ref="cassandra-uidProvider"/>
+        <constructor-arg index="1" ref="cassandra-modSeqProvider"/>
+        <constructor-arg index="2" ref="cassandra-session"/>
+    </bean>
+
+    <bean id="cassandra-uidProvider" class="org.apache.james.mailbox.cassandra.mail.CassandraUidProvider">
+        <constructor-arg index="0" ref="cassandra-session"/>
+    </bean>
+
+    <bean id="cassandra-modSeqProvider" class="org.apache.james.mailbox.cassandra.mail.CassandraModSeqProvider">
+        <constructor-arg index="0" ref="cassandra-session"/>
+    </bean>
+
+    <!--
+      The parameters are : the IP of a Cassendra cluster, the port, the keyspace and the replication factor
+      Default values are : localhost, 9042, apache_james and 1
+    -->
+    <bean id="cassandra-session" class="org.apache.james.mailbox.cassandra.CassandraSession">
+        <constructor-arg index="0" value="localhost"/>
+        <constructor-arg index="1" value="9042" type="int"/>
+        <constructor-arg index="2" value="apache_james"/>
+        <constructor-arg index="3" value="1" type="int"/>
+    </bean>
+
+    <alias name="jvm-locker" alias="cassandra-locker"/>
+
+</beans>
-- 
2.0.3


From 29f5f6ca348411593bdb5a508a75f81173f08db3 Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 15:45:18 +0200
Subject: [PATCH 29/35] Create the Cassandra site.xml

---
 cassandra/src/reporting-site/site.xml | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)
 create mode 100644 cassandra/src/reporting-site/site.xml

diff --git a/cassandra/src/reporting-site/site.xml b/cassandra/src/reporting-site/site.xml
new file mode 100644
index 0000000..d919164
--- /dev/null
+++ b/cassandra/src/reporting-site/site.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+    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 name="${project.name}">
+
+    <body>
+
+        <menu ref="parent" />
+        <menu ref="reports" />
+
+    </body>
+
+</project>
-- 
2.0.3


From d8c36af36d2f8937eba82bee316e2da2973b4997 Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Wed, 30 Jul 2014 16:51:10 +0200
Subject: [PATCH 30/35] Update james-mailbox/pom.xml to resolve a conflit
 between HBase and Cassandra

---
 pom.xml | 27 ++++++++++++++++++++++-----
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/pom.xml b/pom.xml
index 4c1d0dc..aad4632 100644
--- a/pom.xml
+++ b/pom.xml
@@ -52,6 +52,7 @@
         <module>api</module>
         <module>caching</module>
         <module>hbase</module>
+        <module>cassandra</module>
         <module>jcr</module>
         <module>jpa</module>
         <module>lucene</module>
@@ -61,7 +62,6 @@
         <module>spring</module>
         <module>tool</module>
         <module>zoo-seq-provider</module>
-        <module>cassandra</module>
     </modules>
 
     <scm>
@@ -115,10 +115,12 @@
         <geronimo-activation-spec.version>1.1</geronimo-activation-spec.version>
         <geronimo-javamail-mail.version>1.8.3</geronimo-javamail-mail.version>
         <apache-mailet.version>2.5.0</apache-mailet.version>
-        <slf4j.version>1.7.2</slf4j.version>
+        <slf4j.version>1.7.7</slf4j.version>
         <junit.version>4.11</junit.version>
         <jasypt.version>1.9.0</jasypt.version>
         <guava.version>13.0</guava.version>
+        <cassandra-driver-core.version>2.0.1</cassandra-driver-core.version>
+        <cassandra-unit.version>2.0.2.1</cassandra-unit.version>
     </properties>
 
     <dependencyManagement>
@@ -192,7 +194,13 @@
                 <artifactId>apache-james-mailbox-hbase</artifactId>
                 <version>${project.version}</version>
             </dependency>
-            <dependency>
+           <dependency>
+                <groupId>org.apache.james</groupId>
+                <artifactId>apache-james-mailbox-cassandra</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+
+           <dependency>
                 <groupId>org.apache.james</groupId>
                 <artifactId>apache-james-mailbox-tool</artifactId>
                 <version>${project.version}</version>
@@ -503,7 +511,6 @@
                 <artifactId>spring-orm</artifactId>
                 <version>${spring.version}</version>
             </dependency>
-
             <!--
                 END SPRING
             -->
@@ -515,6 +522,16 @@
                 <groupId>org.apache.hbase</groupId>
                 <artifactId>hbase</artifactId>
                 <version>${hbase.version}</version>
+                <exclusions>
+                    <exclusion>
+                        <groupId>org.codehaus.jackson</groupId>
+                        <artifactId>jackson-core-asl</artifactId>
+                    </exclusion>
+                    <exclusion>
+                        <groupId>org.codehaus.jackson</groupId>
+                        <artifactId>jackson-mapper-asl</artifactId>
+                    </exclusion>
+                </exclusions>
             </dependency>
             <dependency>
                 <groupId>org.apache.hbase</groupId>
@@ -537,7 +554,7 @@
             <!--
                 END HBASE/HADOOP
             -->
-        </dependencies>
+       </dependencies>
     </dependencyManagement>
 
     <build>
-- 
2.0.3


From 5120901a4232efedaf7d5620195e42229594b23c Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Thu, 31 Jul 2014 10:31:53 +0200
Subject: [PATCH 31/35] Fix problems detected by Eclipse

---
 .../mailbox/cassandra/CassandraMailboxSessionMapperFactoryTest.java   | 3 +--
 .../james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java      | 2 +-
 .../james/mailbox/cassandra/user/CassandraSubscriptionMapperTest.java | 4 +---
 3 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactoryTest.java b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactoryTest.java
index bcabfe2..b27999b 100644
--- a/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactoryTest.java
+++ b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactoryTest.java
@@ -22,7 +22,6 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
-import java.io.IOException;
 import java.util.UUID;
 
 import org.apache.james.mailbox.MailboxSession;
@@ -47,7 +46,7 @@
     private final static Logger LOG = LoggerFactory.getLogger(CassandraMailboxSessionMapperFactoryTest.class);
 
     @Before
-    public void beforeMethod() throws IOException {
+    public void beforeMethod() {
         CLUSTER.ensureAllTables();
         CLUSTER.clearAllTables();
     }
diff --git a/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java
index 0ab1be3..862d2fe 100644
--- a/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java
+++ b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java
@@ -142,7 +142,7 @@ private void testSave() throws Exception {
         LOG.info("save and mailboxFromResult");
         final List<Mailbox<UUID>> mailboxes = mapper.list();
         final SimpleMailbox<UUID> mlbx = mailboxList.get(mailboxList.size() / 2);
-        Mailbox<UUID> newValue = null;
+        Mailbox<UUID> newValue = mailboxes.get(0);
 
         for (Mailbox<UUID> mailbox : mailboxes) {
             if (mlbx.getMailboxId().equals(mailbox.getMailboxId())) {
diff --git a/cassandra/src/test/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapperTest.java b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapperTest.java
index b62b31f..dde0ece 100644
--- a/cassandra/src/test/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapperTest.java
+++ b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/user/CassandraSubscriptionMapperTest.java
@@ -29,7 +29,6 @@
 import java.util.Map;
 
 import org.apache.james.mailbox.cassandra.CassandraClusterSingleton;
-import org.apache.james.mailbox.exception.SubscriptionException;
 import org.apache.james.mailbox.store.user.model.Subscription;
 import org.apache.james.mailbox.store.user.model.impl.SimpleSubscription;
 import org.junit.Before;
@@ -62,7 +61,7 @@ public void setUp() throws Exception {
         fillSubscriptionList();
     }
 
-    private static void fillSubscriptionList() throws SubscriptionException {
+    private static void fillSubscriptionList() {
         LOG.info("Creating subscription list");
         SimpleSubscription subscription;
         String user, mailbox;
@@ -133,7 +132,6 @@ public void testSave() throws Exception {
     @Test
     public void testFindSubscriptionsForUser() throws Exception {
         LOG.info("findSubscriptionsForUser");
-        final SimpleSubscription fake1 = new SimpleSubscription("user1", "FAKEBOX");
         final SimpleSubscription fake2 = new SimpleSubscription("fakeUser", "INBOX");
         for (String user : subscriptionList.keySet()) {
             LOG.info("Searching for all subscriptions for user: " + user);
-- 
2.0.3


From cc91f0d67e0c154e736edc32df67cad7e872fddb Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Thu, 31 Jul 2014 16:35:36 +0200
Subject: [PATCH 32/35] Change scope of cassandra-unit and indent pom.xml

---
 cassandra/pom.xml | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/cassandra/pom.xml b/cassandra/pom.xml
index 5d81909..b538c44 100644
--- a/cassandra/pom.xml
+++ b/cassandra/pom.xml
@@ -65,14 +65,15 @@
             <type>test-jar</type>
         </dependency>
         <dependency>
-	  <groupId>com.datastax.cassandra</groupId>
-	  <artifactId>cassandra-driver-core</artifactId>
-	  <version>${cassandra-driver-core.version}</version>
-	</dependency>
-	<dependency>
+	        <groupId>com.datastax.cassandra</groupId>
+	        <artifactId>cassandra-driver-core</artifactId>
+	        <version>${cassandra-driver-core.version}</version>
+	    </dependency>
+	    <dependency>
     	    <groupId>org.cassandraunit</groupId>
-   	    <artifactId>cassandra-unit</artifactId>
+   	        <artifactId>cassandra-unit</artifactId>
             <version>${cassandra-unit.version}</version>
+            <scope>test</scope>
         </dependency>
     </dependencies>
 
-- 
2.0.3


From 05dd7050daa534ed41c423e6cffd47e03f5fd97d Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Fri, 1 Aug 2014 11:35:20 +0200
Subject: [PATCH 33/35] Indent the spring file of Cassandra

---
 cassandra/pom.xml | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/cassandra/pom.xml b/cassandra/pom.xml
index b538c44..aa2c240 100644
--- a/cassandra/pom.xml
+++ b/cassandra/pom.xml
@@ -65,13 +65,13 @@
             <type>test-jar</type>
         </dependency>
         <dependency>
-	        <groupId>com.datastax.cassandra</groupId>
-	        <artifactId>cassandra-driver-core</artifactId>
-	        <version>${cassandra-driver-core.version}</version>
-	    </dependency>
-	    <dependency>
+	    <groupId>com.datastax.cassandra</groupId>
+	    <artifactId>cassandra-driver-core</artifactId>
+	    <version>${cassandra-driver-core.version}</version>
+        </dependency>
+        <dependency>
     	    <groupId>org.cassandraunit</groupId>
-   	        <artifactId>cassandra-unit</artifactId>
+   	    <artifactId>cassandra-unit</artifactId>
             <version>${cassandra-unit.version}</version>
             <scope>test</scope>
         </dependency>
-- 
2.0.3


From f2dab82ed32d2b9e23e542d4b7fb134435996c52 Mon Sep 17 00:00:00 2001
From: Philippe BENOIT <pbenoit@linagora.com>
Date: Fri, 1 Aug 2014 16:17:52 +0200
Subject: [PATCH 34/35] Fix problem when fast computer tests run

---
 .../apache/james/mailbox/cassandra/CassandraClusterSingleton.java  | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraClusterSingleton.java b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraClusterSingleton.java
index 0f3119d..b97315c 100644
--- a/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraClusterSingleton.java
+++ b/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraClusterSingleton.java
@@ -53,12 +53,15 @@ public static synchronized CassandraClusterSingleton build() throws RuntimeExcep
     }
 
     private CassandraClusterSingleton() throws RuntimeException {
-        try {
+       try {
             EmbeddedCassandraServerHelper.startEmbeddedCassandra();
+            // Let Cassandra initialization before creating
+            // the session. Solve very fast computer tests run.
+            Thread.sleep(2000);
+            this.session = new CassandraSession(CLUSTER_IP, CLUSTER_PORT_TEST, KEYSPACE_NAME, DEFAULT_REPLICATION_FACTOR);
         } catch (Exception e) {
             throw new RuntimeException(e);
         }
-        this.session = new CassandraSession(CLUSTER_IP, CLUSTER_PORT_TEST, KEYSPACE_NAME, DEFAULT_REPLICATION_FACTOR);
     }
 
     /**
-- 
2.0.3


From ba817efa9b709b56fc8b3ef6e2614bf1c637bbf3 Mon Sep 17 00:00:00 2001
From: Philippe Benoit <contact@philippe-benoit.fr>
Date: Sun, 10 Aug 2014 17:52:04 +0200
Subject: [PATCH 35/35] Update licence of Cassandra classes

---
 .../james/mailbox/cassandra/CassandraSession.java  | 49 ++++++++--------------
 .../cassandra/CassandraSubscriptionManager.java    |  1 +
 .../table/CassandraMailboxCountersTable.java       | 49 ++++++++--------------
 .../cassandra/table/CassandraMailboxTable.java     | 49 ++++++++--------------
 .../cassandra/table/CassandraMessageTable.java     | 49 ++++++++--------------
 .../cassandra/table/CassandraMessageUidTable.java  | 49 ++++++++--------------
 .../table/CassandraSubscriptionTable.java          | 19 +++++++++
 7 files changed, 110 insertions(+), 155 deletions(-)

diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraSession.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraSession.java
index 795e063..b1426cb 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraSession.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraSession.java
@@ -1,34 +1,21 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * 
- * Copyright (C) 2013 Linagora
- *
- * This program is free software: you can redistribute it and/or 
- * modify it under the terms of the GNU Affero General Public License as 
- * published by the Free Software Foundation, either version 3 of the 
- * License, or (at your option) any later version, provided you comply 
- * with the Additional Terms applicable for OBM connector by Linagora 
- * pursuant to Section 7 of the GNU Affero General Public License, 
- * subsections (b), (c), and (e), pursuant to which you must notably (i) retain 
- * the “Message sent thanks to OBM, Free Communication by Linagora” 
- * signature notice appended to any and all outbound messages 
- * (notably e-mail and meeting requests), (ii) retain all hypertext links between 
- * OBM and obm.org, as well as between Linagora and linagora.com, and (iii) refrain 
- * from infringing Linagora intellectual property rights over its trademarks 
- * and commercial brands. Other Additional Terms apply, 
- * see <http://www.linagora.com/licenses/> for more details. 
- *
- * This program is distributed in the hope that it will be useful, 
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
- * for more details. 
- *
- * You should have received a copy of the GNU Affero General Public License 
- * and its applicable Additional Terms for OBM along with this program. If not, 
- * see <http://www.gnu.org/licenses/> for the GNU Affero General Public License version 3 
- * and <http://www.linagora.com/licenses/> for the Additional Terms applicable to 
- * OBM connectors. 
- * 
- * ***** END LICENSE BLOCK ***** */
+/****************************************************************
+ * 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;
 
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManager.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManager.java
index 8ba938e..c1428e9 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManager.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManager.java
@@ -16,6 +16,7 @@
  * specific language governing permissions and limitations      *
  * under the License.                                           *
  ****************************************************************/
+
 package org.apache.james.mailbox.cassandra;
 
 import org.apache.james.mailbox.MailboxSession;
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMailboxCountersTable.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMailboxCountersTable.java
index bb40fbf..175e208 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMailboxCountersTable.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMailboxCountersTable.java
@@ -1,34 +1,21 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * 
- * Copyright (C) 2013 Linagora
- *
- * This program is free software: you can redistribute it and/or 
- * modify it under the terms of the GNU Affero General Public License as 
- * published by the Free Software Foundation, either version 3 of the 
- * License, or (at your option) any later version, provided you comply 
- * with the Additional Terms applicable for OBM connector by Linagora 
- * pursuant to Section 7 of the GNU Affero General Public License, 
- * subsections (b), (c), and (e), pursuant to which you must notably (i) retain 
- * the “Message sent thanks to OBM, Free Communication by Linagora” 
- * signature notice appended to any and all outbound messages 
- * (notably e-mail and meeting requests), (ii) retain all hypertext links between 
- * OBM and obm.org, as well as between Linagora and linagora.com, and (iii) refrain 
- * from infringing Linagora intellectual property rights over its trademarks 
- * and commercial brands. Other Additional Terms apply, 
- * see <http://www.linagora.com/licenses/> for more details. 
- *
- * This program is distributed in the hope that it will be useful, 
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
- * for more details. 
- *
- * You should have received a copy of the GNU Affero General Public License 
- * and its applicable Additional Terms for OBM along with this program. If not, 
- * see <http://www.gnu.org/licenses/> for the GNU Affero General Public License version 3 
- * and <http://www.linagora.com/licenses/> for the Additional Terms applicable to 
- * OBM connectors. 
- * 
- * ***** END LICENSE BLOCK ***** */
+/****************************************************************
+ * 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;
 
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMailboxTable.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMailboxTable.java
index 02b29b3..1851eb9 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMailboxTable.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMailboxTable.java
@@ -1,34 +1,21 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * 
- * Copyright (C) 2013 Linagora
- *
- * This program is free software: you can redistribute it and/or 
- * modify it under the terms of the GNU Affero General Public License as 
- * published by the Free Software Foundation, either version 3 of the 
- * License, or (at your option) any later version, provided you comply 
- * with the Additional Terms applicable for OBM connector by Linagora 
- * pursuant to Section 7 of the GNU Affero General Public License, 
- * subsections (b), (c), and (e), pursuant to which you must notably (i) retain 
- * the “Message sent thanks to OBM, Free Communication by Linagora” 
- * signature notice appended to any and all outbound messages 
- * (notably e-mail and meeting requests), (ii) retain all hypertext links between 
- * OBM and obm.org, as well as between Linagora and linagora.com, and (iii) refrain 
- * from infringing Linagora intellectual property rights over its trademarks 
- * and commercial brands. Other Additional Terms apply, 
- * see <http://www.linagora.com/licenses/> for more details. 
- *
- * This program is distributed in the hope that it will be useful, 
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
- * for more details. 
- *
- * You should have received a copy of the GNU Affero General Public License 
- * and its applicable Additional Terms for OBM along with this program. If not, 
- * see <http://www.gnu.org/licenses/> for the GNU Affero General Public License version 3 
- * and <http://www.linagora.com/licenses/> for the Additional Terms applicable to 
- * OBM connectors. 
- * 
- * ***** END LICENSE BLOCK ***** */
+/****************************************************************
+ * 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;
 
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageTable.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageTable.java
index 78cc004..86ebe4f 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageTable.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageTable.java
@@ -1,34 +1,21 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * 
- * Copyright (C) 2013 Linagora
- *
- * This program is free software: you can redistribute it and/or 
- * modify it under the terms of the GNU Affero General Public License as 
- * published by the Free Software Foundation, either version 3 of the 
- * License, or (at your option) any later version, provided you comply 
- * with the Additional Terms applicable for OBM connector by Linagora 
- * pursuant to Section 7 of the GNU Affero General Public License, 
- * subsections (b), (c), and (e), pursuant to which you must notably (i) retain 
- * the “Message sent thanks to OBM, Free Communication by Linagora” 
- * signature notice appended to any and all outbound messages 
- * (notably e-mail and meeting requests), (ii) retain all hypertext links between 
- * OBM and obm.org, as well as between Linagora and linagora.com, and (iii) refrain 
- * from infringing Linagora intellectual property rights over its trademarks 
- * and commercial brands. Other Additional Terms apply, 
- * see <http://www.linagora.com/licenses/> for more details. 
- *
- * This program is distributed in the hope that it will be useful, 
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
- * for more details. 
- *
- * You should have received a copy of the GNU Affero General Public License 
- * and its applicable Additional Terms for OBM along with this program. If not, 
- * see <http://www.gnu.org/licenses/> for the GNU Affero General Public License version 3 
- * and <http://www.linagora.com/licenses/> for the Additional Terms applicable to 
- * OBM connectors. 
- * 
- * ***** END LICENSE BLOCK ***** */
+/****************************************************************
+ * 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;
 
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageUidTable.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageUidTable.java
index 1563fd0..0566e2b 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageUidTable.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageUidTable.java
@@ -1,34 +1,21 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * 
- * Copyright (C) 2013 Linagora
- *
- * This program is free software: you can redistribute it and/or 
- * modify it under the terms of the GNU Affero General Public License as 
- * published by the Free Software Foundation, either version 3 of the 
- * License, or (at your option) any later version, provided you comply 
- * with the Additional Terms applicable for OBM connector by Linagora 
- * pursuant to Section 7 of the GNU Affero General Public License, 
- * subsections (b), (c), and (e), pursuant to which you must notably (i) retain 
- * the “Message sent thanks to OBM, Free Communication by Linagora” 
- * signature notice appended to any and all outbound messages 
- * (notably e-mail and meeting requests), (ii) retain all hypertext links between 
- * OBM and obm.org, as well as between Linagora and linagora.com, and (iii) refrain 
- * from infringing Linagora intellectual property rights over its trademarks 
- * and commercial brands. Other Additional Terms apply, 
- * see <http://www.linagora.com/licenses/> for more details. 
- *
- * This program is distributed in the hope that it will be useful, 
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
- * for more details. 
- *
- * You should have received a copy of the GNU Affero General Public License 
- * and its applicable Additional Terms for OBM along with this program. If not, 
- * see <http://www.gnu.org/licenses/> for the GNU Affero General Public License version 3 
- * and <http://www.linagora.com/licenses/> for the Additional Terms applicable to 
- * OBM connectors. 
- * 
- * ***** END LICENSE BLOCK ***** */
+/****************************************************************
+ * 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;
 
diff --git a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraSubscriptionTable.java b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraSubscriptionTable.java
index 4b7a7c4..91b2d12 100644
--- a/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraSubscriptionTable.java
+++ b/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraSubscriptionTable.java
@@ -1,3 +1,22 @@
+/****************************************************************
+ * 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 CassandraSubscriptionTable {
-- 
2.0.3

